From 6288dd0a244e785e87b81cb1a465b7c30ea31421 Mon Sep 17 00:00:00 2001 From: cloudhead Date: Thu, 21 Mar 2024 17:02:45 +0100 Subject: [PATCH] radicle: Load inventory lazily Instead of loading the inventory cache on storage open, load it when the `inventory` function is called and the cache is `None`. --- radicle-node/src/service.rs | 1 + radicle/src/storage/git.rs | 63 +++++++++++++++++-------------------- 2 files changed, 29 insertions(+), 35 deletions(-) diff --git a/radicle-node/src/service.rs b/radicle-node/src/service.rs index 59fce3b9..e88608d5 100644 --- a/radicle-node/src/service.rs +++ b/radicle-node/src/service.rs @@ -790,6 +790,7 @@ where } Command::UpdateInventory(rid, resp) => { self.storage.insert(rid); + let synced = self .sync_inventory() .expect("Service::command: error syncing inventory"); diff --git a/radicle/src/storage/git.rs b/radicle/src/storage/git.rs index c22cd95c..f93f3684 100644 --- a/radicle/src/storage/git.rs +++ b/radicle/src/storage/git.rs @@ -89,7 +89,8 @@ impl<'a> TryFrom> for Ref { pub struct Storage { path: PathBuf, info: UserInfo, - inventory: Arc>>, + /// Inventory cache. Set to `None` until the cache is populated. + inventory: Arc>>>, } impl ReadStorage for Storage { @@ -116,24 +117,31 @@ impl ReadStorage for Storage { } fn inventory(&self) -> Result { - match self.inventory.lock() { - Ok(locked) => Ok(locked.clone()), - Err(poisoned) => { - let inv = poisoned.into_inner(); - Ok(inv.clone()) + let mut cache = self + .inventory + .lock() + .unwrap_or_else(|poisoned| poisoned.into_inner()); + + match *cache { + Some(ref cache) => Ok(cache.clone()), + None => { + let repos: BTreeSet<_> = self.public_repositories()?.collect(); + *cache = Some(repos.clone()); + Ok(repos) } } } fn insert(&self, rid: RepoId) { - match self.inventory.lock() { - Ok(mut locked) => { - locked.insert(rid); - } - Err(poisoned) => { - let mut inv = poisoned.into_inner(); - inv.insert(rid); - } + let mut repos = self + .inventory + .lock() + .unwrap_or_else(|poisoned| poisoned.into_inner()); + + // If the cache hasn't been populated yet, we don't do anything, since this repo + // will be loaded when the cache is populated. + if let Some(ref mut repos) = *repos { + repos.insert(rid); } } @@ -178,14 +186,11 @@ impl Storage { Err(err) => return Err(Error::Io(err)), Ok(()) => {} } - let storage = Self { + Ok(Self { path, info, - inventory: Arc::new(Mutex::new(BTreeSet::new())), - }; - storage.refresh()?; - - Ok(storage) + inventory: Default::default(), + }) } /// Create a [`Repository`] in a temporary directory. @@ -306,24 +311,12 @@ impl Storage { Ok(()) } - fn refresh(&self) -> Result<(), Error> { + fn public_repositories(&self) -> Result, Error> { let repos = self.repositories()?; - let rids = repos + Ok(repos .into_iter() .filter(|r| r.doc.visibility.is_public()) - .map(|r| r.rid) - .collect(); - - match self.inventory.lock() { - Ok(mut locked) => { - *locked = rids; - } - Err(poisoned) => { - let mut inv = poisoned.into_inner(); - *inv = rids; - } - } - Ok(()) + .map(|r| r.rid)) } }