Skip to main content

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}