MCPcopy Create free account
hub / github.com/atomicdotdev/atomic / rebuild_session_index

Method rebuild_session_index

atomic-repository/src/repository/changes.rs:400–576  ·  view source on GitHub ↗

Rebuild session indexes from stored provenance graphs. Idempotent: existing `(session, provenance)` pairs are skipped, so a rebuilt repository never gains duplicate turns. Corrupt provenance files are reported in the result rather than aborting the rebuild. Returns `(indexed_count, skipped_existing, corrupt_count)`.

(&self)

Source from the content-addressed store, hash-verified

398 /// files are reported in the result rather than aborting the rebuild.
399 /// Returns `(indexed_count, skipped_existing, corrupt_count)`.
400 pub fn rebuild_session_index(&self) -> Result<(usize, usize, usize), RepositoryError> {
401 let mut indexed = 0usize;
402 let mut skipped = 0usize;
403 let mut corrupt = 0usize;
404
405 // Collect (hash, graph) pairs first so each write txn is short-lived.
406 let mut graphs: Vec<(Hash, atomic_core::change::ProvenanceGraph)> = Vec::new();
407 for result in self.change_store.iter_provenance_graphs() {
408 match result {
409 Ok(hash) => match self.load_provenance_graph(&hash) {
410 Ok(graph) => graphs.push((hash, graph)),
411 Err(_) => corrupt += 1,
412 },
413 Err(_) => corrupt += 1,
414 }
415 }
416
417 // Group by session. The core index derives canonical turn order from
418 // the complete set, independent of this ingestion order.
419 let mut by_session: std::collections::BTreeMap<
420 String,
421 Vec<(Hash, atomic_core::change::ProvenanceGraph)>,
422 > = std::collections::BTreeMap::new();
423 let mut head_manifests = std::collections::BTreeMap::new();
424 let mut fork_parents = std::collections::BTreeMap::new();
425 for (hash, graph) in graphs {
426 by_session
427 .entry(graph.session_id.clone())
428 .or_default()
429 .push((hash, graph));
430 }
431 // Forked children can contain only inherited turns, whose provenance
432 // files still name the parent session. Include both existing ledgers
433 // and portable manifests so rebuild can create or migrate the child.
434 {
435 let txn = self
436 .pristine
437 .read_txn()
438 .map_err(|e| RepositoryError::Database(e.to_string()))?;
439 for record in txn
440 .list_session_records()
441 .map_err(|e| RepositoryError::Database(e.to_string()))?
442 {
443 if record.turn_count > 0 {
444 by_session.entry(record.session_id).or_default();
445 }
446 }
447 for (head_session_id, head) in txn
448 .list_session_heads()
449 .map_err(|e| RepositoryError::Database(e.to_string()))?
450 {
451 match txn.get_session_manifest(&head) {
452 Ok(Some(manifest)) if manifest.session_id == head_session_id => {
453 if let (Some(parent_hash), Some(fork_turn)) =
454 (manifest.parent_session, manifest.fork_turn)
455 {
456 if let Ok(Some(parent)) = txn.get_session_manifest(&parent_hash) {
457 fork_parents.insert(

Calls 15

read_txnMethod · 0.80
list_session_recordsMethod · 0.80
list_session_headsMethod · 0.80
cmpMethod · 0.80
get_session_recordMethod · 0.80
get_session_turnsMethod · 0.80
write_txnMethod · 0.80
index_session_turnMethod · 0.80
index_inherited_turnMethod · 0.80
index_empty_sessionMethod · 0.80