When a statement leaves consistency_level unset, the effective value is inherited from its execution profile and used to construct the protocol message. However, policies receive the original statement, where consistency_level remains None.
Consequently, request planning can disagree with what is sent to Scylla. For example, token-aware routing cannot distinguish a strongly consistent LOCAL_ONE read from a LOCAL_QUORUM read and may prefer the tablet leader unnecessarily. Custom load-balancing and speculative-execution policies have the same limitation.
The original statement must not be modified because it may be reused concurrently with different execution profiles.
Option 1: Quick, targeted fix
Create a request-local shallow copy after resolving the execution profile, populate it with the effective consistency settings, and use it for policy planning:
planning_query = copy(query)
planning_query.consistency_level = effective_cl
planning_query.serial_consistency_level = effective_serial_cl
This is a small, backward-compatible change that fixes the immediate problem. Existing policy interfaces remain unchanged, and the caller’s statement is not mutated.
Option 2: Larger architectural refactor
Introduce an immutable request-scoped context containing the original statement and all resolved execution settings, including consistency levels, timeout, retry policy, row factory, load-balancing policy, speculative-execution policy, and continuous-paging options.
Protocol message construction, ResponseFuture, load balancing, speculative execution, retries, and paging would consume this common context. Existing policy APIs could remain compatible by exposing a request-local planning_statement containing the resolved statement-level values.
This is a broader refactor requiring changes across the request lifecycle, but it establishes one source of truth and prevents similar inconsistencies involving other execution-profile settings and per-attempt behavior.
The two options are not mutually exclusive: the request-local copy can be implemented as the immediate fix, followed by the resolved request context as a separate architectural improvement.
When a statement leaves
consistency_levelunset, the effective value is inherited from its execution profile and used to construct the protocol message. However, policies receive the original statement, whereconsistency_levelremainsNone.Consequently, request planning can disagree with what is sent to Scylla. For example, token-aware routing cannot distinguish a strongly consistent
LOCAL_ONEread from aLOCAL_QUORUMread and may prefer the tablet leader unnecessarily. Custom load-balancing and speculative-execution policies have the same limitation.The original statement must not be modified because it may be reused concurrently with different execution profiles.
Option 1: Quick, targeted fix
Create a request-local shallow copy after resolving the execution profile, populate it with the effective consistency settings, and use it for policy planning:
This is a small, backward-compatible change that fixes the immediate problem. Existing policy interfaces remain unchanged, and the caller’s statement is not mutated.
Option 2: Larger architectural refactor
Introduce an immutable request-scoped context containing the original statement and all resolved execution settings, including consistency levels, timeout, retry policy, row factory, load-balancing policy, speculative-execution policy, and continuous-paging options.
Protocol message construction,
ResponseFuture, load balancing, speculative execution, retries, and paging would consume this common context. Existing policy APIs could remain compatible by exposing a request-localplanning_statementcontaining the resolved statement-level values.This is a broader refactor requiring changes across the request lifecycle, but it establishes one source of truth and prevents similar inconsistencies involving other execution-profile settings and per-attempt behavior.
The two options are not mutually exclusive: the request-local copy can be implemented as the immediate fix, followed by the resolved request context as a separate architectural improvement.