Skip to content

Commit f0763e5

Browse files
committed
response: add non_exhaustive attribute to DbError
I extracted the part of speculative_execution::can_be_ignored as DbError method. This way, we don't have to match against "_" (because method is defined in the same module as the type - namely scylla_cql).
1 parent 6b271fb commit f0763e5

File tree

2 files changed

+43
-39
lines changed

2 files changed

+43
-39
lines changed

scylla-cql/src/frame/response/error.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ impl Error {
151151
/// An error sent from the database in response to a query
152152
/// as described in the [specification](https://github.com/apache/cassandra/blob/5ed5e84613ef0e9664a774493db7d2604e3596e0/doc/native_protocol_v4.spec#L1029)\
153153
#[derive(Error, Debug, Clone, PartialEq, Eq)]
154+
#[non_exhaustive]
154155
pub enum DbError {
155156
/// The submitted query has a syntax error
156157
#[error("The submitted query has a syntax error")]
@@ -386,6 +387,47 @@ impl DbError {
386387
} => protocol_features.rate_limit_error.unwrap(),
387388
}
388389
}
390+
391+
/// Decides whether the error can be ignored. If true, the driver can perform
392+
/// a speculative retry to the next target.
393+
pub fn can_speculative_retry(&self) -> bool {
394+
// Do not remove this lint!
395+
// It's there for a reason - we don't want new variants
396+
// automatically fall under `_` pattern when they are introduced.
397+
#[deny(clippy::wildcard_enum_match_arm)]
398+
match self {
399+
// Errors that will almost certainly appear on other nodes as well
400+
DbError::SyntaxError
401+
| DbError::Invalid
402+
| DbError::AlreadyExists { .. }
403+
| DbError::Unauthorized
404+
| DbError::ProtocolError => false,
405+
406+
// Errors that should not appear there - thus, should not be ignored.
407+
DbError::AuthenticationError | DbError::Other(_) => false,
408+
409+
// For now, let's assume that UDF failure is not transient - don't ignore it
410+
// TODO: investigate
411+
DbError::FunctionFailure { .. } => false,
412+
413+
// Not sure when these can appear - don't ignore them
414+
// TODO: Investigate these errors
415+
DbError::ConfigError | DbError::TruncateError => false,
416+
417+
// Errors that we can ignore and perform a retry on some other node
418+
DbError::Unavailable { .. }
419+
| DbError::Overloaded
420+
| DbError::IsBootstrapping
421+
| DbError::ReadTimeout { .. }
422+
| DbError::WriteTimeout { .. }
423+
| DbError::ReadFailure { .. }
424+
| DbError::WriteFailure { .. }
425+
// Preparation may succeed on some other node.
426+
| DbError::Unprepared { .. }
427+
| DbError::ServerError
428+
| DbError::RateLimitReached { .. } => true,
429+
}
430+
}
389431
}
390432

391433
/// Type of the operation rejected by rate limiting

scylla/src/policies/speculative_execution.rs

Lines changed: 1 addition & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use futures::{
22
future::FutureExt,
33
stream::{FuturesUnordered, StreamExt},
44
};
5-
use scylla_cql::frame::response::error::DbError;
65
use std::{future::Future, sync::Arc, time::Duration};
76
use tracing::{trace_span, warn, Instrument};
87

@@ -125,44 +124,7 @@ fn can_be_ignored<ResT>(result: &Result<ResT, RequestError>) -> bool {
125124
| RequestAttemptError::UnableToAllocStreamId => true,
126125

127126
// Handle DbErrors
128-
RequestAttemptError::DbError(db_error, _) => {
129-
// Do not remove this lint!
130-
// It's there for a reason - we don't want new variants
131-
// automatically fall under `_` pattern when they are introduced.
132-
#[deny(clippy::wildcard_enum_match_arm)]
133-
match db_error {
134-
// Errors that will almost certainly appear on other nodes as well
135-
DbError::SyntaxError
136-
| DbError::Invalid
137-
| DbError::AlreadyExists { .. }
138-
| DbError::Unauthorized
139-
| DbError::ProtocolError => false,
140-
141-
// Errors that should not appear there - thus, should not be ignored.
142-
DbError::AuthenticationError | DbError::Other(_) => false,
143-
144-
// For now, let's assume that UDF failure is not transient - don't ignore it
145-
// TODO: investigate
146-
DbError::FunctionFailure { .. } => false,
147-
148-
// Not sure when these can appear - don't ignore them
149-
// TODO: Investigate these errors
150-
DbError::ConfigError | DbError::TruncateError => false,
151-
152-
// Errors that we can ignore and perform a retry on some other node
153-
DbError::Unavailable { .. }
154-
| DbError::Overloaded
155-
| DbError::IsBootstrapping
156-
| DbError::ReadTimeout { .. }
157-
| DbError::WriteTimeout { .. }
158-
| DbError::ReadFailure { .. }
159-
| DbError::WriteFailure { .. }
160-
// Preparation may succeed on some other node.
161-
| DbError::Unprepared { .. }
162-
| DbError::ServerError
163-
| DbError::RateLimitReached { .. } => true,
164-
}
165-
}
127+
RequestAttemptError::DbError(db_error, _) => db_error.can_speculative_retry(),
166128
}
167129
}
168130
},

0 commit comments

Comments
 (0)