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

Method compute_delta

atomic-remote/src/sync.rs:635–725  ·  view source on GitHub ↗

Compute the full `RemoteDelta` for a given view. This is the main entry point for sync operations. It: 1. Runs the dichotomy algorithm to find the divergence point 2. Downloads the remote's changelist from the divergence point 3. Compares "ours" (cached) vs "theirs" (actual) after divergence 4. Identifies changes to download, unrecords, and unknowns 5. Updates the local cache # Arguments `view

(
        &mut self,
        view: &str,
        local_hashes: &HashSet<String>,
    )

Source from the content-addressed store, hash-verified

633 /// * `local_hashes` - Set of change hashes present in the local repository.
634 /// Used to determine which remote changes need to be downloaded.
635 pub async fn compute_delta(
636 &mut self,
637 view: &str,
638 local_hashes: &HashSet<String>,
639 ) -> RemoteResult<RemoteDelta> {
640 // Order-invariant fast path (additive; dormant until the server
641 // advertises a SetId). If the remote publishes the SetId of its
642 // effective change set and it equals the SetId folded from our local
643 // hashes, both sides hold the same SET of changes regardless of order
644 // — we are in sync and can skip the O(log n) Merkle dichotomy and the
645 // changelist download entirely. When the field is absent (older
646 // server) or the local set cannot be folded, we fall through to the
647 // existing dichotomy with no behavior change.
648 let remote_state = self.remote.get_state(view).await?;
649 if let (Some(remote_sid), Some(local_sid)) =
650 (remote_state.set_id(), Self::local_set_id(local_hashes))
651 {
652 if remote_sid == local_sid {
653 debug!("sync: SetId match ({}), views already in sync", remote_sid);
654 return Ok(RemoteDelta::in_sync());
655 }
656 }
657
658 // Handle from-scratch sync (no cache)
659 if self.cache.is_empty() {
660 return self.compute_delta_from_scratch(view, local_hashes).await;
661 }
662
663 // Find divergence point
664 let divergence = self.dichotomy_changelist(view).await?;
665 self.stats.divergence_point = divergence;
666
667 // Collect our cached entries at or after divergence
668 let ours_ge_dichotomy: Vec<(u64, Node)> = self
669 .cache
670 .entries_from(divergence)
671 .into_iter()
672 .map(|(seq, node)| (seq, node.clone()))
673 .collect();
674
675 let ours_ge_dichotomy_set: HashSet<Node> = ours_ge_dichotomy
676 .iter()
677 .map(|(_, node)| node.clone())
678 .collect();
679
680 // Download the remote's changelist from the divergence point
681 let remote_entries = self.remote.get_changelist(view, divergence).await?;
682 self.stats.changelist_entries_fetched = remote_entries.len();
683
684 // Build "theirs" sets
685 let mut theirs_ge_dichotomy = Vec::new();
686 let mut theirs_ge_dichotomy_set = HashSet::new();
687 let mut to_download = Vec::new();
688
689 for entry in &remote_entries {
690 let node = entry.to_node();
691 theirs_ge_dichotomy_set.insert(node.clone());
692 theirs_ge_dichotomy.push((entry.sequence, node.clone()));

Callers 2

compute_pull_deltaMethod · 0.80
compute_push_deltaMethod · 0.80

Calls 15

set_idMethod · 0.80
dichotomy_changelistMethod · 0.80
entries_fromMethod · 0.80
get_changelistMethod · 0.80
to_nodeMethod · 0.80
get_stateMethod · 0.45
is_emptyMethod · 0.45
into_iterMethod · 0.45
cloneMethod · 0.45
iterMethod · 0.45

Tested by

no test coverage detected