Skip to content

Preserve resolved execution settings during request planning #953

Description

@dkropachev

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions