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}