From c847a16e141a57a803b270841d5af38ab56719eb Mon Sep 17 00:00:00 2001 From: Fintan Halpenny Date: Fri, 7 Feb 2025 17:22:41 +0000 Subject: [PATCH] radicle: return iterator types for db policies Instead of collecting the results and returning the collection as an iterator, introduce `FollowPolicies` and `SeedPolicies` types, which implement `Iterator`. Note that a call in `service` changed due to the lifetime borrow. It simply `collect`s into a `Vec` for the time being. --- radicle-node/src/service.rs | 5 +- radicle/src/node/policy/store.rs | 101 ++++++++++++++++++------------- 2 files changed, 63 insertions(+), 43 deletions(-) diff --git a/radicle-node/src/service.rs b/radicle-node/src/service.rs index c5eba798..dfb8b874 100644 --- a/radicle-node/src/service.rs +++ b/radicle-node/src/service.rs @@ -2476,7 +2476,10 @@ where /// Fetch all repositories that are seeded but missing from storage. fn fetch_missing_repositories(&mut self) -> Result<(), Error> { - for policy in self.policies.seed_policies()? { + // TODO(finto): could filter the policies based on the continue checks + // below, but `storage.contains` is fallible + let policies = self.policies.seed_policies()?.collect::>(); + for policy in policies { let rid = policy.rid; if !policy.is_allow() { diff --git a/radicle/src/node/policy/store.rs b/radicle/src/node/policy/store.rs index 87ff0e3b..6588581b 100644 --- a/radicle/src/node/policy/store.rs +++ b/radicle/src/node/policy/store.rs @@ -295,52 +295,21 @@ impl Store { } /// Get node follow policies. - pub fn follow_policies(&self) -> Result>, Error> { - let mut stmt = self + pub fn follow_policies(&self) -> Result, Error> { + let stmt = self .db - .prepare("SELECT id, alias, policy FROM `following`")? - .into_iter(); - let mut entries = Vec::new(); - - while let Some(Ok(row)) = stmt.next() { - let id = row.read("id"); - let alias = row.read::<&str, _>("alias").to_owned(); - let alias = alias - .is_empty() - .not() - .then_some(alias.to_owned()) - .and_then(|s| Alias::from_str(&s).ok()); - let policy = row.read::("policy"); - - entries.push(FollowPolicy { - nid: id, - alias, - policy, - }); - } - Ok(Box::new(entries.into_iter())) + .prepare("SELECT id, alias, policy FROM `following`")?; + Ok(FollowPolicies { + inner: stmt.into_iter(), + }) } - // TODO: see if sql can return iterator directly /// Get repository seed policies. - pub fn seed_policies(&self) -> Result>, Error> { - let mut stmt = self - .db - .prepare("SELECT id, scope, policy FROM `seeding`")? - .into_iter(); - let mut entries = Vec::new(); - - while let Some(Ok(row)) = stmt.next() { - let id = row.read("id"); - let policy = match row.read::("policy") { - Policy::Allow => SeedingPolicy::Allow { - scope: row.read::("scope"), - }, - Policy::Block => SeedingPolicy::Block, - }; - entries.push(SeedPolicy { rid: id, policy }); - } - Ok(Box::new(entries.into_iter())) + pub fn seed_policies(&self) -> Result, Error> { + let stmt = self.db.prepare("SELECT id, scope, policy FROM `seeding`")?; + Ok(SeedPolicies { + inner: stmt.into_iter(), + }) } pub fn nodes_by_alias<'a>(&'a self, alias: &Alias) -> Result, Error> { @@ -355,6 +324,54 @@ impl Store { } } +pub struct FollowPolicies<'a> { + inner: sql::CursorWithOwnership<'a>, +} + +impl<'a> Iterator for FollowPolicies<'a> { + type Item = FollowPolicy; + + fn next(&mut self) -> Option { + let row = self.inner.next()?; + let Ok(row) = row else { return self.next() }; + let id = row.read("id"); + let alias = row.read::<&str, _>("alias").to_owned(); + let alias = alias + .is_empty() + .not() + .then_some(alias.to_owned()) + .and_then(|s| Alias::from_str(&s).ok()); + let policy = row.read::("policy"); + + Some(FollowPolicy { + nid: id, + alias, + policy, + }) + } +} + +pub struct SeedPolicies<'a> { + inner: sql::CursorWithOwnership<'a>, +} + +impl<'a> Iterator for SeedPolicies<'a> { + type Item = SeedPolicy; + + fn next(&mut self) -> Option { + let row = self.inner.next()?; + let Ok(row) = row else { return self.next() }; + let id = row.read("id"); + let policy = match row.read::("policy") { + Policy::Allow => SeedingPolicy::Allow { + scope: row.read::("scope"), + }, + Policy::Block => SeedingPolicy::Block, + }; + Some(SeedPolicy { rid: id, policy }) + } +} + pub struct NodeAliasIter<'a> { inner: sql::CursorWithOwnership<'a>, }