Insert or update a document in the cache (write-through).
(
&mut self,
database_id: u64,
tenant_id: u64,
collection: &str,
document_id: &str,
value: &[u8],
)
| 158 | |
| 159 | /// Insert or update a document in the cache (write-through). |
| 160 | pub fn put( |
| 161 | &mut self, |
| 162 | database_id: u64, |
| 163 | tenant_id: u64, |
| 164 | collection: &str, |
| 165 | document_id: &str, |
| 166 | value: &[u8], |
| 167 | ) { |
| 168 | let key = Self::make_key(database_id, tenant_id, collection, document_id); |
| 169 | |
| 170 | // Ensure the shard exists (default weight = 1). |
| 171 | self.shards |
| 172 | .entry(database_id) |
| 173 | .or_insert_with(|| DatabaseShard::new(1)); |
| 174 | |
| 175 | // Update in-place if the key is already present. |
| 176 | { |
| 177 | let shard = self.shards.get_mut(&database_id).expect("just inserted"); |
| 178 | if let Some(existing) = shard.entries.get_mut(&key) { |
| 179 | *existing = value.to_vec(); |
| 180 | return; |
| 181 | } |
| 182 | } |
| 183 | |
| 184 | // Evict while the cache is at capacity. When the inserting shard is |
| 185 | // above its weighted fair share, continue evicting beyond the single |
| 186 | // "make room" eviction so that resident-set sizes converge toward the |
| 187 | // weight ratio under sustained pressure. |
| 188 | // |
| 189 | // The extra evictions only fire when `total >= capacity` (i.e., the |
| 190 | // cache is actually full) so the initial warm-up phase is unaffected. |
| 191 | // |
| 192 | // `hint_db_id` is passed to the eviction picker so that when two |
| 193 | // shards have identical overshoot ratios, the inserting shard is |
| 194 | // preferred — preventing a cold shard at its proportional share from |
| 195 | // being displaced in favour of the hot inserting shard. |
| 196 | if self.total >= self.capacity { |
| 197 | loop { |
| 198 | if !self.evict_from_highest_overshoot(database_id) { |
| 199 | break; |
| 200 | } |
| 201 | // After each eviction re-check whether the inserting shard is |
| 202 | // still above its weighted fair share. |
| 203 | let total_weight = self.total_weight(); |
| 204 | let fair_share = self |
| 205 | .shards |
| 206 | .get(&database_id) |
| 207 | .map(|s| { |
| 208 | (self.capacity as u64) |
| 209 | .saturating_mul(s.weight as u64) |
| 210 | .saturating_div(total_weight) as usize |
| 211 | }) |
| 212 | .unwrap_or(0); |
| 213 | let count = self |
| 214 | .shards |
| 215 | .get(&database_id) |
| 216 | .map(|s| s.entries.len()) |
| 217 | .unwrap_or(0); |