1use std::io;
2use thiserror::Error;
3
4#[derive(Error, Debug)]
5pub enum Error {
6 #[error("IO error: {0}")]
7 Io(#[from] io::Error),
8
9 #[error("Corruption detected: {0}")]
10 Corruption(String),
11
12 #[error("Key not found: {0}")]
13 NotFound(String),
14
15 #[error("Invalid argument: {0}")]
16 InvalidArgument(String),
17
18 #[error("Database already exists: {0}")]
19 AlreadyExists(String),
20
21 #[error("WAL full")]
22 WalFull,
23
24 #[error("Checksum mismatch")]
25 ChecksumMismatch,
26
27 #[error("Internal error: {0}")]
28 Internal(String),
29
30 #[error("Encryption error: {0}")]
32 EncryptionError(String),
33
34 #[error("Compression error: {0}")]
35 CompressionError(String),
36
37 #[error("Manifest corruption: {0}")]
38 ManifestCorruption(String),
39
40 #[error("Compaction error: {0}")]
41 CompactionError(String),
42
43 #[error("Stripe error: {0}")]
44 StripeError(String),
45
46 #[error("Invalid expression: {0}")]
48 InvalidExpression(String),
49
50 #[error("Conditional check failed: {0}")]
52 ConditionalCheckFailed(String),
53
54 #[error("Transaction canceled: {0}")]
56 TransactionCanceled(String),
57
58 #[error("Invalid query: {0}")]
60 InvalidQuery(String),
61
62 #[error("Resource exhausted: {0}")]
64 ResourceExhausted(String),
65}
66
67impl Error {
68 pub fn code(&self) -> &'static str {
71 match self {
72 Error::Io(_) => "IO_ERROR",
73 Error::Corruption(_) => "CORRUPTION",
74 Error::NotFound(_) => "NOT_FOUND",
75 Error::InvalidArgument(_) => "INVALID_ARGUMENT",
76 Error::AlreadyExists(_) => "ALREADY_EXISTS",
77 Error::WalFull => "WAL_FULL",
78 Error::ChecksumMismatch => "CHECKSUM_MISMATCH",
79 Error::Internal(_) => "INTERNAL_ERROR",
80 Error::EncryptionError(_) => "ENCRYPTION_ERROR",
81 Error::CompressionError(_) => "COMPRESSION_ERROR",
82 Error::ManifestCorruption(_) => "MANIFEST_CORRUPTION",
83 Error::CompactionError(_) => "COMPACTION_ERROR",
84 Error::StripeError(_) => "STRIPE_ERROR",
85 Error::InvalidExpression(_) => "INVALID_EXPRESSION",
86 Error::ConditionalCheckFailed(_) => "CONDITIONAL_CHECK_FAILED",
87 Error::TransactionCanceled(_) => "TRANSACTION_CANCELED",
88 Error::InvalidQuery(_) => "INVALID_QUERY",
89 Error::ResourceExhausted(_) => "RESOURCE_EXHAUSTED",
90 }
91 }
92
93 pub fn is_retryable(&self) -> bool {
98 match self {
99 Error::Io(_) => true,
101 Error::WalFull => true,
102 Error::ResourceExhausted(_) => true,
103 Error::CompactionError(_) => true,
104 Error::StripeError(_) => true,
105
106 Error::Corruption(_) => false,
108 Error::NotFound(_) => false,
109 Error::InvalidArgument(_) => false,
110 Error::AlreadyExists(_) => false,
111 Error::ChecksumMismatch => false,
112 Error::Internal(_) => false,
113 Error::EncryptionError(_) => false,
114 Error::CompressionError(_) => false,
115 Error::ManifestCorruption(_) => false,
116 Error::InvalidExpression(_) => false,
117 Error::ConditionalCheckFailed(_) => false,
118 Error::TransactionCanceled(_) => false,
119 Error::InvalidQuery(_) => false,
120 }
121 }
122
123 pub fn with_context(self, context: &str) -> Error {
146 Error::Internal(format!("{}: {}", context, self))
147 }
148}
149
150pub type Result<T> = std::result::Result<T, Error>;