(
&self,
object_type: &str,
id: &str,
name: &str,
payload: &[u8],
labels: Option<&str>,
condition: WriteCondition,
)
| 91 | } |
| 92 | |
| 93 | pub async fn put_if( |
| 94 | &self, |
| 95 | object_type: &str, |
| 96 | id: &str, |
| 97 | name: &str, |
| 98 | payload: &[u8], |
| 99 | labels: Option<&str>, |
| 100 | condition: WriteCondition, |
| 101 | ) -> PersistenceResult<WriteResult> { |
| 102 | let now_ms = current_time_ms(); |
| 103 | let labels_jsonb: Option<serde_json::Value> = labels |
| 104 | .map(serde_json::from_str) |
| 105 | .transpose() |
| 106 | .map_err(|e| PersistenceError::Encode(format!("invalid labels JSON: {e}")))?; |
| 107 | |
| 108 | match condition { |
| 109 | WriteCondition::MustCreate => { |
| 110 | // Insert only - fail if object exists |
| 111 | let row = sqlx::query( |
| 112 | r" |
| 113 | INSERT INTO objects (object_type, id, name, payload, created_at_ms, updated_at_ms, labels, resource_version) |
| 114 | VALUES ($1, $2, $3, $4, $5, $5, COALESCE($6, '{}'::jsonb), 1) |
| 115 | RETURNING resource_version, created_at_ms, updated_at_ms |
| 116 | ", |
| 117 | ) |
| 118 | .bind(object_type) |
| 119 | .bind(id) |
| 120 | .bind(name) |
| 121 | .bind(payload) |
| 122 | .bind(now_ms) |
| 123 | .bind(labels_jsonb) |
| 124 | .fetch_one(&self.pool) |
| 125 | .await |
| 126 | .map_err(|e| map_db_error(&e))?; |
| 127 | |
| 128 | let resource_version_i64: i64 = row.try_get("resource_version").unwrap_or(1); |
| 129 | Ok(WriteResult { |
| 130 | resource_version: resource_version_i64.max(1).cast_unsigned(), |
| 131 | created_at_ms: row.get("created_at_ms"), |
| 132 | updated_at_ms: row.get("updated_at_ms"), |
| 133 | }) |
| 134 | } |
| 135 | WriteCondition::MatchResourceVersion(expected_version) => { |
| 136 | // Update with version check using RETURNING |
| 137 | let row_result = sqlx::query( |
| 138 | r" |
| 139 | UPDATE objects |
| 140 | SET payload = $4, labels = COALESCE($5, '{}'::jsonb), updated_at_ms = $6, resource_version = resource_version + 1 |
| 141 | WHERE object_type = $1 AND id = $2 AND resource_version = $3 |
| 142 | RETURNING resource_version, created_at_ms, updated_at_ms |
| 143 | ", |
| 144 | ) |
| 145 | .bind(object_type) |
| 146 | .bind(id) |
| 147 | .bind(i64::try_from(expected_version).unwrap_or(i64::MAX)) |
| 148 | .bind(payload) |
| 149 | .bind(labels_jsonb) |
| 150 | .bind(now_ms) |
nothing calls this directly
no test coverage detected