Uh oh!
There was an error while loading. Please reload this page.
Add LWTRetryPolicy: retry CAS timeouts on same host with backoff - #783
Add LWTRetryPolicy: retry CAS timeouts on same host with backoff#783mykaul wants to merge 1 commit into
Conversation
mykaul
commented
Apr 7, 2026
CC @calebxyz |
calebxyz
commented
Apr 7, 2026
mykaul
commented
Apr 7, 2026
@calebxyz - it's pointless to compare the different drivers' performance - they differ greatly. What is important is the correct and optimized behavior - and there we still have gaps. I think we are very far from testing the correct behavior - we need many more system level tests on one hand (and on the other hand, I'm against testing it in full setup - which is why I've created scylladb/scylla-ccm#731 (that is probably not ready yet , but that's a different issue) |
calebxyz
commented
Apr 7, 2026
This is sad, the amount of unpredictability is horrible |
mykaul
commented
Apr 7, 2026
That's one of the major reasons to move some to be Rust based - Rust, CPP-over-Rust, NodeJS-over-Rust, Python-over-Rust. (and we'll stay with Java and Go, I reckon). |
f1a865b to
d2a8538CompareLWT queries use Paxos consensus where the coordinator is the Paxos leader. Retrying on a different host causes Paxos contention — the new coordinator must compete with the original one, potentially causing cascading timeouts. LWTRetryPolicy (extends ExponentialBackoffRetryPolicy) handles this by: - CAS write timeouts: retry on SAME host with exponential backoff - Serial consistency read timeouts: retry on SAME host with backoff - Serial consistency unavailable: retry on NEXT host (paxos quorum lost) - Non-CAS operations: delegate to base ExponentialBackoffRetryPolicy Modeled after gocql's LWTRetryPolicy interface.
d2a8538 to
0fe5e65CompareImportant Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
mykaul
commented
Jul 29, 2026
Rebased onto current Consistency check vs. related LWT/Paxos work:
Testing:
No unresolved review threads found. Rebased and force-pushed ( |
There was a problem hiding this comment.
Pull request overview
Note
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Adds an LWT-aware retry policy that prefers retrying CAS/serial operations on the same host with exponential backoff to reduce Paxos contention, plus unit tests validating the behavior.
Changes:
- Introduced
LWTRetryPolicyextendingExponentialBackoffRetryPolicywith LWT-specific handling for CAS write timeouts, serial read timeouts, and serial unavailable. - Added a new unit test suite (
LWTRetryPolicyTest) covering same-host retries, backoff behavior, max-retry handling, and delegation to base policy for non-LWT cases.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| cassandra/policies.py | Adds LWTRetryPolicy with LWT-aware retry decisions and backoff. |
| tests/unit/test_policies.py | Adds unit tests for LWTRetryPolicy behavior and delegation paths. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| def test_cas_write_timeout_retries_same_host(self): | ||
| """CAS write timeout on first attempt should retry on SAME host.""" | ||
| policy = self._make_policy() | ||
| retry, consistency, delay = policy.on_write_timeout( | ||
| query=None, consistency=ConsistencyLevel.QUORUM, | ||
| write_type=WriteType.CAS, | ||
| required_responses=3, received_responses=1, retry_num=0) | ||
| assert retry == RetryPolicy.RETRY | ||
| assert consistency == ConsistencyLevel.QUORUM | ||
| assert delay is not None and delay > 0 |
| def _make_policy(self, max_retries=3): | ||
| return LWTRetryPolicy(max_num_retries=max_retries) |
| LWT queries use Paxos consensus, where the first replica in the token ring | ||
| acts as the Paxos coordinator (leader). Retrying LWT queries on a *different* | ||
| host causes Paxos contention — the new coordinator must compete with the | ||
| original one, potentially causing cascading timeouts. |
Summary
LWT queries use Paxos consensus where the first replica (Paxos coordinator/leader) drives the consensus rounds. When a CAS write times out, retrying on a different host causes Paxos contention — the new coordinator must compete with the original, potentially causing cascading timeouts across the cluster.
Currently, no built-in retry policy retries CAS write timeouts at all — they are all RETHROWN immediately:
RetryPolicy.on_write_timeout: CAS → RETHROWExponentialBackoffRetryPolicy.on_write_timeout: CAS → RETHROWDowngradingConsistencyRetryPolicy.on_write_timeout: CAS → RETHROWThis PR adds
LWTRetryPolicy, a new retry policy that extendsExponentialBackoffRetryPolicywith LWT-aware behavior:ExponentialBackoffRetryPolicybehaviorThis is modeled after gocql's
LWTRetryPolicyinterface, which retries LWT queries on the same host to avoid Paxos contention. The key comment from gocql (line 188):Usage
Changes
cassandra/policies.py: AddedLWTRetryPolicyclass (extendsExponentialBackoffRetryPolicy)tests/unit/test_policies.py: AddedLWTRetryPolicyTestwith 21 testsTests
21 new tests covering:
All 103 tests in
tests/unit/test_policies.pypass.Related
TokenAwarePolicy): routing to the Paxos leader + retrying on the same host = optimal LWT latency path.