Skip to content

docs: move scylla-3.11.5.x to 3.11.5.18 - #1142

Closed
nikagra wants to merge 126 commits into
scylladb:scylla-3.11.5.xfrom
nikagra:sync-3115-to-3115-18
Closed

nikagra wants to merge 126 commits into
scylladb:scylla-3.11.5.xfrom
nikagra:sync-3115-to-3115-18

Conversation

@nikagra

@nikagra nikagra commented Sep 24, 2026

Copy link
Copy Markdown

scylla-3.11.5.x was cut at 3.11.5.7 and never moved, so the published 3.x docs are eleven releases behind 3.11.5.18. This makes the branch 3.11.5.18 plus docs fixes, rooted at the release.

Merge with "Create a merge commit". A rebase or squash merge replays the release commits and the branch stops descending from the tag.

  • merge 46993c722e (3.11.5.18 + bump to 3.11.5.19-SNAPSHOT); pom.xml taken from the tag, which already replaced the dead javaee link
  • keep the branch's eval_rst toctrees, for recommonmark
  • cherry-pick ci: read javadoc output from target/reports on scylla-3.x #1124: plugin 3.11.3 writes target/reports
  • scylla-4.x's docs-pages.yml: this branch's copy installs JDK 8 only and would deploy the site without the JDK 11 versions' api/

Verified: git diff 46993c722e is exactly those 10 files; a local four-version multiversion build published 678 javadoc files for this version and the guard passed. No docs CI runs for PRs into this branch.

Refs #1134
Jira: DRIVER-1083

🤖 Generated with Claude Code

scylladb-promoter and others added 30 commits March 21, 2025 15:56
scylla-3.x branch does not publish jars.
Until this issue is fixed we can endup in situation when new version was
pushed to sonatype, merge into git, but never release.
As result tag is there, commits are there, but no packages on maven.
To fix that we need this workflow to re-release, but not create any tag
or commit.
`WITH COMPACT STORAGE` has been discontinued in scylla by scylladb/scylladb#16403
Tests needs to be disabled for newer versions.
…ladb#490)

Commit scylladb/3cd2a6173668c5a13b6e674f912ff597f76422f5 that removes
JMX finally reached enterprise at 2025.1, we need to disable the test.
…ladb#493)

Commit scylladb/3cd2a6173668c5a13b6e674f912ff597f76422f5 that removes
JMX finally reached enterprise at 2025.1, we need to disable the test.
We need to test every possible statement for tablet flow, that makes
sure:
1. That tablet into reported by server
2. Tablet information on Cluster is being updated
3. Statement is routed properly according to tablet info
Test clusters were incorrectly initialized, resulting in singular DC where
two were required.
One method needed additional adjustments due to the change.
In some cases having zero token node is a normal thing.
Logging invalid row each time driver updates metadata confuses users in
such case and produce bad UX.
Make driver report application name, version and client id to server on
startup message.
This brings two adjustments:
First, it changes the expected number of connections for Scylla clusters since
with multiple shards driver will usually open more connections.
Second, the checks for number of open channels now ignore the target port on
the cluster. Any channel matchin the address without port will now count.
This helps to correctly count connections to ccm made Scylla clusters which
can use different ports depending on circumstances. For example with
advanced shard awareness driver will target different port than in
non-shard aware case.
When running this test with newer Scylla, the drop keyspace query times out.
This is because the cluster lacks raft quorum, although the returned
`OperationTimedOutException` does not inform about that.
To observe this you need to enable debug logging and then you may find
message like this one before the exception:
```
[cluster2-nio-worker-3] DEBUG com.datastax.driver.core.Connection - Connection[/127.0.1.2:40269-1, inFlight=0, closed=false] Response received on stream 832 but no handler set anymore (either the request has timed out or it was closed due to another error). Received message is ERROR SERVER_ERROR: group [e4fdf001-521a-11f0-b1fb-7d275bcabf53] raft operation [read_barrier] timed out, there is no raft quorum, total voters count 2, alive voters count 1, dead voters [127.0.1.1]
```
Increasing the number of nodes to 3 allows the cluster to maintain the raft
quorum and does not impact the test itself.
In PR scylladb#554 application API was implemented in the form of three
additional Configuration attributes.

This PR to have one Configuration attribute of `ApplicationInfo` interface.
Default implementation of which will supply same three fields.
`ApplicationInfo` interface is done in such a way that allows to inject
any application information into startup message.
Adds Awaitility to the core module with test scope.
This allows cleaner waiting for boolean conditions in tests.
Turns out that it is possible to inspect TabletMap in this test before
the changes after the queries propagate.
To resolve that simple assertions were changed into short awaits that
will continue as soon as the condition is fulfilled or throw if it times out.

Dropping the keyspace was moved to the teardown method, because
it is possible for the test method to fail and never reach the line executing
the drop.

Repetetive select queries were replaced with more explicit method that ensures
queries are executed on every node. Previously the test relied on round robin
LBP to cause the same effect which may not have been obvious to the reader.
It is unused and not going to be used, only occupy memory and eats CPU
on hash calculation
Keyspace and table name are not used.
It only occupie memory and CPU on hash calculation.
At not point tablet from one table/keyspace is compared to a tablet from
another table/keyspace.
Purely cosmetic, it is not used anywhere.
Second .get on mapping is not necessary.
It can happen that connection is being closed between `isClosed()` from
userEventTriggered `isClosed()` from `write()`.
Which will result in netty event loop printing warning.
Not a big deal, but it confuses QA in regards of the analyzing if this
is a real error or not.
So, let's just ignore it.
Considering them as `LOCAL` confuses `TokenAwarePolicy` as result in
some cases it shuffle nodes from non-local and local racks together.
planing

There are no test for it, as result policy does not work as expected.
Let's have some tests for it.
It looks like we have forgotten to rename it on rebase from master.
It should be `scylla-driver-tests-osgi`.
It resulted in having double signed artifacts:
scylla-driver-core-3.11.5.7-javadoc.jar.asc.asc

Which resulted in publishing failure.
maven-javadoc-plugin started failing:
```
Error: ROR] Failed to execute goal org.apache.maven.plugins:maven-javadoc-plugin:3.11.3:jar (attach-javadocs) on project scylla-driver-core: MavenReportException: Error while generating Javadoc:
Error: ROR] Exit code: 1
Error: ROR] javadoc: warning - The code being documented uses modules but the packages defined in https://javadoc.io/doc/javax/javaee-api/8.0/ are in the unnamed module.
Error:     [ERROR] javadoc: error - Error fetching URL: https://javaee-spec.java.net/nonav/javadocs/
Error: ROR] javadoc: warning - The code being documented uses modules but the packages defined in https://docs.oracle.com/javase/8/docs/api/ are in the unnamed module.
Error: ROR] javadoc: warning - The code being documented uses modules but the packages defined in https://docs.oracle.com/javase/8/docs/api/ are in the unnamed module.
```
Update only plugins, no dependancies were touched.
Some of the plugins stayed untouched due to targeting java 8.
Update only plugins, no dependancies were touched.
Some of the plugins stayed untouched due to targeting java 8.
nikagra and others added 22 commits July 14, 2026 10:53
…rs them

driver-core has no Failsafe plugin binding (only bound in driver-tests/osgi/*),
and Surefire's default includes never match *IT.java, so these CCM integration
tests were silently never executed by `mvn verify -Pshort`/`-Plong`. Renaming to
*Test.java matches Surefire's default discovery pattern, mirroring the fix
already applied to DriverConfigReportingCcmIT in scylladb#973.

Renamed: TabletsIT, ZeroTokenNodesIT, LWTLoadBalancingIT, SchemaBuilderIT.

Now that LWTLoadBalancingTest actually runs, it surfaced a real (previously
undetected) bug: both test methods constructed a SimpleStatement with bound
values and then passed it to session.prepare(), which rejects statements
carrying values. Fixed by preparing the value-free statement and binding
values only on the resulting PreparedStatement, as the tests already intended.

All classes verified live against ScyllaDB 2026.1.0: Tablets (3), ZeroTokenNodes
(7), and LWTLoadBalancing (2) tests pass. SchemaBuilderTest's 6 methods remain
pre-existing enabled=false, unrelated to this fix.

Fixes scylladb#981.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
CCMBridge.add(int, int) unconditionally included `-t <thriftItf>` in the
`ccm add` command, but scylla-ccm's `add` command has no Thrift option at
all (Scylla never had a Thrift interface) -- passing it makes the whole
command fail with "ccm: error: no such option: -t". Confirmed against
scylladb/scylla-ccm's actual ClusterAddCmd parser (ccmlib/cmds/cluster_cmds.py,
master).

ZeroTokenNodesTest is the only caller of this method, and it never ran
before the scylladb#981 rename fix, so this was never caught. All three "Scylla
ITs" CI matrix legs on scylladb#982 failed with the identical error once the
rename made the test actually execute.

Verified locally against a venv with the real `scylla-ccm` (master, same
as CI's `make install-scylla-ccm`) installed: all 7 ZeroTokenNodesTest
methods pass, plus a full regression of the other 3 renamed classes (12/12).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Review follow-up on scylladb#982. Renaming these classes made them execute for the
first time, but several of their assertions could not fail. Each fix below
was verified live against ScyllaDB 2026.1.0.

TabletsTest, two independent false-passes:

  - `removeTableMappings(KEYSPACE_NAME)` passed the mixed-case "tabletsTest"
    while TabletMap keys arrive lowercased from the server and are matched
    with an exact equals(), so the "empty out tablets information" step
    silently cleared nothing and an iteration could be satisfied by state
    learned in a previous one. Lowercased, as the three sibling call sites
    already do.

  - `executeOnAllHostsAndReturnIfResultHasTabletsInfo` pins the statement
    via setHost() and never clears it, so checkIfRoutedProperly re-executed
    a pinned statement and always observed exactly one coordinator --
    `nodes.size() <= REPLICATION_FACTOR` could not fail. The pin is now
    cleared before the routing check.

  - Additionally, checkIfRoutedProperly now clears Statement.getLastHost()
    per iteration. PagingOptimizingLoadBalancingPolicy returns that host
    ahead of the real query plan and PagingOptimizingLatencyTracker sets it
    after every successful BoundStatement execution, which pinned the loop
    to its first coordinator for the bound-statement half of the matrix.

LWTLoadBalancingTest could not distinguish PRESERVE_REPLICA_ORDER from
RANDOM, for two reasons:

  - The framework's default keyspace is hardcoded to RF=1, so "the first
    replica" was trivially unique and hasSize(1) held under REGULAR routing
    too. initTestKeyspace() is now overridden to create an RF=3 keyspace
    (tablets disabled on Scylla, as elsewhere for replica-placement tests),
    following SingleTokenIntegrationTest's template.

  - Both tests re-executed one BoundStatement instance, so the paging
    optimisation described above pinned the coordinator after the first
    query -- hasSize(1) was guaranteed by that, not by the LWT path.
    Coordinator collection now binds a fresh statement per execution.

  - Added should_spread_non_serial_select_across_replicas as the control:
    same statement, same table, same policy, non-serial consistency level,
    asserting the coordinator does vary. Verified that it fails (1
    coordinator) if REPLICATION_FACTOR is dropped back to 1, so the two
    hasSize(1) assertions are now load-bearing.

ZeroTokenNodesTest asserted on a HashSet with containsExactly, which is
order-sensitive; HashSet iteration order is hash-derived, so this was a
latent flake. Switched to containsOnly, already used everywhere else in the
file (AssertJ 1.7.1, which this module pins, has no
containsExactlyInAnyOrder; for a Set containsOnly is equivalent).

CCMBridge derived the instance's `isScylla` from the global scylla.version
property instead of the constructor's scyllaVersion, unlike the sibling
`isDSE = dseVersion != null` one line above. Now derived from the instance.
Behaviour-neutral today -- Builder.scylla already defaults to the global,
withScylla() has no callers, and every bridge that is actually built takes
build()'s !versionConfigured branch where scyllaVersion *is* the global --
so this removes a footgun rather than fixing a live bug.

Verified: TabletsTest 3/3, ZeroTokenNodesTest 7/7, LWTLoadBalancingTest 3/3
against ScyllaDB 2026.1.0.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
…stage 1)

Stage 1 (groundwork) of driver configuration reporting for the 3.x
driver -- the 3.x counterpart of the 4.x feature (DRIVER-381/scylladb#967).
Lets the driver report its effective configuration to ScyllaDB at
connection time via new STARTUP options, so operators can inspect
driver settings (system.clients.client_options) while investigating
incidents.

Two STARTUP options are added:

- SESSION_ID: a dedicated, driver-generated UUID sent on every
  connection (control and pool) unconditionally, like DRIVER_NAME and
  DRIVER_VERSION, so the server can group all of a Cluster's
  connections -- including across multiple Sessions obtained from the
  same Cluster, since the control connection has no affiliation with
  any single Session. Independent of the user-settable CLIENT_ID.
- DRIVER_CONFIG: a compact JSON blob describing the effective
  configuration, sent only on the control connection. Stage 1 emits
  only {"version":1}; the full report follows in stage 2 (scylladb#974).
  Enabled by default; opt out with
  Cluster.builder().withDriverConfigReporting(false).

The report is built once, while the Cluster initializes, and the
resulting string is reused for every control connection that Cluster
opens -- it is never rebuilt while the session is in flight. Building
it is fail-safe: any failure is swallowed and simply leaves
DRIVER_CONFIG unset instead of breaking cluster initialization.

New DriverConfigReporter / DefaultDriverConfigReporter (package
com.datastax.driver.core) build the blob. Connection.Factory, of which
there is one per Cluster, holds that Cluster's session id and the built
report, and hands the report to the control connection as a constructor
argument -- null everywhere else, which is what suppresses reporting.
The control connection is identified by threading a reportConfig flag
from ControlConnection.tryConnect through a new
Connection.Factory.open(host, reportConfig) overload, since 3.x has no
pre-existing signal identifying the control connection at STARTUP time.

jackson-core/jackson-databind are enforced as plain required
dependencies (as they already were in released 3.11.5.17), used to
build the JSON blob; the orphaned jackson-dataformat-yaml dependency
(dead since the Scylla Cloud config code was removed) is dropped, so
consumers no longer inherit SnakeYAML.

system.clients.client_options is per node, so DRIVER_CONFIG only
appears on the node holding the control connection.

Fixes DRIVER-382

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
…VE-2026-59901 and CVE-2026-59949

- CVE-2026-59901 (HIGH): Bzip2Decoder can be driven into a permanent
  infinite loop in the RLE state machine of Bzip2BlockDecompressor.read(),
  capturing the event-loop thread. Fixed in netty 4.1.136.Final.

- CVE-2026-59949 (MEDIUM, CVSS 6.5): JNI-backed XXHash implementations do
  not validate their byte array arguments, so a null array or an
  out-of-range off/len can crash the JVM in GetPrimitiveArrayCritical.
  Fixed in lz4-java 1.11.1.

Both are patch-level bumps driven entirely by the root POM properties;
every netty/lz4 declaration already resolves through them. The driver's
LZ4 usage (LZ4Factory.fastestInstance(), fastCompressor(),
fastDecompressor()) does not touch the affected XXHash API, and netty
stays on the 4.1.x line the driver is built against.

The netty bump matches scylladb#978, which applied the same fix to scylla-4.x.

Tracked in: scylladb/scylla-cdc-source-connector#293

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Motivation:

The DRIVER_CONFIG report is consumed as a cross-driver contract, so it has
to be checked against the normative schema rather than against this driver's
own idea of the shape. Nothing in 3.x could do that.

Modifications:

Vendors the schema block verbatim from the design doc, revision v5 -- whose
report version field is still 1 -- as a test resource. This is the same
resource the 4.x sibling PR scylladb#968 ships, so the two drivers are held to one
document.

Validation runs on com.networknt:json-schema-validator, pinned to the 1.5.x
line because it is the last minor line still targeting Java 8. The
conformance tests assert on this validator's exact ValidationMessage
wording, so a bump may need those strings updated; that is noted on the
version property in the parent pom.

Result:

The resource and the dependency are in place. Nothing consumes them yet --
the reporter and the conformance tests that validate against them follow in
later commits.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Motivation:

The DRIVER_CONFIG report has to describe the policies a session is actually
running with, but the built-in policies keep their configuration in private
fields with no accessors. A preferred datacenter, a replica ordering or a
speculative-execution budget could not be observed from outside the policy
at all.

Modifications:

Adds public getters for exactly what the schema has a slot for:

- DCAwareRoundRobinPolicy: the local datacenter, whether it was set
  explicitly, and used-hosts-per-remote-DC.
- RackAwareRoundRobinPolicy: the local datacenter and rack, and whether
  each was set explicitly.
- TokenAwarePolicy: the replica ordering.
- ConstantSpeculativeExecutionPolicy: max executions and the delay.
- PercentileSpeculativeExecutionPolicy: max executions and the percentile.

The two speculative-execution policies hold these in immutable fields whose
values land in the schema's ranges exactly, so the report can name them by
their built-in type rather than falling back to "custom".

Also makes PagingOptimizingLoadBalancingPolicy implement
ChainableLoadBalancingPolicy. Cluster.Manager wraps every session's policy
in that internal class, so without a getChildPolicy() a chain walk stops at
the wrapper and never reaches the policy the user configured.

Result:

Pure widening -- no behavior changes. Every accessor returns what the policy
was constructed with.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Motivation:

QueryOptions.setConsistencyLevel accepted null, and a null there could never
work: SessionManager falls back to the default consistency level for every
request that does not set one of its own, and CBUtil.writeConsistencyLevel
then dereferences it to write the frame. Any statement without an explicit
level already failed against such a configuration.

Modifications:

The setter now rejects null, like the other QueryOptions setters that back a
value every query needs.

setSerialConsistencyLevel is deliberately left as it is. Serial consistency
is genuinely optional, so a null there is a configuration that works, and it
is reported as an omitted key rather than as a missing required one.

Result:

A behavior change to a public setter, and the only one in this series. It
narrows the accepted input to what the driver could actually use; the
rejected configuration had no working behavior to preserve.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
…on time

Motivation:

Stage 1 wired up DRIVER_CONFIG and sent a {"version":1} placeholder. This
fills in the report itself, in the normative cross-driver schema shape, so an
operator can see from the server what a client is actually configured with.

Modifications:

The report is built once per Cluster as it initializes, from Configuration
and Policies, and hangs off three groups. connection carries the connect/read
timeouts, the per-connection request capacity, the pool, the socket options,
the reconnection policy and -- only when TLS is on -- tls. control-plane
carries the system-query and schema-agreement timeouts. query carries the
per-request defaults plus the three policies acting on a query: retry,
load-balancing (with the node preference beside it) and, when configured,
speculative-execution.

The schema reports the node preference in two places and 3.x fills both from
the same policy chain: query.load-balancing.node-preference for what a query
is routed by, connection.node-preference for the part of the cluster the
driver holds connections to. One LoadBalancingPolicy decides both, since
distance(Host) governs whether a host is pooled at all, so the connection key
carries the datacenter half alone. A rack-aware policy's distance() returns
REMOTE, never IGNORED, for a local-datacenter host in another rack, so the
rack scopes no pooling at all; the datacenter does, a host outside the
preferred one being IGNORED unless the policy is configured to use hosts
there, and an ignored host gets no pool.

token-aware is the only built-in load balancing shape the schema defines, so
every other built-in policy -- a bare DCAwareRoundRobinPolicy,
RoundRobinPolicy, WhiteListPolicy -- is reported as custom with its class
name, which identifies it but carries none of the normalized flags. A
token-aware chain reports load-distribution from its replica ordering
(RANDOM, the 3.x default, is "shuffle"; TOPOLOGICAL is "replica-set";
NEUTRAL keeps the child's plan order, so "round-robin"). A custom policy is
named after the policy the user configured, not after
PagingOptimizingLoadBalancingPolicy, which Cluster.Manager wraps every
session's policy in and which is the outermost element of the chain; an
anonymous class falls back to its binary name, having no simple name where
the schema requires a non-empty one.

fallback-to-non-preferred-nodes is true whenever the policy can reach a node
outside the preference reported beside it. For DCAwareRoundRobin that means
used-hosts-per-remote-DC, since the preference is the datacenter.
RackAwareRoundRobin reports a rack, and the other racks of its local
datacenter are outside that yet are the second tier of every query plan, so
it is always true there, remote datacenter hosts or not.

in-flight.max needs a fallback because PoolingOptions is still UNSET when the
report is built: the protocol version is only negotiated once the control
connection is up. The default row is resolved with the same walk
PoolingOptions.setProtocolVersion applies -- the highest DEFAULTS key not
above the version -- driven by the version the user pinned with
withProtocolVersion when they pinned one, and by v3 otherwise, that being the
lowest version ScyllaDB negotiates. DEFAULTS holds only v1 and v3 rows, so a
cluster pinned to v2 is sized from v1's 128 rather than v3's 1024, and
pinning is the one part of negotiation knowable at report time.

Three ways reporting could break a connection rather than merely fail to
report are closed off:

- The report is capped at 32KiB of UTF-8 (MAX_DRIVER_CONFIG_LENGTH), matching
  the 4.x sibling PR scylladb#968, gocql scylladb#964 and csharp-driver scylladb#262. Beyond
  cross-driver parity this is a correctness fix: CBUtil.writeString writes
  each STARTUP value with a 16-bit length prefix and no bounds check, so a
  value over 65535 bytes truncates the prefix modulo 65536 while still
  appending the whole body -- a corrupt frame and a failed handshake, and not
  something the fail-safe try/catch can contain since nothing throws. Parts
  of the report are user-supplied and unbounded (DC/rack names, consistency
  levels, custom policy class names). Over the limit means WARN and no
  DRIVER_CONFIG.
- The fail-safe catch also covers InternalError, since customPolicy() calls
  getClass().getSimpleName() on arbitrary user policy objects (a documented
  JDK edge case for certain synthetic classes). Not a bare Error, so
  OutOfMemoryError and StackOverflowError still surface.
- The load balancing chain walk is bounded at 16 policies and shared by both
  callers. It follows getChildPolicy() on arbitrary user policies, so a
  cyclic chain used to spin forever on the Cluster initialization path -- the
  one failure mode a try/catch cannot contain, because it hangs rather than
  throws.

Result:

Every group the reporter can emit is validated against the normative schema
shipped earlier in this series, covering each discriminated-union branch and
optional group, with a negative test proving additionalProperties=false is
enforced.

Where a configured value falls outside what the schema can express, an
optional key or group is omitted rather than emitted as a value the schema
rejects; where a required key has no accurate value to carry, it is left in
the one state that is accurate and the limitation is documented on the class.
The assertion is therefore that a report violates the schema in exactly the
documented ways and no other. The PR description catalogues each omission and
the three schema gaps recorded for the cross-driver document.

Both node preference slots are an approximation once a wrapper sits above the
policy they were read from. HostFilterPolicy.distance() -- and so
WhiteListPolicy's, which extends it -- returns IGNORED for any host failing
its predicate, including one inside the reported datacenter, and a custom
chainable policy computes distance() itself and need honor nothing below it.
The configured datacenter is reported anyway, on the grounds that hiding one
the operator really did set is worse. The asymmetry is deliberate: nothing is
inferred on a third party's behalf, but what was configured is passed
through. The restriction has nowhere to go, the built-in shape having no room
for a wrapper and fromDCWhiteList collapsing its datacenters into an opaque
Predicate<Host>.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
… can be

Motivation:

Two problems with where the report was built, both in Connection.Factory.

Stage 1 made jackson-core and jackson-databind required compile-scope
dependencies of driver-core, and DefaultDriverConfigReporter holds an
ObjectMapper in a static field. Exclude jackson-databind and merely
initializing that class raises NoClassDefFoundError. That is an Error, raised
while initializing the class rather than thrown from any method it declares, so
neither the reporter's own fail-safe nor its caller could contain it -- and it
happens on the Cluster initialization path. A classpath that merely lacks an
optional serializer therefore went from "the report is skipped" to "no
connection can be established at all", the inverse of the invariant this class
is written around.

Separately, the report was built once as the Cluster initialized and the
resulting string reused for every control connection that factory ever opened.
But Cluster.Manager.init() builds the factory, and the first control connection
sends its STARTUP, before it calls LoadBalancingPolicy#init -- so a datacenter
or rack the policy infers from the node it reaches could never be reported at
all. The schema has keys for exactly that (dc-auto.local-dc,
rack-auto.inferred-local-dc, rack-auto.inferred-local-rack) and nothing could
ever fill them.

Modifications:

Connection.Factory decides once, as the Cluster initializes, whether a report
can be built at all: canBuildDriverConfigReport catches LinkageError and answers
false. LinkageError rather than NoClassDefFoundError alone, so a partially
present or version-mismatched Jackson -- which surfaces as
ExceptionInInitializerError out of the static initializer -- is covered too;
probing for one class name would pass and then still fail here. Choosing whether
to touch the class at all is the only place the check can live. The report it
builds is discarded; running it there is what loads Jackson on the
initialization thread rather than leaving a Netty event loop to be first.

Logged at WARN, and unconditionally: reporting ships enabled, so nobody opted
into it and nobody would think to look for a message saying it is off.

The report itself is then built inside each control connection's STARTUP frame
assembly, and never cached. Connection carries a reportConfig flag instead of a
blob, and asks the factory for a report when it needs one.

This is the same fallback SnappyCompressor already applies for its own optional
library. It does not contradict buildReport() deliberately not catching bare
Error: that is about report building never masking a real JVM-level failure,
while this is a call site tolerating a missing optional dependency.

Result:

Excluding Jackson costs the report and nothing else, and a report describes the
objects in force at the handshake that sends it rather than the configuration
the Cluster was constructed from. The first control connection still reports
{"type":"dc-auto"} with no datacenter -- the policy genuinely has not inferred
one yet -- and every reconnect carries the one it has since inferred. A CCM test
forces a control-connection reconnect against a live cluster and asserts both
halves, byte-for-byte against a rebuilt report.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Motivation:

Every public member the configuration-reporting feature adds is new and none of
it has shipped: stage 1 merged as 8ee8349, after the 3.11.5.17 release, so the
whole surface is still unreleased on 3.11.5.18-SNAPSHOT. The convention this repo
already applies to recent additions -- TabletMap, Metadata#getReplicasList,
Metadata#getTabletMap, BatchStatement#getRoutingStatement -- is Guava's @beta,
declaring the shape provisional until it has proven out across releases. This
feature was the one recent addition not marked.

Modifications:

Marks the API in the two granularities the tree already uses: a whole new type at
type level, as TabletMap is, and a new method on a pre-existing type at method
level, as Metadata and BatchStatement are.

Type level, both new types:

- DriverConfigReporter, which covers buildReport().
- DefaultDriverConfigReporter, which covers DRIVER_CONFIG_KEY, the constructor,
  buildReport(), and the protected buildJson(), populateConfig(ObjectNode) and
  configuration extension points -- the class is public and non-final, so those
  are part of the surface a subclass compiles against.

Method level, on types that predate the feature:

- Cluster.Builder#withDriverConfigReporting and its Configuration counterparts,
  isDriverConfigReportingEnabled() and Configuration.Builder#withDriverConfig-
  Reporting.
- The thirteen policy accessors this stage added to feed the report:
  ConstantSpeculativeExecutionPolicy and PercentileSpeculativeExecutionPolicy
  (max executions, delay, percentile), DCAwareRoundRobinPolicy and
  RackAwareRoundRobinPolicy (local datacenter and rack, whether each is explicit,
  used hosts per remote DC), HostFilterPolicy#getWhiteListedDatacenters,
  TokenAwarePolicy#getReplicaOrdering.

PagingOptimizingLoadBalancingPolicy is marked on getChildPolicy() rather than on
the class: the class is public API from 2018 and is not provisional, while its
implementing ChainableLoadBalancingPolicy at all is what this work introduced.

Result:

Behaviour is unchanged -- @beta is CLASS-retention, so nothing observes it at
runtime, and @documented, so it renders in the javadoc a caller reads. Callers of
the reporting API now see that its shape may change before it settles, and clirr
is unaffected because no signature moved.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
QueryTrace.doFetchTrace() retries only until the coordinator's session row
reports a duration; the events fetched alongside it can still be empty. The
test read that as "the coordinator never queried locally" and failed, which
reddened the driver matrix on roughly a quarter of runs.

Retry the traced read up to 3 times, binding a fresh statement each attempt,
and fail only when no attempt observes a local read. A wrong shard still
fails immediately.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
All three tests in WarningsTest require the server to emit Cassandra's
"Aggregation query used without partition key" warning for SELECT count(*),
which Scylla does not send. Two were annotated in "Disable ITs which fail
under Scylla" (f475ebd); this one was missed because its `isolated` group
was not run at the time, so it was never observed to fail. The matrix started
running that group in June 2026, and the failure has since been worked around
in a single version's patch file rather than fixed here.

Annotate it like its two siblings so the file is self-consistent and future
tags need no patch hunk. Nothing to fix driver-side: getWarnings() correctly
reports that the server sent no warning.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
scylla-3.11.5.x was cut at 3.11.5.7 and never moved, so the docs site
documents a release eleven patches old. Merge the latest 3.11.5 release
with its next-development pom bump, so the branch can be released from.

pom.xml conflicted on the javaee javadoc link, which the tag already
replaced; taken from the tag. The branch's eval_rst toctrees are kept
for recommonmark.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
)

maven-javadoc-plugin moved the javadoc goal's output from
target/site/apidocs to target/reports/apidocs in 3.11, and this branch
pins 3.11.3. The script still copies from target/site, so the glob never
matches, mv fails, and api/ publishes empty. The frozen scylla-3.*.x
branches pin 2.10.4, which is why scylla-3.x has gone unnoticed: it is
not a published docs version yet.

Resolve from either location, clear both first so the fallback is
unambiguous, and require a real non-empty index.html. Build only
driver-core: with set -e in force, a javadoc failure in another module
would otherwise cost the whole api/.

Fixes scylladb#1123
Refs: scylladb#1080, scylladb#1118

Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
(cherry picked from commit 5a2f793)
A push to this branch runs its own copy of the docs publish workflow,
which rebuilds and deploys the whole site. This copy installs JDK 8
only and has no javadoc guard, so it would publish every JDK 11 version
without its api/. Replace it with scylla-4.x's docs-pages.yml.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
@coderabbitai

coderabbitai Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 156 files, which is 56 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: QUIET

Plan: Advanced

Run ID: b9710c0f-46d9-4e10-8219-9b7ed6230991

📥 Commits

Reviewing files that changed from the base of the PR and between c3f9464 and 51a8bc1.

📒 Files selected for processing (156)
  • .github/workflows/docs-pages.yaml
  • .github/workflows/docs-pages.yml
  • .github/workflows/docs-pr.yaml
  • .github/workflows/release.yml
  • .github/workflows/[email protected]
  • .github/workflows/[email protected]
  • .github/workflows/[email protected]
  • .gitignore
  • .travis.yml
  • CONTRIBUTING.md
  • Jenkinsfile
  • Makefile
  • README.md
  • clirr-ignores.xml
  • docs/_utils/javadoc.sh
  • driver-core/pom.xml
  • driver-core/src/main/java/com/datastax/driver/core/AbstractSession.java
  • driver-core/src/main/java/com/datastax/driver/core/ApplicationInfo.java
  • driver-core/src/main/java/com/datastax/driver/core/ArrayBackedResultSet.java
  • driver-core/src/main/java/com/datastax/driver/core/BatchStatement.java
  • driver-core/src/main/java/com/datastax/driver/core/BoundStatement.java
  • driver-core/src/main/java/com/datastax/driver/core/ChainedResultSetFuture.java
  • driver-core/src/main/java/com/datastax/driver/core/CloseFuture.java
  • driver-core/src/main/java/com/datastax/driver/core/Cluster.java
  • driver-core/src/main/java/com/datastax/driver/core/Configuration.java
  • driver-core/src/main/java/com/datastax/driver/core/ConfigurationBundle.java
  • driver-core/src/main/java/com/datastax/driver/core/Connection.java
  • driver-core/src/main/java/com/datastax/driver/core/ControlConnection.java
  • driver-core/src/main/java/com/datastax/driver/core/DefaultApplicationInfo.java
  • driver-core/src/main/java/com/datastax/driver/core/DefaultDriverConfigReporter.java
  • driver-core/src/main/java/com/datastax/driver/core/DefaultResultSetFuture.java
  • driver-core/src/main/java/com/datastax/driver/core/DriverConfigReporter.java
  • driver-core/src/main/java/com/datastax/driver/core/EventDebouncer.java
  • driver-core/src/main/java/com/datastax/driver/core/FramingFormatHandler.java
  • driver-core/src/main/java/com/datastax/driver/core/GuavaCompatibility.java
  • driver-core/src/main/java/com/datastax/driver/core/Host.java
  • driver-core/src/main/java/com/datastax/driver/core/HostConnectionPool.java
  • driver-core/src/main/java/com/datastax/driver/core/Message.java
  • driver-core/src/main/java/com/datastax/driver/core/MetadataIdInfo.java
  • driver-core/src/main/java/com/datastax/driver/core/Parameters.java
  • driver-core/src/main/java/com/datastax/driver/core/PoolingOptions.java
  • driver-core/src/main/java/com/datastax/driver/core/ProtocolFeature.java
  • driver-core/src/main/java/com/datastax/driver/core/ProtocolFeatureStore.java
  • driver-core/src/main/java/com/datastax/driver/core/ProtocolFeatures.java
  • driver-core/src/main/java/com/datastax/driver/core/QueryOptions.java
  • driver-core/src/main/java/com/datastax/driver/core/RegularStatement.java
  • driver-core/src/main/java/com/datastax/driver/core/RequestHandler.java
  • driver-core/src/main/java/com/datastax/driver/core/Requests.java
  • driver-core/src/main/java/com/datastax/driver/core/Responses.java
  • driver-core/src/main/java/com/datastax/driver/core/ScyllaCloudAuthInfo.java
  • driver-core/src/main/java/com/datastax/driver/core/ScyllaCloudConnectionConfig.java
  • driver-core/src/main/java/com/datastax/driver/core/ScyllaCloudContext.java
  • driver-core/src/main/java/com/datastax/driver/core/ScyllaCloudDatacenter.java
  • driver-core/src/main/java/com/datastax/driver/core/ScyllaCloudSniEndPointFactory.java
  • driver-core/src/main/java/com/datastax/driver/core/SessionManager.java
  • driver-core/src/main/java/com/datastax/driver/core/SystemColumnProjection.java
  • driver-core/src/main/java/com/datastax/driver/core/TabletMap.java
  • driver-core/src/main/java/com/datastax/driver/core/exceptions/OperationTimedOutException.java
  • driver-core/src/main/java/com/datastax/driver/core/policies/ConstantSpeculativeExecutionPolicy.java
  • driver-core/src/main/java/com/datastax/driver/core/policies/DCAwareRoundRobinPolicy.java
  • driver-core/src/main/java/com/datastax/driver/core/policies/HostFilterPolicy.java
  • driver-core/src/main/java/com/datastax/driver/core/policies/LatencyAwarePolicy.java
  • driver-core/src/main/java/com/datastax/driver/core/policies/PagingOptimizingLoadBalancingPolicy.java
  • driver-core/src/main/java/com/datastax/driver/core/policies/PercentileSpeculativeExecutionPolicy.java
  • driver-core/src/main/java/com/datastax/driver/core/policies/RackAwareRoundRobinPolicy.java
  • driver-core/src/main/java/com/datastax/driver/core/policies/TokenAwarePolicy.java
  • driver-core/src/main/java/com/datastax/driver/core/utils/MoreFutures.java
  • driver-core/src/test/java/com/datastax/driver/core/AbstractReconnectionHandlerTest.java
  • driver-core/src/test/java/com/datastax/driver/core/AsyncQueryTest.java
  • driver-core/src/test/java/com/datastax/driver/core/AsyncResultSetTest.java
  • driver-core/src/test/java/com/datastax/driver/core/AuthenticationTest.java
  • driver-core/src/test/java/com/datastax/driver/core/CCMAccess.java
  • driver-core/src/test/java/com/datastax/driver/core/CCMBridge.java
  • driver-core/src/test/java/com/datastax/driver/core/CCMBridgeTest.java
  • driver-core/src/test/java/com/datastax/driver/core/CCMCache.java
  • driver-core/src/test/java/com/datastax/driver/core/CCMConfig.java
  • driver-core/src/test/java/com/datastax/driver/core/CCMTestsSupport.java
  • driver-core/src/test/java/com/datastax/driver/core/CloudConfigYamlParsingTest.java
  • driver-core/src/test/java/com/datastax/driver/core/ConnectionReleaseTest.java
  • driver-core/src/test/java/com/datastax/driver/core/ControlConnectionTest.java
  • driver-core/src/test/java/com/datastax/driver/core/ControlConnectionUnitTest.java
  • driver-core/src/test/java/com/datastax/driver/core/DefaultDriverConfigReporterTest.java
  • driver-core/src/test/java/com/datastax/driver/core/DefaultResultSetFutureTest.java
  • driver-core/src/test/java/com/datastax/driver/core/DriverConfigReportingCcmTest.java
  • driver-core/src/test/java/com/datastax/driver/core/HostConnectionPoolTest.java
  • driver-core/src/test/java/com/datastax/driver/core/MetadataTest.java
  • driver-core/src/test/java/com/datastax/driver/core/PreparedStatementInvalidationTest.java
  • driver-core/src/test/java/com/datastax/driver/core/PreparedStatementTest.java
  • driver-core/src/test/java/com/datastax/driver/core/RequestHandlerTest.java
  • driver-core/src/test/java/com/datastax/driver/core/RequestsTest.java
  • driver-core/src/test/java/com/datastax/driver/core/ReusedStreamIdTest.java
  • driver-core/src/test/java/com/datastax/driver/core/SSLSessionTicketsTest.java
  • driver-core/src/test/java/com/datastax/driver/core/SSLTestBase.java
  • driver-core/src/test/java/com/datastax/driver/core/ScassandraCluster.java
  • driver-core/src/test/java/com/datastax/driver/core/SchemaChangesCCTest.java
  • driver-core/src/test/java/com/datastax/driver/core/ScyllaSniProxyTest.java
  • driver-core/src/test/java/com/datastax/driver/core/SegmentBuilderTest.java
  • driver-core/src/test/java/com/datastax/driver/core/SessionLeakTest.java
  • driver-core/src/test/java/com/datastax/driver/core/ShardAwarenessTest.java
  • driver-core/src/test/java/com/datastax/driver/core/SingleTokenIntegrationTest.java
  • driver-core/src/test/java/com/datastax/driver/core/StatementPagesTest.java
  • driver-core/src/test/java/com/datastax/driver/core/StatementSizeTest.java
  • driver-core/src/test/java/com/datastax/driver/core/TableMetadataTest.java
  • driver-core/src/test/java/com/datastax/driver/core/TabletMapListenerTest.java
  • driver-core/src/test/java/com/datastax/driver/core/TabletsIT.java
  • driver-core/src/test/java/com/datastax/driver/core/TabletsTest.java
  • driver-core/src/test/java/com/datastax/driver/core/TestListener.java
  • driver-core/src/test/java/com/datastax/driver/core/TestUtils.java
  • driver-core/src/test/java/com/datastax/driver/core/TestableNettySSLOptions.java
  • driver-core/src/test/java/com/datastax/driver/core/TimeoutStressTest.java
  • driver-core/src/test/java/com/datastax/driver/core/TokenIntegrationTest.java
  • driver-core/src/test/java/com/datastax/driver/core/TupleTest.java
  • driver-core/src/test/java/com/datastax/driver/core/UnresolvedUserTypeTest.java
  • driver-core/src/test/java/com/datastax/driver/core/UserTypesTest.java
  • driver-core/src/test/java/com/datastax/driver/core/WarningsTest.java
  • driver-core/src/test/java/com/datastax/driver/core/ZeroTokenNodesTest.java
  • driver-core/src/test/java/com/datastax/driver/core/policies/CustomRetryPolicyIntegrationTest.java
  • driver-core/src/test/java/com/datastax/driver/core/policies/DefaultRetryPolicyIntegrationTest.java
  • driver-core/src/test/java/com/datastax/driver/core/policies/DowngradingConsistencyRetryPolicyIntegrationTest.java
  • driver-core/src/test/java/com/datastax/driver/core/policies/FallthroughRetryPolicyIntegrationTest.java
  • driver-core/src/test/java/com/datastax/driver/core/policies/IdempotenceAwareRetryPolicyIntegrationTest.java
  • driver-core/src/test/java/com/datastax/driver/core/policies/LWTLoadBalancingTest.java
  • driver-core/src/test/java/com/datastax/driver/core/policies/LatencyAwarePolicyTest.java
  • driver-core/src/test/java/com/datastax/driver/core/policies/RackAwareRoundRobinPolicyTest.java
  • driver-core/src/test/java/com/datastax/driver/core/policies/TokenAwarePolicyTest.java
  • driver-core/src/test/java/com/datastax/driver/core/schemabuilder/SchemaBuilderTest.java
  • driver-core/src/test/java/com/datastax/driver/core/utils/SocketChannelMonitor.java
  • driver-core/src/test/resources/config/driver-config-report-v1.schema.json
  • driver-dist/pom.xml
  • driver-examples/pom.xml
  • driver-extras/pom.xml
  • driver-mapping/pom.xml
  • driver-mapping/src/main/java/com/datastax/driver/mapping/Mapper.java
  • driver-mapping/src/main/java/com/datastax/driver/mapping/MethodMapper.java
  • driver-mapping/src/main/java/com/datastax/driver/mapping/Result.java
  • driver-mapping/src/test/java/com/datastax/driver/mapping/MapperAsyncResultTest.java
  • driver-mapping/src/test/java/com/datastax/driver/mapping/MapperAsyncTest.java
  • driver-mapping/src/test/java/com/datastax/driver/mapping/MapperKeyspaceTest.java
  • driver-mapping/src/test/java/com/datastax/driver/mapping/MapperTest.java
  • driver-mapping/src/test/java/com/datastax/driver/mapping/UDTFieldMapperTest.java
  • driver-tests/osgi/README.md
  • driver-tests/osgi/common/pom.xml
  • driver-tests/osgi/common/src/test/java/com/datastax/driver/osgi/BundleOptions.java
  • driver-tests/osgi/pom.xml
  • driver-tests/osgi/shaded/pom.xml
  • driver-tests/osgi/unshaded/pom.xml
  • driver-tests/pom.xml
  • driver-tests/shading/pom.xml
  • driver-tests/shading/shaded/pom.xml
  • driver-tests/shading/unshaded/pom.xml
  • driver-tests/stress/pom.xml
  • faq/osgi/README.md
  • manual/compression/README.md
  • manual/load_balancing/README.md
  • pom.xml
  • renovate.json

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@dkropachev

Copy link
Copy Markdown

Changes merged manually

@dkropachev dkropachev closed this Sep 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants