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`.
This commit is contained in:
cloudhead 2024-03-21 17:02:45 +01:00
parent 057af40ea3
commit 6288dd0a24
No known key found for this signature in database
2 changed files with 29 additions and 35 deletions

View File

@ -790,6 +790,7 @@ where
} }
Command::UpdateInventory(rid, resp) => { Command::UpdateInventory(rid, resp) => {
self.storage.insert(rid); self.storage.insert(rid);
let synced = self let synced = self
.sync_inventory() .sync_inventory()
.expect("Service::command: error syncing inventory"); .expect("Service::command: error syncing inventory");

View File

@ -89,7 +89,8 @@ impl<'a> TryFrom<git2::Reference<'a>> for Ref {
pub struct Storage { pub struct Storage {
path: PathBuf, path: PathBuf,
info: UserInfo, info: UserInfo,
inventory: Arc<Mutex<BTreeSet<RepoId>>>, /// Inventory cache. Set to `None` until the cache is populated.
inventory: Arc<Mutex<Option<BTreeSet<RepoId>>>>,
} }
impl ReadStorage for Storage { impl ReadStorage for Storage {
@ -116,24 +117,31 @@ impl ReadStorage for Storage {
} }
fn inventory(&self) -> Result<Inventory, Error> { fn inventory(&self) -> Result<Inventory, Error> {
match self.inventory.lock() { let mut cache = self
Ok(locked) => Ok(locked.clone()), .inventory
Err(poisoned) => { .lock()
let inv = poisoned.into_inner(); .unwrap_or_else(|poisoned| poisoned.into_inner());
Ok(inv.clone())
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) { fn insert(&self, rid: RepoId) {
match self.inventory.lock() { let mut repos = self
Ok(mut locked) => { .inventory
locked.insert(rid); .lock()
} .unwrap_or_else(|poisoned| poisoned.into_inner());
Err(poisoned) => {
let mut inv = poisoned.into_inner(); // If the cache hasn't been populated yet, we don't do anything, since this repo
inv.insert(rid); // 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)), Err(err) => return Err(Error::Io(err)),
Ok(()) => {} Ok(()) => {}
} }
let storage = Self { Ok(Self {
path, path,
info, info,
inventory: Arc::new(Mutex::new(BTreeSet::new())), inventory: Default::default(),
}; })
storage.refresh()?;
Ok(storage)
} }
/// Create a [`Repository`] in a temporary directory. /// Create a [`Repository`] in a temporary directory.
@ -306,24 +311,12 @@ impl Storage {
Ok(()) Ok(())
} }
fn refresh(&self) -> Result<(), Error> { fn public_repositories(&self) -> Result<impl Iterator<Item = RepoId>, Error> {
let repos = self.repositories()?; let repos = self.repositories()?;
let rids = repos Ok(repos
.into_iter() .into_iter()
.filter(|r| r.doc.visibility.is_public()) .filter(|r| r.doc.visibility.is_public())
.map(|r| r.rid) .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(())
} }
} }