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

Method rebuild_session_index

atomic-repository/src/repository/changes.rs:416–592  ·  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

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