···11use crate::db::{self, keys};
22+use crate::filter::FilterMode;
23use crate::ingest::{BufferRx, IngestMessage};
34use crate::ops;
45use crate::resolver::{NoSigningKeyError, ResolverError};
···501502 repo_state,
502503 &commit,
503504 Self::fetch_key(ctx, did)?.as_ref(),
505505+ &ctx.state.filter.load(),
504506 )?;
505507 let repo_state = res.repo_state;
506508 *ctx.added_blocks += res.blocks_count;
···526528 ) -> Result<RepoProcessResult<'s, 'c>, IngestError> {
527529 let repo_key = keys::repo_key(&did);
528530 let Some(state_bytes) = ctx.state.db.repos.get(&repo_key).into_diagnostic()? else {
529529- // we don't know this repo, but we are receiving events for it
530530- // this means we should backfill it before processing its events
531531+ let filter = ctx.state.filter.load();
532532+533533+ if filter.mode == FilterMode::Signal {
534534+ let commit = match msg {
535535+ SubscribeReposMessage::Commit(c) => c,
536536+ _ => return Ok(RepoProcessResult::Syncing(None)),
537537+ };
538538+ let touches_signal = commit.ops.iter().any(|op| {
539539+ op.path
540540+ .split_once('/')
541541+ .map(|(col, _)| filter.matches_signal(col))
542542+ .unwrap_or(false)
543543+ });
544544+ if !touches_signal {
545545+ return Ok(RepoProcessResult::Syncing(None));
546546+ }
547547+ }
548548+531549 debug!("discovered new account {did} from firehose, queueing backfill");
532550533551 let repo_state = RepoState::backfilling(rand::rng().next_u64());
534534- // using a separate batch here since we want to make it known its being backfilled
535535- // immediately. we could use the batch for the unit of work we are doing but
536536- // then we wouldn't be able to start backfilling until the unit of work is done
537552 let mut batch = ctx.state.db.inner.batch();
538553 batch.insert(
539554 &ctx.state.db.repos,
+1
src/lib.rs
···33pub mod config;
44pub mod crawler;
55pub mod db;
66+pub mod filter;
67pub mod ingest;
78pub mod ops;
89pub mod resolver;
+23-2
src/main.rs
···2525 info!("{cfg}");
26262727 let state = AppState::new(&cfg)?;
2828+2929+ if cfg.full_network {
3030+ let filter_ks = state.db.filter.clone();
3131+ let inner = state.db.inner.clone();
3232+ tokio::task::spawn_blocking(move || {
3333+ use hydrant::filter::{FilterMode, MODE_KEY};
3434+ let mut batch = inner.batch();
3535+ batch.insert(
3636+ &filter_ks,
3737+ MODE_KEY,
3838+ rmp_serde::to_vec(&FilterMode::Full).into_diagnostic()?,
3939+ );
4040+ batch.commit().into_diagnostic()
4141+ })
4242+ .await
4343+ .into_diagnostic()??;
4444+4545+ let new_filter = hydrant::db::filter::load(&state.db.filter)?;
4646+ state.filter.store(new_filter.into());
4747+ }
4848+2849 let (buffer_tx, buffer_rx) = mpsc::unbounded_channel();
2950 let state = Arc::new(state);
3051···123144 }
124145 });
125146126126- if cfg.full_network {
147147+ if state.filter.load().mode == hydrant::filter::FilterMode::Full {
127148 tokio::spawn(
128149 Crawler::new(
129150 state.clone(),
···158179 state.clone(),
159180 buffer_tx,
160181 cfg.relay_host,
161161- cfg.full_network,
182182+ state.filter.clone(),
162183 matches!(cfg.verify_signatures, SignatureVerification::Full),
163184 );
164185
+7
src/ops.rs
···11use crate::db::types::{DbAction, DbRkey, DbTid, TrimmedDid};
22use crate::db::{self, Db, keys, ser_repo_state};
33+use crate::filter::FilterConfig;
34use crate::types::{
45 AccountEvt, BroadcastEvent, IdentityEvt, MarshallableEvt, RepoState, RepoStatus, ResyncState,
56 StoredEvent,
···222223 mut repo_state: RepoState<'s>,
223224 commit: &'commit Commit<'commit>,
224225 signing_key: Option<&PublicKey>,
226226+ filter: &FilterConfig,
225227) -> Result<ApplyCommitResults<'s>> {
226228 let did = &commit.repo;
227229 debug!("applying commit {} for {did}", &commit.commit);
···267269268270 for op in &commit.ops {
269271 let (collection, rkey) = parse_path(&op.path)?;
272272+273273+ if !filter.matches_collection(collection) {
274274+ continue;
275275+ }
276276+270277 let rkey = DbRkey::new(rkey);
271278 let db_key = keys::record_key(did, collection, &rkey);
272279