cli: Don't announce if already in sync

In this change, we check whether we are in sync with a node before
announcing refs to it.
This commit is contained in:
cloudhead 2023-11-17 17:22:44 +01:00
parent d4ec2176bb
commit b140d8580f
No known key found for this signature in database
3 changed files with 62 additions and 19 deletions

View File

@ -28,11 +28,11 @@ $ rad sync --announce
``` ```
If we try to sync again after the nodes have synced, we will already If we try to sync again after the nodes have synced, we will already
be up to date and so we will see the same message. be up to date.
``` ```
$ rad sync --announce $ rad sync --announce
Synced with 2 node(s) Nothing to announce, already in sync with network (see `rad sync status`)
``` ```
We can also use the `--fetch` option to only fetch objects: We can also use the `--fetch` option to only fetch objects:
@ -51,7 +51,7 @@ $ rad sync --fetch --announce
✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6Mkux1…nVhib7Z.. ✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6Mkux1…nVhib7Z..
✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6Mkt67…v4N1tRk.. ✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6Mkt67…v4N1tRk..
✓ Fetched repository from 2 seed(s) ✓ Fetched repository from 2 seed(s)
Synced with 2 node(s) Nothing to announce, already in sync with network (see `rad sync status`)
``` ```
It's also possible to use the `--seed` flag to only sync with a specific node: It's also possible to use the `--seed` flag to only sync with a specific node:

View File

@ -328,16 +328,46 @@ fn sync_status(rid: Id, node: &mut Node) -> anyhow::Result<()> {
fn announce_refs( fn announce_refs(
rid: Id, rid: Id,
_mode: RepoSync, mode: RepoSync,
timeout: time::Duration, timeout: time::Duration,
mut node: Node, mut node: Node,
profile: &Profile, profile: &Profile,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let repo = profile.storage.repository(rid)?; let repo = profile.storage.repository(rid)?;
let doc = repo.identity_doc()?; let doc = repo.identity_doc()?;
let connected: Vec<_> = if doc.visibility.is_public() { let unsynced: Vec<_> = if doc.visibility.is_public() {
let seeds = node.seeds(rid)?; let seeds = node.seeds(rid)?;
seeds.connected().map(|s| s.nid).collect() let synced = seeds.iter().filter(|s| s.is_synced());
match mode {
RepoSync::Seeds(seeds) => {
let synced = synced.map(|s| s.nid).collect::<Vec<_>>();
if seeds.iter().all(|s| synced.contains(s)) {
term::success!(
"Already in sync with the specified seed(s) (see `rad sync status`)"
);
return Ok(());
}
}
RepoSync::Replicas(replicas) => {
let count = synced.count();
if count >= seeds.len() {
term::success!(
"Nothing to announce, already in sync with network (see `rad sync status`)"
);
return Ok(());
}
if count >= replicas {
term::success!("Nothing to announce, already in sync with {count} seed(s) (see `rad sync status`)");
return Ok(());
}
}
}
seeds
.connected()
.filter(|s| !s.is_synced())
.map(|s| s.nid)
.collect()
} else { } else {
node.sessions()? node.sessions()?
.into_iter() .into_iter()
@ -346,13 +376,13 @@ fn announce_refs(
.collect() .collect()
}; };
if connected.is_empty() { if unsynced.is_empty() {
term::info!("Not connected to any seeds."); term::info!("Not connected to any seeds for {rid}.");
return Ok(()); return Ok(());
} }
let mut spinner = term::spinner(format!("Syncing with {} node(s)..", connected.len())); let mut spinner = term::spinner(format!("Syncing with {} node(s)..", unsynced.len()));
let result = node.announce(rid, connected, timeout, |event| match event { let result = node.announce(rid, unsynced, timeout, |event| match event {
node::AnnounceEvent::Announced => {} node::AnnounceEvent::Announced => {}
node::AnnounceEvent::RefsSynced { remote } => { node::AnnounceEvent::RefsSynced { remote } => {
spinner.message(format!("Synced with {remote}..")); spinner.message(format!("Synced with {remote}.."));

View File

@ -460,6 +460,11 @@ impl Seed {
matches!(self.state, Some(State::Connected { .. })) matches!(self.state, Some(State::Connected { .. }))
} }
/// Check if this seed is in sync with us.
pub fn is_synced(&self) -> bool {
matches!(self.sync, Some(SyncStatus::Synced { .. }))
}
pub fn new( pub fn new(
nid: NodeId, nid: NodeId,
addrs: Vec<KnownAddress>, addrs: Vec<KnownAddress>,
@ -497,22 +502,30 @@ impl Seeds {
self.0.contains_key(nid) self.0.contains_key(nid)
} }
/// Number of seeds.
pub fn len(&self) -> usize {
self.0.len()
}
/// Check if there are any seeds.
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
/// Partitions the list of seeds into connected and disconnected seeds. /// Partitions the list of seeds into connected and disconnected seeds.
/// Note that the disconnected seeds may be in a "connecting" state. /// Note that the disconnected seeds may be in a "connecting" state.
pub fn partition(&self) -> (Vec<Seed>, Vec<Seed>) { pub fn partition(&self) -> (Vec<Seed>, Vec<Seed>) {
self.0 self.iter().cloned().partition(|s| s.is_connected())
.shuffled()
.map(|(_, v)| v)
.cloned()
.partition(|s| s.is_connected())
} }
/// Return connected seeds. /// Return connected seeds.
pub fn connected(&self) -> impl Iterator<Item = &Seed> { pub fn connected(&self) -> impl Iterator<Item = &Seed> {
self.0 self.iter().filter(|s| s.is_connected())
.shuffled() }
.map(|(_, v)| v)
.filter(|s| s.is_connected()) /// Return all seeds.
pub fn iter(&self) -> impl Iterator<Item = &Seed> {
self.0.shuffled().map(|(_, v)| v)
} }
/// Check if a seed is connected. /// Check if a seed is connected.