···3131 let mut next_cursor: Option<Did<'static>> = None;
32323333 for item in hydrant.repos.iter_states(cursor.as_ref()) {
3434- let (did, state, _metadata) = item?;
3434+ let (did, state) = item?;
35353636 // skip repos that haven't been synced at least once
3737 let Some(commit) = state.root else {
+43-27
src/control/repos/mod.rs
···2727#[cfg(feature = "indexer")]
2828pub use indexer::*;
29293030-/// information about a tracked or known repository. returned by [`ReposControl`] methods.
3030+/// information about a repository known to hydrant. returned by [`ReposControl`] methods.
3131#[derive(Debug, Clone, serde::Serialize)]
3232pub struct RepoInfo {
3333 /// the DID of the repository.
···3737 pub status: RepoStatus,
3838 /// whether this repository is tracked or not.
3939 /// untracked repositories are not updated and they stay frozen.
4040+ ///
4141+ /// this will always be `true` in relay mode.
4042 pub tracked: bool,
4143 /// the revision of the root commit of this repository.
4244 #[serde(skip_serializing_if = "Option::is_none")]
···6668 pub last_message_at: Option<DateTime<Utc>>,
6769}
68706969-/// control over which repositories are tracked and access to their state.
7171+/// control over repositories and access to their state.
7072///
7171-/// in `filter` mode, a repo is only indexed if it either matches a signal or is
7272-/// explicitly tracked via [`ReposControl::track`]. in `full` mode all repos are
7373-/// indexed and tracking is implicit.
7373+/// in indexer mode, repositories can be explicitly tracked or untracked:
7474+/// - in `filter` mode, a repo is only indexed if it matches a signal or is
7575+/// explicitly tracked via [`ReposControl::track`]. in `full` mode all repos
7676+/// are indexed and tracking is implicit.
7777+/// - tracking a DID that hydrant has never seen enqueues an immediate backfill.
7878+/// - tracking a DID that hydrant already knows about (but has marked untracked)
7979+/// re-enqueues it for backfill.
7480///
7575-/// tracking a DID that hydrant has never seen enqueues an immediate backfill.
7676-/// tracking a DID that hydrant already knows about (but has marked untracked)
7777-/// re-enqueues it for backfill.
8181+/// in relay mode, all observed repositories are passively indexed. explicit
8282+/// tracking and backfill do not apply; [`RepoInfo::tracked`] is always `true`.
7883#[derive(Clone)]
7984pub struct ReposControl(pub(super) Arc<AppState>);
8085···8287 pub(crate) fn iter_states(
8388 &self,
8489 cursor: Option<&Did<'_>>,
8585- ) -> impl Iterator<Item = Result<(Did<'static>, RepoState<'static>, crate::types::RepoMetadata)>>
8686- {
9090+ ) -> impl Iterator<Item = Result<(Did<'static>, RepoState<'static>)>> {
8791 let start_bound = if let Some(cursor) = cursor {
8892 let did_key = keys::repo_key(cursor);
8993 std::ops::Bound::Excluded(did_key)
···9195 std::ops::Bound::Unbounded
9296 };
93979494- let state = self.0.clone();
9598 self.0
9699 .db
97100 .repos
98101 .range((start_bound, std::ops::Bound::Unbounded))
9999- .map(move |g| {
102102+ .map(|g| {
100103 let (k, v) = g.into_inner().into_diagnostic()?;
101104 let repo_state = crate::db::deser_repo_state(&v)?.into_static();
102105 let did = TrimmedDid::try_from(k.as_ref())?.to_did();
103103- let metadata_key = keys::repo_metadata_key(&did);
104104- let metadata = state
105105- .db
106106- .repo_metadata
107107- .get(&metadata_key)
108108- .into_diagnostic()?
109109- .ok_or_else(|| miette::miette!("repo metadata not found for {}", did))?;
110110- let metadata = crate::db::deser_repo_meta(metadata.as_ref())?;
111111- Ok((did, repo_state, metadata))
106106+ Ok((did, repo_state))
112107 })
113108 }
114109115110 /// iterates through all repositories, returning their state.
116111 pub fn iter(&self, cursor: Option<&Did<'_>>) -> impl Iterator<Item = Result<RepoInfo>> {
117117- self.iter_states(cursor)
118118- .map(|r| r.map(|(did, s, m)| repo_state_to_info(did, s, m.tracked)))
112112+ #[cfg(feature = "indexer")]
113113+ let state = self.0.clone();
114114+ self.iter_states(cursor).map(move |r| {
115115+ r.and_then(|(did, s)| {
116116+ #[cfg(feature = "indexer")]
117117+ let tracked = state
118118+ .db
119119+ .repo_metadata
120120+ .get(&keys::repo_metadata_key(&did))
121121+ .into_diagnostic()?
122122+ .map(|b| crate::db::deser_repo_meta(&b))
123123+ .transpose()?
124124+ .map_or(true, |m| m.tracked);
125125+ #[cfg(not(feature = "indexer"))]
126126+ let tracked = true;
127127+ Ok(repo_state_to_info(did, s, tracked))
128128+ })
129129+ })
119130 }
120131121132 /// gets a handle for a repository to read from it.
···233244 pub async fn info(&self) -> Result<Option<RepoInfo>> {
234245 let did = self.did.clone().into_static();
235246 let did_key = keys::repo_key(&did);
247247+ #[cfg(feature = "indexer")]
236248 let metadata_key = keys::repo_metadata_key(&did);
237249 let app_state = self.state.clone();
238250···243255 };
244256 let repo_state = crate::db::deser_repo_state(&state_bytes)?;
245257246246- let metadata_bytes = app_state
258258+ #[cfg(feature = "indexer")]
259259+ let tracked = app_state
247260 .db
248261 .repo_metadata
249262 .get(&metadata_key)
250263 .into_diagnostic()?
251251- .ok_or_else(|| miette::miette!("repo metadata not found for {}", did))?;
252252- let metadata = crate::db::deser_repo_meta(&metadata_bytes)?;
264264+ .map(|b| crate::db::deser_repo_meta(&b))
265265+ .transpose()?
266266+ .map_or(true, |m| m.tracked);
267267+ #[cfg(not(feature = "indexer"))]
268268+ let tracked = true;
253269254254- Ok(Some(repo_state_to_info(did, repo_state, metadata.tracked)))
270270+ Ok(Some(repo_state_to_info(did, repo_state, tracked)))
255271 })
256272 .await
257273 .into_diagnostic()?