Skip to main content

common/peer/sync/
mod.rs

1//! Sync provider abstraction and job execution
2//!
3//! This module defines the sync provider trait and job types. Each job type
4//! has its own module with execution logic that can be reused by peers.
5
6use anyhow::Result;
7use async_trait::async_trait;
8use thiserror::Error;
9
10use crate::bucket_log::BucketLogProvider;
11use crate::linked_data::Link;
12
13/// Errors that can occur during provenance verification.
14#[derive(Debug, Error)]
15pub enum ProvenanceError {
16    #[error("invalid signature on manifest")]
17    InvalidSignature,
18    #[error("author not in manifest shares")]
19    AuthorNotInShares,
20    #[error("author does not have write permission")]
21    AuthorNotWriter,
22    #[error("invalid manifest in chain at {link}: {reason}")]
23    InvalidManifestInChain { link: Link, reason: String },
24    #[error("{0}")]
25    Other(#[from] anyhow::Error),
26}
27
28pub mod download_pins;
29pub mod ping_peer;
30pub mod sync_bucket;
31
32// Re-export job types, helpers, and errors
33pub use download_pins::DownloadPinsJob;
34pub use ping_peer::PingPeerJob;
35pub use sync_bucket::{SyncBucketJob, SyncTarget};
36
37/// Background sync job types
38///
39/// These represent the different kinds of background work that can be dispatched.
40#[derive(Debug, Clone)]
41pub enum SyncJob {
42    /// Sync a bucket from a remote peer
43    SyncBucket(SyncBucketJob),
44    /// Download pins from remote peers
45    DownloadPins(DownloadPinsJob),
46    /// Ping a peer to check bucket sync status
47    PingPeer(PingPeerJob),
48}
49
50/// Execute a sync job by calling the appropriate module's execute function
51///
52/// This is a helper function that dispatches to the per-job-type execution logic.
53/// Both synchronous and queued providers can use this.
54pub async fn execute_job<L>(peer: &crate::peer::Peer<L>, job: SyncJob) -> Result<()>
55where
56    L: BucketLogProvider + Clone + Send + Sync + 'static,
57    L::Error: std::error::Error + Send + Sync + 'static,
58{
59    match job {
60        SyncJob::DownloadPins(job) => download_pins::execute(peer, job).await,
61        SyncJob::SyncBucket(job) => sync_bucket::execute(peer, job).await,
62        SyncJob::PingPeer(job) => ping_peer::execute(peer, job).await,
63    }
64}
65
66/// Trait for sync provider implementations
67///
68/// This trait abstracts WHEN and WHERE sync jobs are executed. The actual sync
69/// logic lives in the per-job modules. Implementations decide the execution
70/// context:
71///
72/// - **Synchronous**: Execute immediately by calling execute_job directly
73/// - **Queued**: Send to a channel for background worker processing
74/// - **Actor-based**: Send to an actor mailbox for processing
75///
76/// This allows minimal peers to use simple synchronous execution, while complex
77/// applications can decouple sync jobs from protocol handlers using queues.
78#[async_trait]
79pub trait SyncProvider<L>: Send + Sync + std::fmt::Debug
80where
81    L: BucketLogProvider + Clone + Send + Sync + 'static,
82    L::Error: std::error::Error + Send + Sync + 'static,
83{
84    /// Execute a sync job with the given peer
85    ///
86    /// Implementations decide when and where this runs. The job execution logic
87    /// is provided by the execute_job helper and per-job modules.
88    async fn execute(&self, peer: &crate::peer::Peer<L>, job: SyncJob) -> Result<()>;
89}