cli: Include all nodes we can announce to on sync

Previously, we only kept tracked of unsynced nodes we were connected to.
Now we track all unsynced nodes, since announcements are relayed.

We also cap the replicas to exit earlier in case of very low replica
count.
This commit is contained in:
cloudhead 2024-03-22 16:08:37 +01:00
parent 3535170f2d
commit 98b0d55fde
No known key found for this signature in database
3 changed files with 25 additions and 12 deletions

View File

@ -186,7 +186,7 @@ fn announce_<R: ReadRepository>(
) -> Result<AnnounceResult, SyncError> { ) -> Result<AnnounceResult, SyncError> {
let rid = repo.id(); let rid = repo.id();
let doc = repo.identity_doc()?; let doc = repo.identity_doc()?;
let settings = settings.with_profile(profile); let mut settings = settings.with_profile(profile);
let unsynced: Vec<_> = if doc.visibility.is_public() { let unsynced: Vec<_> = if doc.visibility.is_public() {
// All seeds. // All seeds.
let all = node.seeds(rid)?; let all = node.seeds(rid)?;
@ -217,8 +217,8 @@ fn announce_<R: ReadRepository>(
); );
return Ok(AnnounceResult::default()); return Ok(AnnounceResult::default());
} }
// Return nodes we can announce to. // Return nodes we can announce to. They don't have to be connected directly.
all.connected() all.iter()
.filter(|s| !s.is_synced() && &s.nid != profile.id()) .filter(|s| !s.is_synced() && &s.nid != profile.id())
.map(|s| s.nid) .map(|s| s.nid)
.collect() .collect()
@ -234,6 +234,10 @@ fn announce_<R: ReadRepository>(
term::info!(&mut reporting.completion; "No seeds to announce to for {rid}. (see `rad sync status`)"); term::info!(&mut reporting.completion; "No seeds to announce to for {rid}. (see `rad sync status`)");
return Ok(AnnounceResult::default()); return Ok(AnnounceResult::default());
} }
// Cap the replicas to the maximum achievable.
// Nb. It's impossible to know if a replica follows our node. This means that if we announce
// only our refs, and the replica doesn't follow us, it won't fetch from us.
settings.replicas = settings.replicas.min(unsynced.len());
let mut spinner = term::spinner_to( let mut spinner = term::spinner_to(
format!("Found {} seed(s)..", unsynced.len()), format!("Found {} seed(s)..", unsynced.len()),

View File

@ -332,7 +332,7 @@ fn rad_id() {
let events = alice.handle.events(); let events = alice.handle.events();
bob.fork(acme, bob.home.path()).unwrap(); bob.fork(acme, bob.home.path()).unwrap();
bob.announce(acme, bob.home.path()).unwrap(); bob.announce(acme, 2, bob.home.path()).unwrap();
alice.has_inventory_of(&acme, &bob.id); alice.has_inventory_of(&acme, &bob.id);
// Alice must have Bob to try add them as a delegate // Alice must have Bob to try add them as a delegate
@ -540,7 +540,7 @@ fn rad_id_conflict() {
alice.connect(&bob).converge([&bob]); alice.connect(&bob).converge([&bob]);
bob.fork(acme, working.join("bob")).unwrap(); bob.fork(acme, working.join("bob")).unwrap();
bob.announce(acme, bob.home.path()).unwrap(); bob.announce(acme, 2, bob.home.path()).unwrap();
alice.has_inventory_of(&acme, &bob.id); alice.has_inventory_of(&acme, &bob.id);
formula(&environment.tmp(), "examples/rad-id-conflict.md") formula(&environment.tmp(), "examples/rad-id-conflict.md")
@ -982,7 +982,7 @@ fn rad_clean() {
eve.handle.fetch(acme, alice.id, DEFAULT_TIMEOUT).unwrap(); eve.handle.fetch(acme, alice.id, DEFAULT_TIMEOUT).unwrap();
bob.fork(acme, bob.home.path()).unwrap(); bob.fork(acme, bob.home.path()).unwrap();
bob.announce(acme, bob.home.path()).unwrap(); bob.announce(acme, 1, bob.home.path()).unwrap();
bob.has_inventory_of(&acme, &alice.id); bob.has_inventory_of(&acme, &alice.id);
alice.has_inventory_of(&acme, &bob.id); alice.has_inventory_of(&acme, &bob.id);
eve.has_inventory_of(&acme, &alice.id); eve.has_inventory_of(&acme, &alice.id);
@ -1116,7 +1116,7 @@ fn rad_clone_all() {
// Fork and sync repo. // Fork and sync repo.
bob.fork(acme, bob.home.path()).unwrap(); bob.fork(acme, bob.home.path()).unwrap();
bob.announce(acme, bob.home.path()).unwrap(); bob.announce(acme, 2, bob.home.path()).unwrap();
bob.has_inventory_of(&acme, &alice.id); bob.has_inventory_of(&acme, &alice.id);
alice.has_inventory_of(&acme, &bob.id); alice.has_inventory_of(&acme, &bob.id);
@ -1762,13 +1762,13 @@ fn rad_remote() {
bob.connect(&alice); bob.connect(&alice);
bob.routes_to(&[(rid, alice.id)]); bob.routes_to(&[(rid, alice.id)]);
bob.fork(rid, bob.home.path()).unwrap(); bob.fork(rid, bob.home.path()).unwrap();
bob.announce(rid, bob.home.path()).unwrap(); bob.announce(rid, 2, bob.home.path()).unwrap();
alice.has_inventory_of(&rid, &bob.id); alice.has_inventory_of(&rid, &bob.id);
eve.connect(&bob); eve.connect(&bob);
eve.routes_to(&[(rid, alice.id)]); eve.routes_to(&[(rid, alice.id)]);
eve.fork(rid, eve.home.path()).unwrap(); eve.fork(rid, eve.home.path()).unwrap();
eve.announce(rid, eve.home.path()).unwrap(); eve.announce(rid, 2, eve.home.path()).unwrap();
alice.has_inventory_of(&rid, &eve.id); alice.has_inventory_of(&rid, &eve.id);
test( test(

View File

@ -308,14 +308,23 @@ impl<G: Signer + cyphernet::Ecdh> NodeHandle<G> {
pub fn fork<P: AsRef<Path>>(&self, rid: RepoId, cwd: P) -> io::Result<()> { pub fn fork<P: AsRef<Path>>(&self, rid: RepoId, cwd: P) -> io::Result<()> {
self.clone(rid, &cwd)?; self.clone(rid, &cwd)?;
self.rad("fork", &[rid.to_string().as_str()], &cwd)?; self.rad("fork", &[rid.to_string().as_str()], &cwd)?;
self.announce(rid, &cwd)?; self.announce(rid, 1, &cwd)?;
Ok(()) Ok(())
} }
/// Announce a repo. /// Announce a repo.
pub fn announce<P: AsRef<Path>>(&self, rid: RepoId, cwd: P) -> io::Result<()> { pub fn announce<P: AsRef<Path>>(&self, rid: RepoId, replicas: usize, cwd: P) -> io::Result<()> {
self.rad("sync", &[rid.to_string().as_str(), "--announce"], cwd) self.rad(
"sync",
&[
rid.to_string().as_str(),
"--announce",
"--replicas",
replicas.to_string().as_str(),
],
cwd,
)
} }
/// Init a repo. /// Init a repo.