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
be up to date and so we will see the same message.
be up to date.
```
$ 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:
@ -51,7 +51,7 @@ $ rad sync --fetch --announce
✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6Mkux1…nVhib7Z..
✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6Mkt67…v4N1tRk..
✓ 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:

View File

@ -328,16 +328,46 @@ fn sync_status(rid: Id, node: &mut Node) -> anyhow::Result<()> {
fn announce_refs(
rid: Id,
_mode: RepoSync,
mode: RepoSync,
timeout: time::Duration,
mut node: Node,
profile: &Profile,
) -> anyhow::Result<()> {
let repo = profile.storage.repository(rid)?;
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)?;
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 {
node.sessions()?
.into_iter()
@ -346,13 +376,13 @@ fn announce_refs(
.collect()
};
if connected.is_empty() {
term::info!("Not connected to any seeds.");
if unsynced.is_empty() {
term::info!("Not connected to any seeds for {rid}.");
return Ok(());
}
let mut spinner = term::spinner(format!("Syncing with {} node(s)..", connected.len()));
let result = node.announce(rid, connected, timeout, |event| match event {
let mut spinner = term::spinner(format!("Syncing with {} node(s)..", unsynced.len()));
let result = node.announce(rid, unsynced, timeout, |event| match event {
node::AnnounceEvent::Announced => {}
node::AnnounceEvent::RefsSynced { remote } => {
spinner.message(format!("Synced with {remote}.."));

View File

@ -460,6 +460,11 @@ impl Seed {
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(
nid: NodeId,
addrs: Vec<KnownAddress>,
@ -497,22 +502,30 @@ impl Seeds {
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.
/// Note that the disconnected seeds may be in a "connecting" state.
pub fn partition(&self) -> (Vec<Seed>, Vec<Seed>) {
self.0
.shuffled()
.map(|(_, v)| v)
.cloned()
.partition(|s| s.is_connected())
self.iter().cloned().partition(|s| s.is_connected())
}
/// Return connected seeds.
pub fn connected(&self) -> impl Iterator<Item = &Seed> {
self.0
.shuffled()
.map(|(_, v)| v)
.filter(|s| s.is_connected())
self.iter().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.