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