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

Method retain_view_changes

atomic-repository/src/repository/history.rs:602–686  ·  view source on GitHub ↗

Converge a view's own change log to a target effective set by removing** every own change absent from `target`. This is the removal half of set-based view convergence (the add half is [`insert_change`](crate::Repository::insert_change)). A durable view record declares the view's effective change set (its own changes plus everything inherited through its parent chain); any of the view's OWN change

(
        &self,
        view_name: &str,
        target: &HashSet<Hash>,
    )

Source from the content-addressed store, hash-verified

600 /// Idempotent: a view already matching its target removes nothing and
601 /// returns an empty vector. On success returns the hashes removed.
602 pub fn retain_view_changes(
603 &self,
604 view_name: &str,
605 target: &HashSet<Hash>,
606 ) -> Result<Vec<Hash>, RepositoryError> {
607 let mut txn = self
608 .pristine
609 .write_txn()
610 .map_err(|e| RepositoryError::Database(e.to_string()))?;
611
612 let mut view = txn
613 .get_view(view_name)
614 .map_err(|e| RepositoryError::Database(e.to_string()))?
615 .ok_or_else(|| RepositoryError::ViewNotFound {
616 name: view_name.to_string(),
617 })?;
618
619 // Snapshot the view's own change ids first (the iterator borrows the
620 // txn immutably; collecting frees it for the mutable `del_change`).
621 let own_ids: Vec<NodeId> = txn
622 .iter_changes(&view, 0)
623 .map_err(|e| RepositoryError::Database(e.to_string()))?
624 .map(|entry| entry.map(|(_seq, change_id, _merkle)| change_id))
625 .collect::<Result<_, _>>()
626 .map_err(|e| RepositoryError::Database(e.to_string()))?;
627
628 // Any own change whose external hash is not in the target set is stale.
629 let mut to_remove: Vec<(NodeId, Hash)> = Vec::new();
630 for change_id in own_ids {
631 let hash = txn
632 .get_external(change_id)
633 .map_err(|e| RepositoryError::Database(e.to_string()))?
634 .ok_or_else(|| {
635 RepositoryError::Database(format!(
636 "change {} has no external hash",
637 change_id.0
638 ))
639 })?;
640 if !target.contains(&hash) {
641 to_remove.push((change_id, hash));
642 }
643 }
644
645 if to_remove.is_empty() {
646 // Leave the write txn unwritten — nothing to converge.
647 return Ok(Vec::new());
648 }
649
650 // `del_change` re-derives the sequence from `change_id` on each call, so
651 // it is robust to the resequencing it performs internally; removal order
652 // does not affect the final set.
653 let mut removed = Vec::with_capacity(to_remove.len());
654 for (change_id, hash) in &to_remove {
655 let seq = txn
656 .del_change(&mut view, *change_id, hash)
657 .map_err(|e| RepositoryError::Database(e.to_string()))?;
658 if seq.is_some() {
659 removed.push(*hash);

Calls 15

write_txnMethod · 0.80
del_changeMethod · 0.80
update_viewMethod · 0.80
commitMethod · 0.80
get_viewMethod · 0.45
iter_changesMethod · 0.45
get_externalMethod · 0.45
containsMethod · 0.45
pushMethod · 0.45
is_emptyMethod · 0.45
lenMethod · 0.45
load_changeMethod · 0.45