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

Function merge_for_retention

nodedb-array/src/query/retention.rs:170–314  ·  view source on GitHub ↗

Merge tile-versions for one `hilbert_prefix` according to the retention policy, operating at cell granularity. `versions` contains all [`TileEntry`] records for a single `hilbert_prefix` (the caller is responsible for grouping). They may arrive in any order; this function sorts internally. `horizon_ms` is the retention boundary expressed as an absolute `system_from_ms` timestamp: versions with `

(
    versions: &[TileEntry],
    reader: &SegmentReader<'_>,
    schema: &ArraySchema,
    horizon_ms: i64,
)

Source from the content-addressed store, hash-verified

168/// `system_from_ms` timestamp: versions with `system_from_ms < horizon_ms`
169/// are outside the retention window.
170pub fn merge_for_retention(
171 versions: &[TileEntry],
172 reader: &SegmentReader<'_>,
173 schema: &ArraySchema,
174 horizon_ms: i64,
175) -> ArrayResult<RetentionMergeResult> {
176 if versions.is_empty() {
177 return Ok(RetentionMergeResult {
178 ceiling_tile: None,
179 keep_inhorizon: Vec::new(),
180 dropped_tile_ids: Vec::new(),
181 cells_carried_forward: 0,
182 });
183 }
184
185 // Partition into inside / outside by system_from_ms.
186 let mut inside: Vec<&TileEntry> = Vec::new();
187 let mut outside: Vec<&TileEntry> = Vec::new();
188 for entry in versions {
189 if entry.tile_id.system_from_ms >= horizon_ms {
190 inside.push(entry);
191 } else {
192 outside.push(entry);
193 }
194 }
195
196 // Collect TileIds for in-horizon pass-through.
197 let keep_inhorizon: Vec<TileId> = inside.iter().map(|e| e.tile_id).collect();
198
199 // If nothing is outside the horizon, there is nothing to merge.
200 if outside.is_empty() {
201 return Ok(RetentionMergeResult {
202 ceiling_tile: None,
203 keep_inhorizon,
204 dropped_tile_ids: Vec::new(),
205 cells_carried_forward: 0,
206 });
207 }
208
209 // Build the set of coord keys already covered by inside-horizon versions.
210 // Any coord present in any inside tile (regardless of RowKind) supersedes
211 // what the ceiling would contribute for that coord.
212 let mut inhorizon_coords: HashSet<Vec<u8>> = HashSet::new();
213 for entry in &inside {
214 let tile_idx = find_tile_index(reader, entry.tile_id)?;
215 let payload = reader.read_tile(tile_idx)?;
216 if let TilePayload::Sparse(ref tile) = payload {
217 for trow in decode_sparse_rows(tile)? {
218 inhorizon_coords.insert(trow.coord_key);
219 }
220 }
221 // Dense tiles inside horizon contribute no coords to the exclusion set
222 // for the ceiling (dense tiles don't participate in sparse retention
223 // merge; their coords are not relevant here).
224 }
225
226 // Walk outside-horizon versions newest → oldest, accumulating the ceiling.
227 // For each coord not yet seen, the first (newest) occurrence wins.

Calls 13

find_tile_indexFunction · 0.85
decode_sparse_rowsFunction · 0.85
collectMethod · 0.80
read_tileMethod · 0.80
entryMethod · 0.80
push_rowMethod · 0.80
is_emptyMethod · 0.45
pushMethod · 0.45
iterMethod · 0.45
insertMethod · 0.45
containsMethod · 0.45
cmpMethod · 0.45