Was this page helpful?
Caution
You're viewing documentation for an unstable version of ScyllaDB Rust Driver. Switch to the latest stable version.
Default retry policy¶
This is the retry policy used by default. It retries when there is a high chance that it might help.
This policy is based on the one in DataStax Java Driver.
The behaviour is the same.
Decision matrix¶
The exact retry decision per error class, taken from the implementation in
scylla::policies::retry::DefaultRetryPolicy:
Error |
Idempotent statement |
Non-idempotent statement |
|---|---|---|
Broken connection |
retry on next target |
don’t retry |
|
retry on next target |
don’t retry |
|
retry on next target (at most once) |
retry on next target (at most once) |
|
retry on same target (at most once) |
retry on same target (at most once) |
|
don’t retry |
don’t retry |
|
retry on same target (at most once) |
don’t retry |
|
don’t retry |
don’t retry |
|
retry on next target |
retry on next target |
|
retry on next target |
retry on next target |
|
don’t retry |
don’t retry |
Anything else ( |
don’t retry |
don’t retry |
Two cross-cutting rules to keep in mind:
Serial consistency short-circuits everything: if
RequestInfo.consistencyis one of the*_SERIALlevels (LWT path),DefaultRetryPolicyreturnsDontRetryregardless of the error and idempotence. This is a safety net for Paxos-routed writes, where the second attempt would re-enter the LWT protocol with surprising semantics.Per-session “at most once” guards:
Unavailable,ReadTimeout, andWriteTimeouteach have awas_*_retryflag on the session that flips after the first retry. Subsequent occurrences of the same error class on the sameRetrySessionreturnDontRetryeven if everything else still qualifies. The flags are reset byRetrySession::reset()between requests, so each new request gets a fresh budget.
Examples¶
To use in Session:
use scylla::client::session::Session;
use scylla::client::session_builder::SessionBuilder;
use scylla::client::execution_profile::ExecutionProfile;
use scylla::policies::retry::DefaultRetryPolicy;
let handle = ExecutionProfile::builder()
.retry_policy(Arc::new(DefaultRetryPolicy::new()))
.build()
.into_handle();
let session: Session = SessionBuilder::new()
.known_node("127.0.0.1:9042")
.default_execution_profile_handle(handle)
.build()
.await?;
To use in an unprepared statement:
use scylla::statement::unprepared::Statement;
use scylla::client::execution_profile::ExecutionProfile;
use scylla::policies::retry::DefaultRetryPolicy;
// Create a Statement manually and set the retry policy
let mut my_statement: Statement = Statement::new("INSERT INTO ks.tab (a) VALUES(?)");
my_statement.set_retry_policy(Some(Arc::new(DefaultRetryPolicy::new())));
// You can also set retry policy in an execution profile
let handle = ExecutionProfile::builder()
.retry_policy(Arc::new(DefaultRetryPolicy::new()))
.build()
.into_handle();
my_statement.set_execution_profile_handle(Some(handle));
// Execute the statement using this retry policy
let to_insert: i32 = 12345;
session.query_unpaged(my_statement, (to_insert,)).await?;
To use in a prepared statement:
use scylla::statement::prepared::PreparedStatement;
use scylla::client::execution_profile::ExecutionProfile;
use scylla::policies::retry::DefaultRetryPolicy;
// Create PreparedStatement manually and set the retry policy
let mut prepared: PreparedStatement = session
.prepare("INSERT INTO ks.tab (a) VALUES(?)")
.await?;
prepared.set_retry_policy(Some(Arc::new(DefaultRetryPolicy::new())));
// You can also set retry policy in an execution profile
let handle = ExecutionProfile::builder()
.retry_policy(Arc::new(DefaultRetryPolicy::new()))
.build()
.into_handle();
prepared.set_execution_profile_handle(Some(handle));
// Execute the statement using this retry policy
let to_insert: i32 = 12345;
session.execute_unpaged(&prepared, (to_insert,)).await?;