diff --git a/src/app/sync.rs b/src/app/sync.rs index 478eda3..1c4461e 100644 --- a/src/app/sync.rs +++ b/src/app/sync.rs @@ -83,73 +83,14 @@ impl AppaService { .await; let mut synchronized_count = 0; for (peer, response) in peer_summaries { - let PeerSummaryResponse { - summary, - roster: remote_roster, - peer_endpoints: remote_peers, - capability: remote_capability, - } = match response { - Ok(response) => response, - Err(error) => { - tracing::debug!(folder = %folder.name, peer = %peer.id, %error, "peer is unavailable; continuing with other peers"); - continue; - } - }; - if summary.folder_id != folder.id { - tracing::warn!(folder = %folder.name, peer = %peer.id, "peer returned a summary for another folder"); - continue; - } - self.save_peer_response( - folder, - &peer, - &remote_roster, - remote_peers, - &remote_capability, - )?; - if summary.root_hash == manifest_root_hash(&local_manifest)? { - tracing::debug!(folder = %folder.name, peer = %peer.id, "Folder roots match; skipping manifest transfer"); - continue; - } - let remote = match node - .request_manifest_delta( - peer.clone(), - folder.id, - folder.capability.clone(), - self.state_store.join_invite(folder.id)?, - &local_manifest, - ) - .await - { - Ok(manifest) => manifest, - Err(error) => { - tracing::debug!(folder = %folder.name, peer = %peer.id, %error, "peer did not provide its changed entries"); - continue; - } - }; - if remote.folder_id != folder.id { - tracing::warn!(folder = %folder.name, peer = %peer.id, "peer returned a manifest for another folder"); - continue; - } - if !folder.mode.can_receive() { - tracing::debug!(folder = %folder.name, "Ignoring remote changes for send-only folder"); + let Some((merged_manifest, synchronized_files)) = self + .synchronize_peer(&context, &local_manifest, peer, response) + .await? + else { continue; - } - let (merged, count) = match apply_remote_manifest( - &context, - &local_manifest, - &remote, - peer.clone(), - ) - .await - { - Ok(result) => result, - Err(error) => { - tracing::warn!(folder = %folder.name, peer = %peer.id, %error, "could not apply peer manifest"); - continue; - } }; - local_manifest = merged; - synchronized_count += count; + local_manifest = merged_manifest; + synchronized_count += synchronized_files; self.state_store.save_manifest(&local_manifest)?; node.publish_manifest(local_manifest.clone()).await?; } @@ -238,6 +179,69 @@ impl AppaService { } Ok(()) } + + async fn synchronize_peer( + &self, + context: &SyncContext<'_>, + local_manifest: &crate::domain::Manifest, + peer: iroh::EndpointAddr, + response: anyhow::Result, + ) -> AppResult> { + let folder = context.folder; + let PeerSummaryResponse { + summary, + roster, + peer_endpoints, + capability, + } = match response { + Ok(response) => response, + Err(error) => { + tracing::debug!(folder = %folder.name, peer = %peer.id, %error, "peer is unavailable; continuing with other peers"); + return Ok(None); + } + }; + if summary.folder_id != folder.id { + tracing::warn!(folder = %folder.name, peer = %peer.id, "peer returned a summary for another folder"); + return Ok(None); + } + self.save_peer_response(folder, &peer, &roster, peer_endpoints, &capability)?; + if summary.root_hash == manifest_root_hash(local_manifest)? { + tracing::debug!(folder = %folder.name, peer = %peer.id, "Folder roots match; skipping manifest transfer"); + return Ok(None); + } + let remote_manifest = match context + .node + .request_manifest_delta( + peer.clone(), + folder.id, + folder.capability.clone(), + self.state_store.join_invite(folder.id)?, + local_manifest, + ) + .await + { + Ok(manifest) => manifest, + Err(error) => { + tracing::debug!(folder = %folder.name, peer = %peer.id, %error, "peer did not provide its changed entries"); + return Ok(None); + } + }; + if remote_manifest.folder_id != folder.id { + tracing::warn!(folder = %folder.name, peer = %peer.id, "peer returned a manifest for another folder"); + return Ok(None); + } + if !folder.mode.can_receive() { + tracing::debug!(folder = %folder.name, "Ignoring remote changes for send-only folder"); + return Ok(None); + } + match apply_remote_manifest(context, local_manifest, &remote_manifest, peer.clone()).await { + Ok(result) => Ok(Some(result)), + Err(error) => { + tracing::warn!(folder = %folder.name, peer = %peer.id, %error, "could not apply peer manifest"); + Ok(None) + } + } + } } async fn request_peer_summaries(