(
&mut self,
tenant_id: u64,
collection: &str,
tkey: u64,
key: &[u8],
value: &[u8],
ttl_ms: u64,
now_ms: u64,
is_new_key: bool,
| 317 | /// If `ttl_ms > 0`, sets/resets TTL. If key is new and `ttl_ms == 0`, no TTL. |
| 318 | #[allow(clippy::too_many_arguments)] |
| 319 | fn atomic_put( |
| 320 | &mut self, |
| 321 | tenant_id: u64, |
| 322 | collection: &str, |
| 323 | tkey: u64, |
| 324 | key: &[u8], |
| 325 | value: &[u8], |
| 326 | ttl_ms: u64, |
| 327 | now_ms: u64, |
| 328 | is_new_key: bool, |
| 329 | ) { |
| 330 | // Cache metadata lookup to avoid double HashMap access. |
| 331 | let old_meta = if is_new_key { |
| 332 | None |
| 333 | } else { |
| 334 | self.tables.get(&tkey).and_then(|t| t.get_entry_meta(key)) |
| 335 | }; |
| 336 | |
| 337 | // Determine the target expire_at. |
| 338 | let expire_at = if ttl_ms > 0 { |
| 339 | // Explicit TTL: set/reset. |
| 340 | now_ms + ttl_ms |
| 341 | } else if let Some(ref meta) = old_meta { |
| 342 | // Existing key, preserve TTL. |
| 343 | meta.expire_at_ms |
| 344 | } else { |
| 345 | // New key with no TTL request: persistent. |
| 346 | NO_EXPIRY |
| 347 | }; |
| 348 | |
| 349 | // Cancel old expiry before mutation. |
| 350 | if let Some(ref meta) = old_meta |
| 351 | && meta.has_ttl |
| 352 | { |
| 353 | let composite = expiry_key(tenant_id, collection, key); |
| 354 | self.expiry.cancel(&composite, meta.expire_at_ms); |
| 355 | } |
| 356 | |
| 357 | // Extract old field values BEFORE overwriting — needed so on_put can |
| 358 | // remove stale index entries when a field changes. |
| 359 | let old_fields = |
| 360 | if !is_new_key && self.indexes.get(&tkey).is_some_and(|idx| !idx.is_empty()) { |
| 361 | self.tables |
| 362 | .get(&tkey) |
| 363 | .and_then(|t| t.get(key, now_ms)) |
| 364 | .map(|old_val| { |
| 365 | super::engine_helpers::extract_all_field_values_from_msgpack(old_val) |
| 366 | }) |
| 367 | } else { |
| 368 | None |
| 369 | }; |
| 370 | |
| 371 | // Write the value. |
| 372 | let table = self.tables.get_mut(&tkey).expect("table ensured"); |
| 373 | table.put(key, value, expire_at, nodedb_types::Surrogate::ZERO); |
| 374 | |
| 375 | // Schedule new expiry if needed. |
| 376 | if expire_at != NO_EXPIRY { |
no test coverage detected