Skip to content

Commit ab07be6

Browse files
authored
Merge pull request #1075 from muzarski/fix-use-keyspace-errors-management-logic
errors: fix driver's logic that bases on error variants returned from query execution
2 parents 44a3093 + ce0fdca commit ab07be6

File tree

7 files changed

+56
-71
lines changed

7 files changed

+56
-71
lines changed

scylla/src/transport/cluster.rs

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -731,31 +731,7 @@ impl ClusterWorker {
731731
let use_keyspace_results: Vec<Result<(), QueryError>> =
732732
join_all(use_keyspace_futures).await;
733733

734-
// If there was at least one Ok and the rest were IoErrors we can return Ok
735-
// keyspace name is correct and will be used on broken connection on the next reconnect
736-
737-
// If there were only IoErrors then return IoError
738-
// If there was an error different than IoError return this error - something is wrong
739-
740-
let mut was_ok: bool = false;
741-
let mut io_error: Option<Arc<std::io::Error>> = None;
742-
743-
for result in use_keyspace_results {
744-
match result {
745-
Ok(()) => was_ok = true,
746-
Err(err) => match err {
747-
QueryError::IoError(io_err) => io_error = Some(io_err),
748-
_ => return Err(err),
749-
},
750-
}
751-
}
752-
753-
if was_ok {
754-
return Ok(());
755-
}
756-
757-
// We can unwrap io_error because use_keyspace_futures must be nonempty
758-
Err(QueryError::IoError(io_error.unwrap()))
734+
use_keyspace_result(use_keyspace_results.into_iter())
759735
}
760736

761737
async fn perform_refresh(&mut self) -> Result<(), QueryError> {
@@ -788,3 +764,39 @@ impl ClusterWorker {
788764
self.cluster_data.store(new_cluster_data);
789765
}
790766
}
767+
768+
/// Returns a result of use_keyspace operation, based on the query results
769+
/// returned from given node/connection.
770+
///
771+
/// This function assumes that `use_keyspace_results` iterator is NON-EMPTY!
772+
pub(crate) fn use_keyspace_result(
773+
use_keyspace_results: impl Iterator<Item = Result<(), QueryError>>,
774+
) -> Result<(), QueryError> {
775+
// If there was at least one Ok and the rest were broken connection errors we can return Ok
776+
// keyspace name is correct and will be used on broken connection on the next reconnect
777+
778+
// If there were only broken connection errors then return broken connection error.
779+
// If there was an error different than broken connection error return this error - something is wrong
780+
781+
let mut was_ok: bool = false;
782+
let mut broken_conn_error: Option<QueryError> = None;
783+
784+
for result in use_keyspace_results {
785+
match result {
786+
Ok(()) => was_ok = true,
787+
Err(err) => match err {
788+
QueryError::BrokenConnection(_) | QueryError::ConnectionPoolError(_) => {
789+
broken_conn_error = Some(err)
790+
}
791+
_ => return Err(err),
792+
},
793+
}
794+
}
795+
796+
if was_ok {
797+
return Ok(());
798+
}
799+
800+
// We can unwrap conn_broken_error because use_keyspace_results must be nonempty
801+
Err(broken_conn_error.unwrap())
802+
}

scylla/src/transport/connection_pool.rs

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,31 +1108,7 @@ impl PoolRefiller {
11081108
.await
11091109
.map_err(|_| QueryError::TimeoutError)?;
11101110

1111-
// If there was at least one Ok and the rest were IoErrors we can return Ok
1112-
// keyspace name is correct and will be used on broken connection on the next reconnect
1113-
1114-
// If there were only IoErrors then return IoError
1115-
// If there was an error different than IoError return this error - something is wrong
1116-
1117-
let mut was_ok: bool = false;
1118-
let mut io_error: Option<Arc<std::io::Error>> = None;
1119-
1120-
for result in use_keyspace_results {
1121-
match result {
1122-
Ok(()) => was_ok = true,
1123-
Err(err) => match err {
1124-
QueryError::IoError(io_err) => io_error = Some(io_err),
1125-
_ => return Err(err),
1126-
},
1127-
}
1128-
}
1129-
1130-
if was_ok {
1131-
return Ok(());
1132-
}
1133-
1134-
// We can unwrap io_error because use_keyspace_futures must be nonempty
1135-
Err(QueryError::IoError(io_error.unwrap()))
1111+
super::cluster::use_keyspace_result(use_keyspace_results.into_iter())
11361112
};
11371113

11381114
tokio::task::spawn(async move {

scylla/src/transport/downgrading_consistency_retry_policy.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ impl RetrySession for DowngradingConsistencyRetrySession {
9494
match query_info.error {
9595
// Basic errors - there are some problems on this node
9696
// Retry on a different one if possible
97-
QueryError::IoError(_)
97+
QueryError::BrokenConnection(_)
98+
| QueryError::ConnectionPoolError(_)
9899
| QueryError::DbError(DbError::Overloaded, _)
99100
| QueryError::DbError(DbError::ServerError, _)
100101
| QueryError::DbError(DbError::TruncateError, _) => {
@@ -181,12 +182,10 @@ impl RetrySession for DowngradingConsistencyRetrySession {
181182

182183
#[cfg(test)]
183184
mod tests {
184-
use std::{io::ErrorKind, sync::Arc};
185-
186185
use bytes::Bytes;
187186

188187
use crate::test_utils::setup_tracing;
189-
use crate::transport::errors::BadQuery;
188+
use crate::transport::errors::{BadQuery, BrokenConnectionErrorKind, ConnectionPoolError};
190189

191190
use super::*;
192191

@@ -328,7 +327,10 @@ mod tests {
328327
QueryError::DbError(DbError::Overloaded, String::new()),
329328
QueryError::DbError(DbError::TruncateError, String::new()),
330329
QueryError::DbError(DbError::ServerError, String::new()),
331-
QueryError::IoError(Arc::new(std::io::Error::new(ErrorKind::Other, "test"))),
330+
QueryError::BrokenConnection(
331+
BrokenConnectionErrorKind::TooManyOrphanedStreamIds(5).into(),
332+
),
333+
QueryError::ConnectionPoolError(ConnectionPoolError::Initializing),
332334
];
333335

334336
for &cl in CONSISTENCY_LEVELS {

scylla/src/transport/errors.rs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,6 @@ pub enum QueryError {
5252
#[error("Failed to deserialize ERROR response: {0}")]
5353
CqlErrorParseError(#[from] CqlErrorParseError),
5454

55-
/// Input/Output error has occurred, connection broken etc.
56-
#[error("IO Error: {0}")]
57-
IoError(Arc<std::io::Error>),
58-
5955
/// Selected node's connection pool is in invalid state.
6056
#[error("No connections in the pool: {0}")]
6157
ConnectionPoolError(#[from] ConnectionPoolError),
@@ -154,7 +150,6 @@ impl From<QueryError> for NewSessionError {
154150
QueryError::BadQuery(e) => NewSessionError::BadQuery(e),
155151
QueryError::CqlResultParseError(e) => NewSessionError::CqlResultParseError(e),
156152
QueryError::CqlErrorParseError(e) => NewSessionError::CqlErrorParseError(e),
157-
QueryError::IoError(e) => NewSessionError::IoError(e),
158153
QueryError::ConnectionPoolError(e) => NewSessionError::ConnectionPoolError(e),
159154
QueryError::ProtocolError(m) => NewSessionError::ProtocolError(m),
160155
QueryError::InvalidMessage(m) => NewSessionError::InvalidMessage(m),
@@ -207,10 +202,6 @@ pub enum NewSessionError {
207202
#[error("Failed to deserialize ERROR response: {0}")]
208203
CqlErrorParseError(#[from] CqlErrorParseError),
209204

210-
/// Input/Output error has occurred, connection broken etc.
211-
#[error("IO Error: {0}")]
212-
IoError(Arc<std::io::Error>),
213-
214205
/// Selected node's connection pool is in invalid state.
215206
#[error("No connections in the pool: {0}")]
216207
ConnectionPoolError(#[from] ConnectionPoolError),

scylla/src/transport/load_balancing/default.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2855,7 +2855,6 @@ mod latency_awareness {
28552855
| QueryError::CqlResultParseError(_)
28562856
| QueryError::CqlErrorParseError(_)
28572857
| QueryError::InvalidMessage(_)
2858-
| QueryError::IoError(_)
28592858
| QueryError::ProtocolError(_)
28602859
| QueryError::TimeoutError
28612860
| QueryError::RequestTimeout(_) => true,

scylla/src/transport/retry_policy.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,8 @@ impl RetrySession for DefaultRetrySession {
142142
match query_info.error {
143143
// Basic errors - there are some problems on this node
144144
// Retry on a different one if possible
145-
QueryError::IoError(_)
145+
QueryError::BrokenConnection(_)
146+
| QueryError::ConnectionPoolError(_)
146147
| QueryError::DbError(DbError::Overloaded, _)
147148
| QueryError::DbError(DbError::ServerError, _)
148149
| QueryError::DbError(DbError::TruncateError, _) => {
@@ -221,11 +222,11 @@ mod tests {
221222
use super::{DefaultRetryPolicy, QueryInfo, RetryDecision, RetryPolicy};
222223
use crate::statement::Consistency;
223224
use crate::test_utils::setup_tracing;
224-
use crate::transport::errors::{BadQuery, QueryError};
225+
use crate::transport::errors::{
226+
BadQuery, BrokenConnectionErrorKind, ConnectionPoolError, QueryError,
227+
};
225228
use crate::transport::errors::{DbError, WriteType};
226229
use bytes::Bytes;
227-
use std::io::ErrorKind;
228-
use std::sync::Arc;
229230

230231
fn make_query_info(error: &QueryError, is_idempotent: bool) -> QueryInfo<'_> {
231232
QueryInfo {
@@ -323,7 +324,10 @@ mod tests {
323324
QueryError::DbError(DbError::Overloaded, String::new()),
324325
QueryError::DbError(DbError::TruncateError, String::new()),
325326
QueryError::DbError(DbError::ServerError, String::new()),
326-
QueryError::IoError(Arc::new(std::io::Error::new(ErrorKind::Other, "test"))),
327+
QueryError::BrokenConnection(
328+
BrokenConnectionErrorKind::TooManyOrphanedStreamIds(5).into(),
329+
),
330+
QueryError::ConnectionPoolError(ConnectionPoolError::Initializing),
327331
];
328332

329333
for error in idempotent_next_errors {

scylla/src/transport/speculative_execution.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ impl SpeculativeExecutionPolicy for PercentileSpeculativeExecutionPolicy {
8585
fn can_be_ignored<ResT>(result: &Result<ResT, QueryError>) -> bool {
8686
match result {
8787
Ok(_) => false,
88-
Err(QueryError::IoError(_)) => true,
88+
Err(QueryError::BrokenConnection(_)) => true,
89+
Err(QueryError::ConnectionPoolError(_)) => true,
8990
Err(QueryError::TimeoutError) => true,
9091
_ => false,
9192
}

0 commit comments

Comments
 (0)