idiolect_indexer/error.rs
1//! Error types for the indexer crate.
2//!
3//! The indexer loop pulls from three pluggable boundaries (stream,
4//! handler, cursor store) and owns the dispatch of firehose commits
5//! into strongly-typed records. Each boundary has its own failure
6//! modes; [`IndexerError`] flattens them for the orchestrator.
7
8use idiolect_records::DecodeError;
9
10/// Every failure the indexer can raise while pulling events and
11/// driving handlers.
12#[derive(Debug, thiserror::Error)]
13pub enum IndexerError {
14 /// The [`EventStream`](crate::EventStream) produced an error
15 /// pulling the next event. Transport-level failures bubble up
16 /// here so the caller can decide whether to reconnect or exit.
17 #[error("event stream error: {0}")]
18 Stream(String),
19
20 /// The cursor store failed to load or commit a cursor position.
21 #[error("cursor store error: {0}")]
22 Cursor(String),
23
24 /// Decoding the record body json into an
25 /// [`idiolect_records::AnyRecord`] failed. Includes unknown
26 /// `dev.idiolect.*` nsids and serde type mismatches.
27 #[error("record decode error: {0}")]
28 Decode(#[from] DecodeError),
29
30 /// A [`RecordHandler`](crate::RecordHandler) returned an error
31 /// while processing a decoded record. The error message is
32 /// handler-defined; by the time this variant is constructed the
33 /// record has already been decoded and is valid.
34 #[error("record handler error: {0}")]
35 Handler(String),
36
37 /// The record body json was missing or malformed on the
38 /// firehose event. Tap produces this for delete actions (no
39 /// record body) and for events whose embedded record failed to
40 /// round-trip through `serde_json::RawValue`.
41 #[error("missing or malformed record body: {0}")]
42 MissingBody(String),
43
44 /// The configured [`RecordFamily`](idiolect_records::RecordFamily)'s
45 /// `contains` predicate accepted a collection NSID, but its
46 /// `decode` then returned `Ok(None)` for the same NSID. The
47 /// two predicates have diverged, which is a family-implementation
48 /// bug; this variant surfaces it as a hard error rather than
49 /// silently dropping the record.
50 #[error("record family contract violated: contains accepted {0} but decode returned None")]
51 FamilyContract(String),
52}