Radish alpha
r
rad:z2UcCU1LgMshWvXj6hXSDDrwB8q8M
Radicle Job Collaborative Object
Radicle
Git
feat: add function to announce changes to other nodes
Open liw opened 9 months ago

Most users of applications that make job COB changes will probably want them announced sooner rather than later. It’d be good to avoid having to duplicate the announcement code in every such application.

Signed-off-by: Lars Wirzenius liw@liw.fi

2 files changed +61 -3 574129a2 4eaf59cd
modified src/error.rs
@@ -47,3 +47,17 @@ pub enum Apply {
    #[error(transparent)]
    Op(#[from] cob::op::OpEncodingError),
}
+

+
/// Errors that can occur when announcing changes to other nodes.
+
#[derive(Debug, Error)]
+
pub enum Announce {
+
    /// Getting seeds for a repository.
+
    #[error("failed to get seeds for a repository")]
+
    Seeds(#[source] radicle::node::Error),
+
    /// Creating a COB announcer.
+
    #[error("failed to create a COB announcer")]
+
    Announcer,
+
    /// Announcing changes.
+
    #[error("failed to announce COB change")]
+
    Announce(#[source] radicle::node::Error),
+
}
modified src/lib.rs
@@ -49,10 +49,11 @@

#![deny(missing_docs)]

-
use std::collections::HashMap;
+
use std::collections::{BTreeSet, HashMap};
use std::fmt;
use std::ops::{Deref, DerefMut};
use std::str::FromStr;
+
use std::time::Duration;

use indexmap::IndexMap;
use once_cell::sync::Lazy;
@@ -61,8 +62,11 @@ use radicle::cob::{self, store, EntryId, Evaluate, ObjectId, Op, TypeName};
use radicle::crypto;
use radicle::crypto::signature::Signer;
use radicle::node::device::Device;
-
use radicle::node::NodeId;
-
use radicle::prelude::ReadRepository;
+
use radicle::node::{
+
    sync::{Announcer, AnnouncerConfig, ReplicationFactor},
+
    Handle, Node, NodeId,
+
};
+
use radicle::prelude::{Profile, ReadRepository, RepoId};
use radicle::storage::{RepositoryError, SignRepository, WriteRepository};
use radicle::{cob::store::CobAction, git::Oid};
use serde::{Deserialize, Serialize};
@@ -817,6 +821,46 @@ where
    }
}

+
/// Ask node to announce any changes to a repository to other nodes.
+
///
+
/// Call this after making changes to COBs so that the changes get
+
/// propagated to the Radicle network as soon as possible.
+
pub fn announce(profile: &Profile, repo_id: RepoId) -> Result<(), error::Announce> {
+
    const TIMEOUT: Duration = Duration::from_millis(5000);
+

+
    let mut node = Node::new(profile.home.socket());
+

+
    let (synced, unsynced) = node
+
        .seeds(repo_id)
+
        .map_err(error::Announce::Seeds)?
+
        .iter()
+
        .fold(
+
            (BTreeSet::new(), BTreeSet::new()),
+
            |(mut synced, mut unsynced), seed| {
+
                if seed.is_synced() {
+
                    synced.insert(seed.nid);
+
                } else {
+
                    unsynced.insert(seed.nid);
+
                }
+
                (synced, unsynced)
+
            },
+
        );
+

+
    let announcer = Announcer::new(AnnouncerConfig::public(
+
        *profile.id(),
+
        ReplicationFactor::MustReach(1),
+
        BTreeSet::new(),
+
        synced,
+
        unsynced,
+
    ))
+
    .map_err(|_| error::Announce::Announcer)?;
+

+
    node.announce(repo_id, TIMEOUT, announcer, |_, _| ())
+
        .map_err(error::Announce::Announce)?;
+

+
    Ok(())
+
}
+

#[cfg(test)]
#[allow(clippy::unwrap_used)]
mod test {