MCPcopy Create free account
hub / github.com/NodeDB-Lab/nodedb / cas

Method cas

nodedb/src/engine/kv/engine_atomic.rs:152–235  ·  view source on GitHub ↗

Atomic compare-and-swap. If current value equals `expected`, sets to `new_value` and returns success. If current value differs, returns the actual current value. If key doesn't exist and `expected` is empty, creates the key (create-if-not-exists).

(
        &mut self,
        tenant_id: u64,
        collection: &str,
        key: &[u8],
        expected: &[u8],
        new_value: &[u8],
        now_ms: u64,
    )

Source from the content-addressed store, hash-verified

150 /// If current value differs, returns the actual current value.
151 /// If key doesn't exist and `expected` is empty, creates the key (create-if-not-exists).
152 pub fn cas(
153 &mut self,
154 tenant_id: u64,
155 collection: &str,
156 key: &[u8],
157 expected: &[u8],
158 new_value: &[u8],
159 now_ms: u64,
160 ) -> CasResult {
161 let tkey = table_key(tenant_id, collection);
162 let table = self.ensure_table(tkey, tenant_id, collection);
163
164 let current = table.get(key, now_ms).map(|v| v.to_vec());
165
166 // For typed KV entries (maps), compare against the first non-key string field.
167 let matches = match &current {
168 None => expected.is_empty(),
169 Some(v) => {
170 if v.as_slice() == expected {
171 true
172 } else if let Ok(nodedb_types::Value::Object(map)) =
173 nodedb_types::value_from_msgpack(v)
174 {
175 // Compare expected string against the first non-key string field.
176 let expected_str = String::from_utf8_lossy(expected);
177 map.iter().any(|(k, val)| {
178 k != "key"
179 && matches!(val, nodedb_types::Value::String(s) if s == expected_str.as_ref())
180 })
181 } else {
182 false
183 }
184 }
185 };
186
187 if matches {
188 // For typed KV: update the field value within the map.
189 let write_bytes = if let Some(ref cur) = current
190 && let Ok(nodedb_types::Value::Object(mut map)) =
191 nodedb_types::value_from_msgpack(cur)
192 && map.len() > 1
193 {
194 let new_str = String::from_utf8_lossy(new_value).to_string();
195 let mut updated = false;
196 for (k, v) in map.iter_mut() {
197 if k == "key" {
198 continue;
199 }
200 if matches!(v, nodedb_types::Value::String(_)) {
201 *v = nodedb_types::Value::String(new_str.clone());
202 updated = true;
203 break;
204 }
205 }
206 if updated {
207 nodedb_types::value_to_msgpack(&nodedb_types::Value::Object(map))
208 .unwrap_or_else(|_| new_value.to_vec())
209 } else {

Callers 4

execute_kv_casMethod · 0.80
cas_create_if_not_existsFunction · 0.80
cas_successFunction · 0.80
cas_failureFunction · 0.80

Calls 14

table_keyFunction · 0.85
value_from_msgpackFunction · 0.85
value_to_msgpackFunction · 0.85
ensure_tableMethod · 0.80
to_stringMethod · 0.80
iter_mutMethod · 0.80
atomic_putMethod · 0.80
getMethod · 0.45
to_vecMethod · 0.45
is_emptyMethod · 0.45
as_sliceMethod · 0.45
iterMethod · 0.45

Tested by 3

cas_create_if_not_existsFunction · 0.64
cas_successFunction · 0.64
cas_failureFunction · 0.64