Atomically increment an f64 value by `delta`. Returns the new value. - If key doesn't exist: initializes to 0.0, adds delta, returns delta. - If value is not a MessagePack float or integer: returns `TypeMismatch`. - f64 does not overflow in the traditional sense (it goes to infinity), but NaN/Infinity results are rejected as `Overflow`.
(
&mut self,
tenant_id: u64,
collection: &str,
key: &[u8],
delta: f64,
now_ms: u64,
)
| 107 | /// - f64 does not overflow in the traditional sense (it goes to infinity), |
| 108 | /// but NaN/Infinity results are rejected as `Overflow`. |
| 109 | pub fn incr_float( |
| 110 | &mut self, |
| 111 | tenant_id: u64, |
| 112 | collection: &str, |
| 113 | key: &[u8], |
| 114 | delta: f64, |
| 115 | now_ms: u64, |
| 116 | ) -> Result<f64, AtomicError> { |
| 117 | let tkey = table_key(tenant_id, collection); |
| 118 | let table = self.ensure_table(tkey, tenant_id, collection); |
| 119 | |
| 120 | let current = table.get(key, now_ms).map(|v| v.to_vec()); |
| 121 | let old_f64 = match ¤t { |
| 122 | None => 0.0f64, |
| 123 | Some(bytes) => decode_msgpack_f64(bytes)?, |
| 124 | }; |
| 125 | |
| 126 | let new_f64 = old_f64 + delta; |
| 127 | if new_f64.is_nan() || new_f64.is_infinite() { |
| 128 | return Err(AtomicError::Overflow); |
| 129 | } |
| 130 | |
| 131 | let new_bytes = zerompk::to_msgpack_vec(&new_f64).expect("f64 always serializes"); |
| 132 | // incr_float always preserves existing TTL (ttl_ms = 0). |
| 133 | self.atomic_put( |
| 134 | tenant_id, |
| 135 | collection, |
| 136 | tkey, |
| 137 | key, |
| 138 | &new_bytes, |
| 139 | 0, |
| 140 | now_ms, |
| 141 | current.is_none(), |
| 142 | ); |
| 143 | |
| 144 | Ok(new_f64) |
| 145 | } |
| 146 | |
| 147 | /// Atomic compare-and-swap. |
| 148 | /// |