Skip to main content

duroxide_cdb/
errors.rs

1use duroxide::providers::ProviderError;
2
3/// Map an HTTP status code and message from CosmosDB into a ProviderError.
4pub fn map_cosmosdb_error(operation: &str, status: u16, message: &str) -> ProviderError {
5    match status {
6        // Conflict — ETag mismatch or duplicate ID
7        409 => ProviderError::retryable(operation, format!("CosmosDB conflict (409): {message}")),
8        // Too many requests — rate limited
9        429 => {
10            ProviderError::retryable(operation, format!("CosmosDB rate limited (429): {message}"))
11        }
12        // Request timeout
13        408 => ProviderError::retryable(
14            operation,
15            format!("CosmosDB request timeout (408): {message}"),
16        ),
17        // Precondition failed — ETag mismatch on conditional write
18        412 => ProviderError::retryable(
19            operation,
20            format!("CosmosDB precondition failed (412): {message}"),
21        ),
22        // Service unavailable
23        503 => ProviderError::retryable(
24            operation,
25            format!("CosmosDB service unavailable (503): {message}"),
26        ),
27        // Not found
28        404 => ProviderError::permanent(operation, format!("CosmosDB not found (404): {message}")),
29        // Bad request
30        400 => {
31            ProviderError::permanent(operation, format!("CosmosDB bad request (400): {message}"))
32        }
33        // Request entity too large
34        413 => ProviderError::permanent(
35            operation,
36            format!("CosmosDB request too large (413): {message}"),
37        ),
38        // Other errors: assume transient for 5xx, permanent for 4xx
39        s if s >= 500 => {
40            ProviderError::retryable(operation, format!("CosmosDB server error ({s}): {message}"))
41        }
42        s => ProviderError::permanent(operation, format!("CosmosDB client error ({s}): {message}")),
43    }
44}
45
46/// Check if an HTTP status represents a conflict (409).
47pub fn is_conflict(status: u16) -> bool {
48    status == 409
49}
50
51/// Check if an HTTP status represents not found (404).
52pub fn is_not_found(status: u16) -> bool {
53    status == 404
54}
55
56/// Check if an HTTP status represents precondition failed (412).
57pub fn is_precondition_failed(status: u16) -> bool {
58    status == 412
59}