Skip to main content

force_sync/
error.rs

1//! Error types for force-sync.
2
3/// Database and migration errors.
4#[derive(Debug, thiserror::Error)]
5pub enum ForceSyncError {
6    /// Postgres pool acquisition failure.
7    #[error("database pool error: {0}")]
8    Pool(#[from] deadpool_postgres::PoolError),
9
10    /// Postgres client or query failure.
11    #[error("database error: {0}")]
12    Database(#[from] tokio_postgres::Error),
13
14    /// A replay cursor is required to append journal entries.
15    #[error("sync journal entries require a source cursor")]
16    MissingSourceCursor,
17
18    /// The transaction callback failed and the rollback also failed.
19    #[error(
20        "transaction callback failed and rollback also failed: callback={callback}; rollback={rollback}"
21    )]
22    TransactionRollback {
23        /// Error returned by the transaction callback.
24        callback: Box<Self>,
25        /// Error returned while attempting to roll back the transaction.
26        rollback: tokio_postgres::Error,
27    },
28
29    /// A required sync key part was empty.
30    #[error("sync key {part} cannot be empty")]
31    EmptySyncKeyPart {
32        /// The offending sync key part.
33        part: &'static str,
34    },
35
36    /// A requested sync record was not found.
37    #[error("missing {entity}")]
38    NotFound {
39        /// The missing entity name.
40        entity: &'static str,
41    },
42
43    /// A required engine configuration field was not provided.
44    #[error("missing required configuration: {field}")]
45    MissingConfiguration {
46        /// The missing configuration field.
47        field: &'static str,
48    },
49
50    /// A lease duration could not be represented as a Postgres interval timestamp.
51    #[error("lease duration is out of range")]
52    InvalidLeaseDuration,
53
54    /// A JSON payload could not be decoded.
55    #[error("json error: {0}")]
56    Json(#[from] serde_json::Error),
57
58    /// A Salesforce Pub/Sub operation failed.
59    #[error("pubsub error: {0}")]
60    PubSub(Box<force_pubsub::PubSubError>),
61
62    /// An outbox row carried an unexpected operation value.
63    #[error("invalid outbox operation: {op}")]
64    InvalidOutboxOperation {
65        /// The invalid operation value.
66        op: String,
67    },
68
69    /// An outbox row carried an already-encoded or otherwise invalid cursor.
70    #[error("invalid outbox cursor: {cursor}")]
71    InvalidOutboxCursor {
72        /// The invalid cursor value.
73        cursor: String,
74    },
75
76    /// A stored database value could not be decoded into a domain type.
77    #[error("invalid stored value for {field}: {value}")]
78    InvalidStoredValue {
79        /// The field or column name.
80        field: &'static str,
81        /// The invalid stored value.
82        value: String,
83    },
84
85    /// Placeholder variant while the crate surface is being implemented.
86    #[error("not implemented")]
87    NotImplemented,
88}
89
90/// Backward-compatible alias for the crate's top-level error type.
91pub type Error = ForceSyncError;
92
93impl From<force_pubsub::PubSubError> for ForceSyncError {
94    fn from(error: force_pubsub::PubSubError) -> Self {
95        Self::PubSub(Box::new(error))
96    }
97}