Bump ch.qos.logback:logback-classic from 1.2.3 to 1.3.12 - #262
Closed
dependabot[bot] wants to merge 1 commit into
Closed
Bump ch.qos.logback:logback-classic from 1.2.3 to 1.3.12#262dependabot[bot] wants to merge 1 commit into
dependabot[bot] wants to merge 1 commit into
Conversation
Bumps [ch.qos.logback:logback-classic](https://github.com/qos-ch/logback) from 1.2.3 to 1.3.12. - [Commits](qos-ch/logback@v_1.2.3...v_1.3.12) --- updated-dependencies: - dependency-name: ch.qos.logback:logback-classic dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com>
Author
|
Superseded by #263. |
dependabot
Bot
deleted the
dependabot/maven/ch.qos.logback-logback-classic-1.3.12
branch
December 5, 2023 22:35
nikagra
added a commit
to nikagra/java-driver
that referenced
this pull request
Aug 3, 2026
Fills in the full DRIVER_CONFIG JSON report in the approved v2
cross-driver schema shape, replacing the stage-1 {"version":1}
placeholder. All groups are populated from Configuration and Policies
when the report is built, i.e. once per Cluster as it initializes.
Adds public getters to DCAwareRoundRobinPolicy and
RackAwareRoundRobinPolicy needed to report node-location-preference
and dc-failover, and makes PagingOptimizingLoadBalancingPolicy
implement ChainableLoadBalancingPolicy so the reporter can unwrap the
LB policy Cluster.Manager wraps at runtime.
Caps the report 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.
Hardens the other two ways reporting could break a connection rather
than merely fail to report:
- The fail-safe catch also covers InternalError, since customPolicy()
calls getClass().getSimpleName() on arbitrary user policy objects
(documented JDK edge case for certain synthetic classes). Not a bare
Error, so OutOfMemoryError/StackOverflowError still surface.
- The load balancing policy 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 the try/catch cannot
contain, because it hangs rather than throws.
Adds a JSON-Schema conformance test suite (mirroring the 4.x sibling
PR scylladb#968): the normative schema is shipped as a test resource and
validated via com.networknt:json-schema-validator (pinned to 1.5.x,
the last line still targeting Java 8), covering every discriminated-
union branch and optional group the 3.x reporter can emit, plus a
negative test proving additionalProperties=false is enforced.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
nikagra
added a commit
to nikagra/java-driver
that referenced
this pull request
Aug 3, 2026
Fills in the full DRIVER_CONFIG JSON report in the approved v2
cross-driver schema shape, replacing the stage-1 {"version":1}
placeholder. All groups are populated from Configuration and Policies
when the report is built, i.e. once per Cluster as it initializes.
Adds public getters to DCAwareRoundRobinPolicy and
RackAwareRoundRobinPolicy needed to report node-location-preference
and dc-failover, and makes PagingOptimizingLoadBalancingPolicy
implement ChainableLoadBalancingPolicy so the reporter can unwrap the
LB policy Cluster.Manager wraps at runtime.
Caps the report 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.
Hardens the other two ways reporting could break a connection rather
than merely fail to report:
- The fail-safe catch also covers InternalError, since customPolicy()
calls getClass().getSimpleName() on arbitrary user policy objects
(documented JDK edge case for certain synthetic classes). Not a bare
Error, so OutOfMemoryError/StackOverflowError still surface.
- The load balancing policy 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 the try/catch cannot
contain, because it hangs rather than throws.
A custom load balancing policy is now named after the policy the user
configured rather than PagingOptimizingLoadBalancingPolicy. Cluster
.Manager wraps every session's policy in that internal class, and it is
the outermost element of the chain, so every custom policy was reported
as {"type":"custom","name":"PagingOptimizingLoadBalancingPolicy"}.
Adds a JSON-Schema conformance test suite (mirroring the 4.x sibling
PR scylladb#968): the normative schema is shipped as a test resource and
validated via com.networknt:json-schema-validator (pinned to 1.5.x,
the last line still targeting Java 8), covering every discriminated-
union branch and optional group the 3.x reporter can emit, plus a
negative test proving additionalProperties=false is enforced.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
nikagra
added a commit
to nikagra/java-driver
that referenced
this pull request
Aug 3, 2026
Fills in the full DRIVER_CONFIG JSON report in the approved v2
cross-driver schema shape, replacing the stage-1 {"version":1}
placeholder. All groups are populated from Configuration and Policies
when the report is built, i.e. once per Cluster as it initializes.
connection-pool.desired-connections-count reports the core connections
per host rather than the maximum: HostConnectionPool opens core
connections when it initializes and only grows towards the maximum
under load, which is what the schema's "connections to open per host"
means. Both protocol-v3 defaults are 1, so this only shows on a tuned
pool -- where reporting the maximum was wrong in both directions,
overstating a configured core/max pair and falling back to the v3
default when only the core count was set.
Where a configured value falls outside what the schema can express, an
optional key or group is omitted rather than emitted as a number the
schema rejects: a disabled read timeout (connection.read and
control-plane.system-queries.timeout.client-side-ms), a negative
SO_LINGER, a non-positive socket buffer size. Omission is not always
available -- connection.connect.timeout-ms and
query-defaults.request.timeout-ms are required and positive-only, and
query-defaults.consistency is an enum without the serial levels, all
three reachable through unvalidated 3.x setters -- so those are
reported as-is and the limitation is documented on the class: the
reporter neither fabricates an in-range value, which would misreport a
setting an operator may have chosen on purpose, nor drops the whole
report over one field. Recorded as a cross-driver schema gap, to be
fixed the way control-plane.schema-agreement.timeout-ms already admits
0.
Adds public getters to DCAwareRoundRobinPolicy and
RackAwareRoundRobinPolicy needed to report node-location-preference
and dc-failover, and makes PagingOptimizingLoadBalancingPolicy
implement ChainableLoadBalancingPolicy so the reporter can unwrap the
LB policy Cluster.Manager wraps at runtime.
Caps the report 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.
Hardens the other two ways reporting could break a connection rather
than merely fail to report:
- The fail-safe catch also covers InternalError, since customPolicy()
calls getClass().getSimpleName() on arbitrary user policy objects
(documented JDK edge case for certain synthetic classes). Not a bare
Error, so OutOfMemoryError/StackOverflowError still surface.
- The load balancing policy 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 the try/catch cannot
contain, because it hangs rather than throws.
A custom load balancing policy is now named after the policy the user
configured rather than PagingOptimizingLoadBalancingPolicy. Cluster
.Manager wraps every session's policy in that internal class, and it is
the outermost element of the chain, so every custom policy was reported
as {"type":"custom","name":"PagingOptimizingLoadBalancingPolicy"}.
Adds a JSON-Schema conformance test suite (mirroring the 4.x sibling
PR scylladb#968): the normative schema is shipped as a test resource and
validated via com.networknt:json-schema-validator (pinned to 1.5.x,
the last line still targeting Java 8), covering every discriminated-
union branch and optional group the 3.x reporter can emit, plus a
negative test proving additionalProperties=false is enforced.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
nikagra
added a commit
to nikagra/java-driver
that referenced
this pull request
Aug 4, 2026
Fills in the full DRIVER_CONFIG JSON report in the approved v2
cross-driver schema shape, replacing the stage-1 {"version":1}
placeholder. All groups are populated from Configuration and Policies
when the report is built, i.e. once per Cluster as it initializes.
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; its datacenter and rack still show up in
node-location-preference. 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") and adaptive-ordering from LatencyAwarePolicy, the only
runtime observation a 3.x policy can reorder candidates on.
Where a configured value falls outside what the schema can express, an
optional key or group is omitted rather than emitted as a number the
schema rejects: a disabled connect timeout, a disabled read timeout
(connection.read and control-plane.system-queries.timeout
.client-side-ms), a negative SO_LINGER, a non-positive socket buffer
size, an unbounded page size. Omission is not always available, so
these required keys are left in the one state that is accurate:
- connection.requests.orphaned.max has no 3.x equivalent to report at
all. A request the driver stopped waiting for keeps its stream
identifier until the response arrives, with no configurable bound and
no connection replacement, so the key is omitted -- which its
required-ness then rejects. This is the one violation every report
carries.
- connection.requests.in-flight.max is capped at 32767 by the schema,
one below the 32768 stream identifiers protocol v3 provides and
PoolingOptions accepts.
- query-defaults.request.timeout-ms is positive-only, yet the read
timeout feeding it documents a non-positive value as "no timeout",
and query-defaults.consistency is an enum without the serial levels
that QueryOptions.setConsistencyLevel accepts unvalidated. Both
setters validate nothing.
Such a value is reported as-is and the limitation is documented on the
class: the reporter neither fabricates an in-range value -- which would
misreport a setting an operator may have chosen on purpose, or a policy
3.x does not implement -- nor drops the whole report over one field.
Recorded as a cross-driver schema gap, to be fixed the way
control-plane.schema-agreement.timeout-ms already admits 0.
Adds public getters to DCAwareRoundRobinPolicy,
RackAwareRoundRobinPolicy and TokenAwarePolicy needed to report
node-location-preference, dc-failover and load-distribution, and makes
PagingOptimizingLoadBalancingPolicy implement
ChainableLoadBalancingPolicy so the reporter can unwrap the LB policy
Cluster.Manager wraps at runtime.
Caps the report 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.
Hardens the other two ways reporting could break a connection rather
than merely fail to report:
- The fail-safe catch also covers InternalError, since customPolicy()
calls getClass().getSimpleName() on arbitrary user policy objects
(documented JDK edge case for certain synthetic classes). Not a bare
Error, so OutOfMemoryError/StackOverflowError still surface.
- The load balancing policy 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 the try/catch cannot
contain, because it hangs rather than throws.
A custom load balancing policy is now named after the policy the user
configured rather than PagingOptimizingLoadBalancingPolicy. Cluster
.Manager wraps every session's policy in that internal class, and it is
the outermost element of the chain, so every custom policy was reported
as {"type":"custom","name":"PagingOptimizingLoadBalancingPolicy"}. An
anonymous policy class falls back to its binary name, since it has no
simple name and the schema requires a non-empty one.
Adds a JSON-Schema conformance test suite (mirroring the 4.x sibling
PR scylladb#968): the normative schema is shipped as a test resource and
validated via com.networknt:json-schema-validator (pinned to 1.5.x,
the last line still targeting Java 8), covering every discriminated-
union branch and optional group the 3.x reporter can emit. Since one
required key has no value to report, the assertion is that a report
violates the schema in exactly the documented ways and no other, with
a test naming each gap and a negative test proving
additionalProperties=false is enforced.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
nikagra
added a commit
to nikagra/java-driver
that referenced
this pull request
Aug 4, 2026
Fills in the full DRIVER_CONFIG JSON report in the approved v2
cross-driver schema shape, replacing the stage-1 {"version":1}
placeholder. All groups are populated from Configuration and Policies
when the report is built, i.e. once per Cluster as it initializes.
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; its datacenter and rack still show up in
node-location-preference. 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") and adaptive-ordering from LatencyAwarePolicy, the only
runtime observation a 3.x policy can reorder candidates on.
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: a disabled connect timeout, a disabled read timeout
(connection.read and control-plane.system-queries.timeout
.client-side-ms), a negative SO_LINGER, a non-positive socket buffer
size, an unbounded page size, and a default serial consistency level
that is not serial -- QueryOptions, unlike Statement, does not check
that one. Omission is not always available, so these required keys are
left in the one state that is accurate:
- connection.requests.orphaned.max has no 3.x equivalent to report at
all. A request the driver stopped waiting for keeps its stream
identifier until the response arrives, with no configurable bound and
no connection replacement, so the key is omitted -- which its
required-ness then rejects. This is the one violation every report
carries.
- connection.requests.in-flight.max is bounded to 1..32767 by the
schema, while PoolingOptions accepts 0..32768 -- one above at the top
(protocol v3 provides 32768 stream identifiers) and one below at the
bottom. Only PoolingOptions.UNSET falls back to the protocol default,
so a limit of 0 an operator set deliberately is not reported as 1024.
- query-defaults.request.timeout-ms is positive-only, yet the read
timeout feeding it documents a non-positive value as "no timeout",
and query-defaults.consistency is an enum without the serial levels
that QueryOptions.setConsistencyLevel accepts unvalidated -- as it
does null, which leaves that key omitted for want of a level to
report. Both setters validate nothing.
Such a value is reported as-is and the limitation is documented on the
class: the reporter neither fabricates an in-range value -- which would
misreport a setting an operator may have chosen on purpose, or a policy
3.x does not implement -- nor drops the whole report over one field.
Recorded as a cross-driver schema gap, to be fixed the way
control-plane.schema-agreement.timeout-ms already admits 0.
Adds public getters to DCAwareRoundRobinPolicy,
RackAwareRoundRobinPolicy and TokenAwarePolicy needed to report
node-location-preference, dc-failover and load-distribution, and makes
PagingOptimizingLoadBalancingPolicy implement
ChainableLoadBalancingPolicy so the reporter can unwrap the LB policy
Cluster.Manager wraps at runtime.
Caps the report 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.
Hardens the other two ways reporting could break a connection rather
than merely fail to report:
- The fail-safe catch also covers InternalError, since customPolicy()
calls getClass().getSimpleName() on arbitrary user policy objects
(documented JDK edge case for certain synthetic classes). Not a bare
Error, so OutOfMemoryError/StackOverflowError still surface.
- The load balancing policy 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 the try/catch cannot
contain, because it hangs rather than throws.
A custom load balancing policy is now named after the policy the user
configured rather than PagingOptimizingLoadBalancingPolicy. Cluster
.Manager wraps every session's policy in that internal class, and it is
the outermost element of the chain, so every custom policy was reported
as {"type":"custom","name":"PagingOptimizingLoadBalancingPolicy"}. An
anonymous policy class falls back to its binary name, since it has no
simple name and the schema requires a non-empty one.
Adds a JSON-Schema conformance test suite (mirroring the 4.x sibling
PR scylladb#968): the normative schema is shipped as a test resource and
validated via com.networknt:json-schema-validator (pinned to 1.5.x,
the last line still targeting Java 8), covering every discriminated-
union branch and optional group the 3.x reporter can emit. Since one
required key has no value to report, the assertion is that a report
violates the schema in exactly the documented ways and no other, with
a test naming each gap and a negative test proving
additionalProperties=false is enforced.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
nikagra
added a commit
to nikagra/java-driver
that referenced
this pull request
Aug 5, 2026
Fills in the full DRIVER_CONFIG JSON report in the normative cross-driver
schema shape, replacing the stage-1 {"version":1} placeholder. All groups
are populated from Configuration and Policies when the report is built,
i.e. once per Cluster as it initializes.
Everything 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 also has an optional connection.node-preference, for a driver
that scopes its connection pools independently of its query routing. 3.x
has no such second knob -- one LoadBalancingPolicy decides both, since
distance(Host) governs whether a host is pooled at all -- so the
preference is reported once, under the policy it derives from, rather
than duplicated.
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; its
datacenter and rack still show up in query.load-balancing.node-preference.
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") and
fallback-to-non-preferred-nodes from either locality-aware policy's
used-hosts-per-remote-DC.
adaptive-ordering has no "enabled" flag and cannot carry an empty signal
list, so it is reported only when a LatencyAwarePolicy is in the chain --
latency being the only runtime observation a 3.x policy can reorder
candidates on. tls likewise has no "enabled" flag: the group's presence
is what says TLS is on.
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: a disabled connect timeout, a disabled read timeout (all
three of connection.read, control-plane.queries.system.timeout
.client-side-ms and query.defaults.request), a negative SO_LINGER, a
non-positive socket buffer size, an unbounded page size, and a default
serial consistency level that is not serial -- QueryOptions, unlike
Statement, does not check that one. Omission is not always available, so
these required keys are left in the one state that is accurate:
- connection.requests.orphaned.max has no 3.x equivalent to report at
all. A request the driver stopped waiting for keeps its stream
identifier until the response arrives, with no configurable bound and
no connection replacement, so the key is omitted -- which its
required-ness then rejects. This is the one violation every report
carries.
- connection.requests.in-flight.max is bounded to 1..32767 by the
schema, while PoolingOptions accepts 0..32768 -- one above at the top
(protocol v3 provides 32768 stream identifiers) and one below at the
bottom. Only PoolingOptions.UNSET falls back to the protocol default,
so a limit of 0 an operator set deliberately is not reported as 1024.
- query.defaults.consistency is an enum without the serial levels that
QueryOptions.setConsistencyLevel accepts unvalidated -- as it does
null, which leaves that key omitted for want of a level to report.
Such a value is reported as-is and the limitation is documented on the
class: the reporter neither fabricates an in-range value -- which would
misreport a setting an operator may have chosen on purpose, or a policy
3.x does not implement -- nor drops the whole report over one field.
Recorded as a cross-driver schema gap, to be fixed the way
control-plane.schema.agreement.timeout-ms already admits 0.
Adds public getters to DCAwareRoundRobinPolicy,
RackAwareRoundRobinPolicy and TokenAwarePolicy needed to report the node
preference, the non-preferred-node fallback and load-distribution, and
makes PagingOptimizingLoadBalancingPolicy implement
ChainableLoadBalancingPolicy so the reporter can unwrap the LB policy
Cluster.Manager wraps at runtime.
Caps the report 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.
Hardens the other two ways reporting could break a connection rather
than merely fail to report:
- The fail-safe catch also covers InternalError, since customPolicy()
calls getClass().getSimpleName() on arbitrary user policy objects
(documented JDK edge case for certain synthetic classes). Not a bare
Error, so OutOfMemoryError/StackOverflowError still surface.
- The load balancing policy 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 the try/catch cannot
contain, because it hangs rather than throws.
A custom load balancing policy is now named after the policy the user
configured rather than PagingOptimizingLoadBalancingPolicy. Cluster
.Manager wraps every session's policy in that internal class, and it is
the outermost element of the chain, so every custom policy was reported
as {"type":"custom","name":"PagingOptimizingLoadBalancingPolicy"}. An
anonymous policy class falls back to its binary name, since it has no
simple name and the schema requires a non-empty one.
Adds a JSON-Schema conformance test suite (mirroring the 4.x sibling
PR scylladb#968): the normative schema is shipped as a test resource and
validated via com.networknt:json-schema-validator (pinned to 1.5.x,
the last line still targeting Java 8), covering every discriminated-
union branch and optional group the 3.x reporter can emit. Since one
required key has no value to report, the assertion is that a report
violates the schema in exactly the documented ways and no other, with
a test naming the gap and a negative test proving
additionalProperties=false is enforced.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
nikagra
added a commit
to nikagra/java-driver
that referenced
this pull request
Aug 5, 2026
Fills in the full DRIVER_CONFIG JSON report in the normative cross-driver
schema shape, replacing the stage-1 {"version":1} placeholder. All groups
are populated from Configuration and Policies when the report is built,
i.e. once per Cluster as it initializes.
Everything 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 also has an optional connection.node-preference, for a driver
that scopes its connection pools independently of its query routing. 3.x
has no such second knob -- one LoadBalancingPolicy decides both, since
distance(Host) governs whether a host is pooled at all -- so the
preference is reported once, under the policy it derives from, rather
than duplicated.
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; its
datacenter and rack still show up in query.load-balancing.node-preference.
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") and
fallback-to-non-preferred-nodes from either locality-aware policy's
used-hosts-per-remote-DC.
adaptive-ordering has no "enabled" flag and cannot carry an empty signal
list, so it is reported only when a LatencyAwarePolicy is in the chain --
latency being the only runtime observation a 3.x policy can reorder
candidates on. tls likewise has no "enabled" flag: the group's presence
is what says TLS is on.
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: a disabled connect timeout, a disabled read timeout (all
three of connection.read, control-plane.queries.system.timeout
.client-side-ms and query.defaults.request), a negative SO_LINGER, a
non-positive socket buffer size, an unbounded page size, and a default
serial consistency level that is not serial -- QueryOptions, unlike
Statement, does not check that one. Two optional bounds are omitted for
the opposite reason -- 3.x has no such bound to report at all:
connection.reconnection.policy.max-attempts, since its reconnection
policies retry forever, and query.retry.policy.max-retries, since
DefaultRetryPolicy and DowngradingConsistencyRetryPolicy stop after one
attempt on read timeouts, write timeouts and unavailable errors but
leave onRequestError to try the next host until the query plan runs out.
Omission is not always available, so these required keys are left in the
one state that is accurate:
- connection.requests.orphaned.max has no 3.x equivalent to report at
all. A request the driver stopped waiting for keeps its stream
identifier until the response arrives, with no configurable bound and
no connection replacement, so the key is omitted -- which its
required-ness then rejects. This is the one violation every report
carries.
- connection.requests.in-flight.max is bounded to 1..32767 by the
schema, while PoolingOptions accepts 0..32768 -- one above at the top
(protocol v3 provides 32768 stream identifiers) and one below at the
bottom. Only PoolingOptions.UNSET falls back to the protocol default,
so a limit of 0 an operator set deliberately is not reported as 1024.
- query.defaults.consistency is an enum without the serial levels that
QueryOptions.setConsistencyLevel accepts unvalidated -- as it does
null, which leaves that key omitted for want of a level to report.
Such a value is reported as-is and the limitation is documented on the
class: the reporter neither fabricates an in-range value -- which would
misreport a setting an operator may have chosen on purpose, or a policy
3.x does not implement -- nor drops the whole report over one field.
Recorded as a cross-driver schema gap, to be fixed the way
control-plane.schema.agreement.timeout-ms already admits 0.
Adds public getters to DCAwareRoundRobinPolicy,
RackAwareRoundRobinPolicy and TokenAwarePolicy needed to report the node
preference, the non-preferred-node fallback and load-distribution, and
makes PagingOptimizingLoadBalancingPolicy implement
ChainableLoadBalancingPolicy so the reporter can unwrap the LB policy
Cluster.Manager wraps at runtime.
Caps the report 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.
Hardens the other two ways reporting could break a connection rather
than merely fail to report:
- The fail-safe catch also covers InternalError, since customPolicy()
calls getClass().getSimpleName() on arbitrary user policy objects
(documented JDK edge case for certain synthetic classes). Not a bare
Error, so OutOfMemoryError/StackOverflowError still surface.
- The load balancing policy 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 the try/catch cannot
contain, because it hangs rather than throws.
A custom load balancing policy is now named after the policy the user
configured rather than PagingOptimizingLoadBalancingPolicy. Cluster
.Manager wraps every session's policy in that internal class, and it is
the outermost element of the chain, so every custom policy was reported
as {"type":"custom","name":"PagingOptimizingLoadBalancingPolicy"}. An
anonymous policy class falls back to its binary name, since it has no
simple name and the schema requires a non-empty one.
Adds a JSON-Schema conformance test suite (mirroring the 4.x sibling
PR scylladb#968): the normative schema block is shipped verbatim as a test
resource and validated via com.networknt:json-schema-validator (1.5.x,
the last line still targeting Java 8), covering every discriminated-
union branch and optional group the 3.x reporter can emit. Since one
required key has no value to report, the assertion is that a report
violates the schema in exactly the documented ways and no other, with
a test naming the gap and a negative test proving
additionalProperties=false is enforced.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
nikagra
added a commit
to nikagra/java-driver
that referenced
this pull request
Aug 5, 2026
Fills in the full DRIVER_CONFIG JSON report in the normative cross-driver
schema shape, replacing the stage-1 {"version":1} placeholder. All groups
are populated from Configuration and Policies when the report is built,
i.e. once per Cluster as it initializes.
Everything 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 also has an optional connection.node-preference, for a driver
that scopes its connection pools independently of its query routing. 3.x
has no such second knob -- one LoadBalancingPolicy decides both, since
distance(Host) governs whether a host is pooled at all -- so the
preference is reported once, under the policy it derives from, rather
than duplicated.
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; its
datacenter and rack still show up in query.load-balancing.node-preference.
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") and
fallback-to-non-preferred-nodes from either locality-aware policy's
used-hosts-per-remote-DC.
adaptive-ordering has no "enabled" flag and cannot carry an empty signal
list, so it is reported only when a LatencyAwarePolicy is in the chain --
latency being the only runtime observation a 3.x policy can reorder
candidates on. tls likewise has no "enabled" flag: the group's presence
is what says TLS is on.
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: a disabled connect timeout, a disabled read timeout (all
three of connection.read, control-plane.queries.system.timeout
.client-side-ms and query.defaults.request), a negative SO_LINGER, a
non-positive socket buffer size, an unbounded page size, and a default
serial consistency level that is not serial -- QueryOptions, unlike
Statement, does not check that one. Two optional bounds are omitted for
the opposite reason -- 3.x has no such bound to report at all:
connection.reconnection.policy.max-attempts, since its reconnection
policies retry forever, and query.retry.policy.max-retries, since
DefaultRetryPolicy and DowngradingConsistencyRetryPolicy stop after one
attempt on read timeouts, write timeouts and unavailable errors but
leave onRequestError to try the next host until the query plan runs out.
Omission is not always available, so these required keys are left in the
one state that is accurate:
- connection.requests.orphaned.max has no 3.x equivalent to report at
all. A request the driver stopped waiting for keeps its stream
identifier until the response arrives, with no configurable bound and
no connection replacement, so the key is omitted -- which its
required-ness then rejects. This is the one violation every report
carries.
- connection.requests.in-flight.max is bounded to 1..32767 by the
schema, while PoolingOptions accepts 0..32768 -- one above at the top
(protocol v3 provides 32768 stream identifiers) and one below at the
bottom. Only PoolingOptions.UNSET falls back to the protocol default,
so a limit of 0 an operator set deliberately is not reported as 1024.
- query.defaults.consistency is an enum without the serial levels that
QueryOptions.setConsistencyLevel accepts unvalidated -- as it does
null, which leaves that key omitted for want of a level to report.
Such a value is reported as-is and the limitation is documented on the
class: the reporter neither fabricates an in-range value -- which would
misreport a setting an operator may have chosen on purpose, or a policy
3.x does not implement -- nor drops the whole report over one field.
Recorded as a cross-driver schema gap, to be fixed the way
control-plane.schema.agreement.timeout-ms already admits 0.
Adds public getters to DCAwareRoundRobinPolicy,
RackAwareRoundRobinPolicy and TokenAwarePolicy needed to report the node
preference, the non-preferred-node fallback and load-distribution, and
makes PagingOptimizingLoadBalancingPolicy implement
ChainableLoadBalancingPolicy so the reporter can unwrap the LB policy
Cluster.Manager wraps at runtime.
Caps the report 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.
Hardens the other two ways reporting could break a connection rather
than merely fail to report:
- The fail-safe catch also covers InternalError, since customPolicy()
calls getClass().getSimpleName() on arbitrary user policy objects
(documented JDK edge case for certain synthetic classes). Not a bare
Error, so OutOfMemoryError/StackOverflowError still surface.
- The load balancing policy 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 the try/catch cannot
contain, because it hangs rather than throws.
A custom load balancing policy is now named after the policy the user
configured rather than PagingOptimizingLoadBalancingPolicy. Cluster
.Manager wraps every session's policy in that internal class, and it is
the outermost element of the chain, so every custom policy was reported
as {"type":"custom","name":"PagingOptimizingLoadBalancingPolicy"}. An
anonymous policy class falls back to its binary name, since it has no
simple name and the schema requires a non-empty one.
Adds a JSON-Schema conformance test suite (mirroring the 4.x sibling
PR scylladb#968): the normative schema block is shipped verbatim as a test
resource and validated via com.networknt:json-schema-validator (1.5.x,
the last line still targeting Java 8), covering every discriminated-
union branch and optional group the 3.x reporter can emit. Since one
required key has no value to report, the assertion is that a report
violates the schema in exactly the documented ways and no other, with
a test naming the gap and a negative test proving
additionalProperties=false is enforced.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
nikagra
added a commit
to nikagra/java-driver
that referenced
this pull request
Aug 6, 2026
Fills in the full DRIVER_CONFIG JSON report in the normative cross-driver
schema shape, replacing the stage-1 {"version":1} placeholder. All groups
are populated from Configuration and Policies when the report is built,
i.e. once per Cluster as it initializes.
Everything 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 also has an optional connection.node-preference, for a driver
that scopes its connection pools independently of its query routing. 3.x
has no such second knob -- one LoadBalancingPolicy decides both, since
distance(Host) governs whether a host is pooled at all -- so the
preference is reported once, under the policy it derives from, rather
than duplicated.
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; its
datacenter and rack still show up in query.load-balancing.node-preference.
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").
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 -- distance() returns REMOTE, not IGNORED, for them -- so it
is always true there, remote datacenter hosts or not.
adaptive-ordering has no "enabled" flag and cannot carry an empty signal
list, so it is reported only when a LatencyAwarePolicy is in the chain --
latency being the only runtime observation a 3.x policy can reorder
candidates on. tls likewise has no "enabled" flag: the group's presence
is what says TLS is on.
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: a disabled connect timeout, a disabled read timeout (all
three of connection.read, control-plane.queries.system.timeout
.client-side-ms and query.defaults.request), a negative SO_LINGER, a
non-positive socket buffer size, an unbounded page size, and a default
serial consistency level that is not serial -- QueryOptions, unlike
Statement, does not check that one. Two optional bounds are omitted for
the opposite reason -- 3.x has no such bound to report at all:
connection.reconnection.policy.max-attempts, since its reconnection
policies retry forever, and query.retry.policy.max-retries, since no
single number describes a 3.x retry policy. Both built-ins are
parameterless singletons, and while they stop after one attempt on a
read timeout, a write timeout or an unavailable error -- all three
sharing one counter, so one retry between them rather than one each --
onRequestError leaves nbRetry unread and keeps trying the next host
until the query plan runs out. Which of the two applies is decided per
statement rather than by configuration: RequestHandler only consults
onRequestError and onWriteTimeout for an idempotent statement, so the
same policy bounds a non-idempotent request at one retry and an
idempotent one at the length of the query plan, and setIdempotent
overrides the reported query.defaults.idempotence per statement.
Omission is not always available, so these required keys are left in the
one state that is accurate:
- connection.requests.orphaned.max has no 3.x equivalent to report at
all. A request the driver stopped waiting for keeps its stream
identifier until the response arrives, with no configurable bound and
no connection replacement, so the key is omitted -- which its
required-ness then rejects. This is the one violation every report
carries.
- connection.requests.in-flight.max is bounded to 1..32767 by the
schema, while PoolingOptions accepts 0..32768 -- one above at the top
(protocol v3 provides 32768 stream identifiers) and one below at the
bottom. Only PoolingOptions.UNSET falls back to the protocol default,
so a limit of 0 an operator set deliberately is not reported as 1024.
- query.defaults.consistency is an enum without the serial levels that
QueryOptions.setConsistencyLevel accepts unvalidated.
- query.speculative-execution.policy.percentile is bounded to 0..100
exclusive, while PercentileSpeculativeExecutionPolicy accepts a
percentile of 0.
Such a value is reported as-is and the limitation is documented on the
class: the reporter neither fabricates an in-range value -- which would
misreport a setting an operator may have chosen on purpose, or a policy
3.x does not implement -- nor drops the whole report over one field.
Recorded as a cross-driver schema gap, to be fixed the way
control-plane.schema.agreement.timeout-ms already admits 0.
QueryOptions.setConsistencyLevel now rejects null. Every query needs a
consistency level, so a null default already failed any statement that
did not set one of its own -- RoundRobinPolicy and DCAwareRoundRobin
call isDCLocal() on it while building a query plan -- which turned a
schema-required key into a missing one. The reporter keeps omitting a
null it is handed anyway: the field is private, so only a QueryOptions
subclass overriding the getter can still produce one, and letting it
through would throw and cost the whole report rather than one key.
Adds the public getters the report needs: local DC/rack, their explicit
flags and used-hosts-per-remote-DC on DCAwareRoundRobinPolicy, the same
minus used-hosts-per-remote-DC on RackAwareRoundRobinPolicy, replica
ordering on TokenAwarePolicy, and max-executions plus the delay or
percentile on the two built-in speculative execution policies -- whose
parameters are immutable and land in the schema's range exactly, so
they are reported as constant/percentile rather than as custom. Also
makes PagingOptimizingLoadBalancingPolicy implement
ChainableLoadBalancingPolicy so the reporter can unwrap the LB policy
Cluster.Manager wraps at runtime.
Caps the report 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.
Hardens the other two ways reporting could break a connection rather
than merely fail to report:
- The fail-safe catch also covers InternalError, since customPolicy()
calls getClass().getSimpleName() on arbitrary user policy objects
(documented JDK edge case for certain synthetic classes). Not a bare
Error, so OutOfMemoryError/StackOverflowError still surface.
- The load balancing policy 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 the try/catch cannot
contain, because it hangs rather than throws.
A custom load balancing policy is now named after the policy the user
configured rather than PagingOptimizingLoadBalancingPolicy. Cluster
.Manager wraps every session's policy in that internal class, and it is
the outermost element of the chain, so every custom policy was reported
as {"type":"custom","name":"PagingOptimizingLoadBalancingPolicy"}. An
anonymous policy class falls back to its binary name, since it has no
simple name and the schema requires a non-empty one.
Adds a JSON-Schema conformance test suite (mirroring the 4.x sibling
PR scylladb#968): the normative schema block is shipped verbatim as a test
resource and validated via com.networknt:json-schema-validator (1.5.x,
the last line still targeting Java 8), covering every discriminated-
union branch and optional group the 3.x reporter can emit. Since one
required key has no value to report, the assertion is that a report
violates the schema in exactly the documented ways and no other, with
a test naming the gap and a negative test proving
additionalProperties=false is enforced.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
nikagra
added a commit
to nikagra/java-driver
that referenced
this pull request
Aug 6, 2026
Fills in the full DRIVER_CONFIG JSON report in the normative cross-driver
schema shape, replacing the stage-1 {"version":1} placeholder. All groups
are populated from Configuration and Policies when the report is built,
i.e. once per Cluster as it initializes.
Everything 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 also has an optional connection.node-preference, for a driver
that scopes its connection pools independently of its query routing. 3.x
has no such second knob -- one LoadBalancingPolicy decides both, since
distance(Host) governs whether a host is pooled at all -- so the
preference is reported once, under the policy it derives from, rather
than duplicated.
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; its
datacenter and rack still show up in query.load-balancing.node-preference.
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").
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 -- distance() returns REMOTE, not IGNORED, for them -- so it
is always true there, remote datacenter hosts or not.
adaptive-ordering has no "enabled" flag and cannot carry an empty signal
list, so it is reported only when a LatencyAwarePolicy is in the chain --
latency being the only runtime observation a 3.x policy can reorder
candidates on. tls likewise has no "enabled" flag: the group's presence
is what says TLS is on.
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: a disabled connect timeout, a disabled read timeout (all
three of connection.read, control-plane.queries.system.timeout
.client-side-ms and query.defaults.request), a negative SO_LINGER, a
non-positive socket buffer size, an unbounded page size, and a default
serial consistency level that is not serial -- QueryOptions, unlike
Statement, does not check that one. Two optional bounds are omitted for
the opposite reason -- 3.x has no such bound to report at all:
connection.reconnection.policy.max-attempts, since its reconnection
policies retry forever (the maxAttempts field ExponentialReconnection
Policy carries is an overflow guard on the doubling, not a give-up
bound: past it nextDelayMs() keeps returning maxDelayMs), and
query.retry.policy.max-retries, since no
single number describes a 3.x retry policy. Both built-ins are
parameterless singletons, and while they stop after one attempt on a
read timeout, a write timeout or an unavailable error -- all three
sharing one counter, so one retry between them rather than one each --
onRequestError leaves nbRetry unread and keeps trying the next host
until the query plan runs out. Which of the two applies is decided per
statement rather than by configuration: RequestHandler only consults
onRequestError and onWriteTimeout for an idempotent statement, so the
same policy bounds a non-idempotent request at one retry and an
idempotent one at the length of the query plan, and setIdempotent
overrides the reported query.defaults.idempotence per statement.
Two more keys are omitted for a third reason -- the schema admits only a
boolean, and 3.x cannot observe which one applies.
query.defaults.client-timestamps is false for ServerSideTimestamp
Generator, whose next() always returns Long.MIN_VALUE, and true for an
AbstractMonotonicTimestampGenerator, which never can; any other
generator makes that a per-call decision, so whether timestamps are
assigned client-side is not a property of the configuration at all.
connection.tls.hostname-verification is true for SniSSLOptions, the
driver's only setEndpointIdentificationAlgorithm call, and omitted for
every other SSLOptions, which builds its engine from a user SSLContext
or hands the whole handler to Netty. Both keys are documented as absent
exactly when the behavior is unknown, which is this case. The tls group
can therefore be empty -- its presence is still what reports TLS is on.
Omission is not always available, so these required keys are left in the
one state that is accurate:
- connection.requests.orphaned.max has no 3.x equivalent to report at
all. A request the driver stopped waiting for keeps its stream
identifier until the response arrives, with no configurable bound and
no connection replacement, so the key is omitted -- which its
required-ness then rejects. This is the one violation every report
carries.
- connection.requests.in-flight.max must be positive, while
PoolingOptions also accepts 0. Only PoolingOptions.UNSET falls back to
a protocol default, so a limit of 0 an operator set deliberately is
not reported as 1024.
- query.speculative-execution.policy.percentile is bounded to 0..100
exclusive, while PercentileSpeculativeExecutionPolicy accepts a
percentile of 0.
Such a value is reported as-is and the limitation is documented on the
class: the reporter neither fabricates an in-range value -- which would
misreport a setting an operator may have chosen on purpose, or a policy
3.x does not implement -- nor drops the whole report over one field.
Recorded as a cross-driver schema gap, to be fixed the way
control-plane.schema.agreement.timeout-ms already admits 0.
QueryOptions.setConsistencyLevel now rejects null -- a behavior change
to a public setter. Every query needs a consistency level, so a null
default already failed any statement that did not set one of its own:
SessionManager falls back to it for every request, and
CBUtil.writeConsistencyLevel then dereferences it to write the frame.
That turned a schema-required key into a missing one for a
configuration that could never work. setSerialConsistencyLevel is
deliberately left as it is: the schema makes serial-consistency
optional, so a null there is faithfully reported as an omission rather
than as a missing required key. The reporter keeps omitting a
null it is handed anyway: the field is private, so only a QueryOptions
subclass overriding the getter can still produce one, and letting it
through would throw and cost the whole report rather than one key.
Adds the public getters the report needs: local DC/rack, their explicit
flags and used-hosts-per-remote-DC on DCAwareRoundRobinPolicy, the same
minus used-hosts-per-remote-DC on RackAwareRoundRobinPolicy, replica
ordering on TokenAwarePolicy, and max-executions plus the delay or
percentile on the two built-in speculative execution policies -- whose
parameters are immutable and land in the schema's range exactly, so
they are reported as constant/percentile rather than as custom. Also
makes PagingOptimizingLoadBalancingPolicy implement
ChainableLoadBalancingPolicy so the reporter can unwrap the LB policy
Cluster.Manager wraps at runtime.
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 and the reference row for
everything above it. 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.
Caps the report 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.
Hardens the other two ways reporting could break a connection rather
than merely fail to report:
- The fail-safe catch also covers InternalError, since customPolicy()
calls getClass().getSimpleName() on arbitrary user policy objects
(documented JDK edge case for certain synthetic classes). Not a bare
Error, so OutOfMemoryError/StackOverflowError still surface.
- The load balancing policy 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 the try/catch cannot
contain, because it hangs rather than throws.
A custom load balancing policy is now named after the policy the user
configured rather than PagingOptimizingLoadBalancingPolicy. Cluster
.Manager wraps every session's policy in that internal class, and it is
the outermost element of the chain, so every custom policy was reported
as {"type":"custom","name":"PagingOptimizingLoadBalancingPolicy"}. An
anonymous policy class falls back to its binary name, since it has no
simple name and the schema requires a non-empty one.
Adds a JSON-Schema conformance test suite (mirroring the 4.x sibling
PR scylladb#968): the normative schema block is shipped verbatim as a test
resource -- design-doc revision v5, whose report version field is still
1 -- and validated via com.networknt:json-schema-validator (1.5.x,
the last line still targeting Java 8), covering every discriminated-
union branch and optional group the 3.x reporter can emit. Since one
required key has no value to report, the assertion is that a report
violates the schema in exactly the documented ways and no other, with
a test naming the gap and a negative test proving
additionalProperties=false is enforced.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
nikagra
added a commit
to nikagra/java-driver
that referenced
this pull request
Aug 10, 2026
Fills in the full DRIVER_CONFIG JSON report in the normative cross-driver
schema shape, replacing the stage-1 {"version":1} placeholder. All groups
are populated from Configuration and Policies when the report is built,
i.e. once per Cluster as it initializes.
Everything 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 those hosts are still pooled and 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; its
datacenter and rack still show up in query.load-balancing.node-preference.
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").
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 -- distance() returns REMOTE, not IGNORED, for them -- so it
is always true there, remote datacenter hosts or not.
adaptive-ordering has no "enabled" flag and cannot carry an empty signal
list, so it is reported only when a LatencyAwarePolicy is in the chain --
latency being the only runtime observation a 3.x policy can reorder
candidates on. tls likewise has no "enabled" flag: the group's presence
is what says TLS is on.
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: a disabled connect timeout, a disabled read timeout (all
three of connection.read, control-plane.queries.system.timeout
.client-side-ms and query.defaults.request), a negative SO_LINGER, a
non-positive socket buffer size, an unbounded page size, and a default
serial consistency level that is not serial -- QueryOptions, unlike
Statement, does not check that one. Two optional bounds are omitted for
the opposite reason -- 3.x has no such bound to report at all:
connection.reconnection.policy.max-attempts, since its reconnection
policies retry forever (the maxAttempts field ExponentialReconnection
Policy carries is an overflow guard on the doubling, not a give-up
bound: past it nextDelayMs() keeps returning maxDelayMs), and
query.retry.policy.max-retries, since no
single number describes a 3.x retry policy. Both built-ins are
parameterless singletons, and while they stop after one attempt on a
read timeout, a write timeout or an unavailable error -- all three
sharing one counter, so one retry between them rather than one each --
onRequestError leaves nbRetry unread and keeps trying the next host
until the query plan runs out. Which of the two applies is decided per
statement rather than by configuration: RequestHandler only consults
onRequestError and onWriteTimeout for an idempotent statement, so the
same policy bounds a non-idempotent request at one retry and an
idempotent one at the length of the query plan, and setIdempotent
overrides the reported query.defaults.idempotence per statement.
Two more keys are omitted for a third reason -- the schema admits only a
boolean, and 3.x cannot observe which one applies.
query.defaults.client-timestamps is false for ServerSideTimestamp
Generator, whose next() always returns Long.MIN_VALUE, and true for an
AbstractMonotonicTimestampGenerator, which never can; any other
generator makes that a per-call decision, so whether timestamps are
assigned client-side is not a property of the configuration at all.
connection.tls.hostname-verification is true for SniSSLOptions, the
driver's only setEndpointIdentificationAlgorithm call, and omitted for
every other SSLOptions, which builds its engine from a user SSLContext
or hands the whole handler to Netty. Both keys are documented as absent
exactly when the behavior is unknown, which is this case. The tls group
can therefore be empty -- its presence is still what reports TLS is on.
Omission is not always available, so these required keys are left in the
one state that is accurate:
- connection.requests.orphaned.max has no 3.x equivalent to report at
all. A request the driver stopped waiting for keeps its stream
identifier until the response arrives, with no configurable bound and
no connection replacement, so the key is omitted -- which its
required-ness then rejects. This is the one violation every report
carries.
- connection.requests.in-flight.max must be positive, while
PoolingOptions also accepts 0. Only PoolingOptions.UNSET falls back to
a protocol default, so a limit of 0 an operator set deliberately is
not reported as 1024.
- query.speculative-execution.policy.percentile is bounded to 0..100
exclusive, while PercentileSpeculativeExecutionPolicy accepts a
percentile of 0.
Such a value is reported as-is and the limitation is documented on the
class: the reporter neither fabricates an in-range value -- which would
misreport a setting an operator may have chosen on purpose, or a policy
3.x does not implement -- nor drops the whole report over one field.
Recorded as a cross-driver schema gap, to be fixed the way
control-plane.schema.agreement.timeout-ms already admits 0.
QueryOptions.setConsistencyLevel now rejects null -- a behavior change
to a public setter. Every query needs a consistency level, so a null
default already failed any statement that did not set one of its own:
SessionManager falls back to it for every request, and
CBUtil.writeConsistencyLevel then dereferences it to write the frame.
That turned a schema-required key into a missing one for a
configuration that could never work. setSerialConsistencyLevel is
deliberately left as it is: the schema makes serial-consistency
optional, so a null there is faithfully reported as an omission rather
than as a missing required key. The reporter keeps omitting a
null it is handed anyway: the field is private, so only a QueryOptions
subclass overriding the getter can still produce one, and letting it
through would throw and cost the whole report rather than one key.
Adds the public getters the report needs: local DC/rack, their explicit
flags and used-hosts-per-remote-DC on DCAwareRoundRobinPolicy, the same
minus used-hosts-per-remote-DC on RackAwareRoundRobinPolicy, replica
ordering on TokenAwarePolicy, and max-executions plus the delay or
percentile on the two built-in speculative execution policies -- whose
parameters are immutable and land in the schema's range exactly, so
they are reported as constant/percentile rather than as custom. Also
makes PagingOptimizingLoadBalancingPolicy implement
ChainableLoadBalancingPolicy so the reporter can unwrap the LB policy
Cluster.Manager wraps at runtime.
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 and the reference row for
everything above it. 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.
Caps the report 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.
Hardens the other two ways reporting could break a connection rather
than merely fail to report:
- The fail-safe catch also covers InternalError, since customPolicy()
calls getClass().getSimpleName() on arbitrary user policy objects
(documented JDK edge case for certain synthetic classes). Not a bare
Error, so OutOfMemoryError/StackOverflowError still surface.
- The load balancing policy 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 the try/catch cannot
contain, because it hangs rather than throws.
A custom load balancing policy is now named after the policy the user
configured rather than PagingOptimizingLoadBalancingPolicy. Cluster
.Manager wraps every session's policy in that internal class, and it is
the outermost element of the chain, so every custom policy was reported
as {"type":"custom","name":"PagingOptimizingLoadBalancingPolicy"}. An
anonymous policy class falls back to its binary name, since it has no
simple name and the schema requires a non-empty one.
Adds a JSON-Schema conformance test suite (mirroring the 4.x sibling
PR scylladb#968): the normative schema block is shipped verbatim as a test
resource -- design-doc revision v5, whose report version field is still
1 -- and validated via com.networknt:json-schema-validator (1.5.x,
the last line still targeting Java 8), covering every discriminated-
union branch and optional group the 3.x reporter can emit. Since one
required key has no value to report, the assertion is that a report
violates the schema in exactly the documented ways and no other, with
a test naming the gap and a negative test proving
additionalProperties=false is enforced.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
nikagra
added a commit
to nikagra/java-driver
that referenced
this pull request
Aug 11, 2026
Fills in the full DRIVER_CONFIG JSON report in the normative cross-driver
schema shape, replacing the stage-1 {"version":1} placeholder. All groups
are populated from Configuration and Policies when the report is built,
i.e. once per Cluster as it initializes.
Everything 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 those hosts are still pooled and 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; its
datacenter and rack still show up in query.load-balancing.node-preference.
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").
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 -- distance() returns REMOTE, not IGNORED, for them -- so it
is always true there, remote datacenter hosts or not.
adaptive-ordering has no "enabled" flag and cannot carry an empty signal
list, so it is reported only when a LatencyAwarePolicy is in the chain --
latency being the only runtime observation a 3.x policy can reorder
candidates on. tls likewise has no "enabled" flag: the group's presence
is what says TLS is on.
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: a disabled connect timeout, a disabled read timeout (all
three of connection.read, control-plane.queries.system.timeout
.client-side-ms and query.defaults.request), a negative SO_LINGER, a
non-positive socket buffer size, an unbounded page size, and a default
serial consistency level that is not serial -- QueryOptions, unlike
Statement, does not check that one. Two optional bounds are omitted for
the opposite reason -- 3.x has no such bound to report at all:
connection.reconnection.policy.max-attempts, since its reconnection
policies retry forever (the maxAttempts field ExponentialReconnection
Policy carries is an overflow guard on the doubling, not a give-up
bound: past it nextDelayMs() keeps returning maxDelayMs), and
query.retry.policy.max-retries, since no
single number describes a 3.x retry policy. Both built-ins are
parameterless singletons, and while they stop after one attempt on a
read timeout, a write timeout or an unavailable error -- all three
sharing one counter, so one retry between them rather than one each --
onRequestError leaves nbRetry unread and keeps trying the next host
until the query plan runs out. Which of the two applies is decided per
statement rather than by configuration: RequestHandler only consults
onRequestError and onWriteTimeout for an idempotent statement, so the
same policy bounds a non-idempotent request at one retry and an
idempotent one at the length of the query plan, and setIdempotent
overrides the reported query.defaults.idempotence per statement.
Two more keys are omitted for a third reason -- the schema admits only a
boolean, and 3.x cannot observe which one applies.
query.defaults.client-timestamps is false for ServerSideTimestamp
Generator, whose next() always returns Long.MIN_VALUE, and true for an
AbstractMonotonicTimestampGenerator, which never can; any other
generator makes that a per-call decision, so whether timestamps are
assigned client-side is not a property of the configuration at all.
connection.tls.hostname-verification is true for SniSSLOptions, the
driver's only setEndpointIdentificationAlgorithm call, and omitted for
every other SSLOptions, which builds its engine from a user SSLContext
or hands the whole handler to Netty. Both keys are documented as absent
exactly when the behavior is unknown, which is this case. The tls group
can therefore be empty -- its presence is still what reports TLS is on.
Omission is not always available, so these required keys are left in the
one state that is accurate:
- connection.requests.orphaned.max has no 3.x equivalent to report at
all. A request the driver stopped waiting for keeps its stream
identifier until the response arrives, with no configurable bound and
no connection replacement, so the key is omitted -- which its
required-ness then rejects. This is the one violation every report
carries.
- connection.requests.in-flight.max must be positive, while
PoolingOptions also accepts 0. Only PoolingOptions.UNSET falls back to
a protocol default, so a limit of 0 an operator set deliberately is
not reported as 1024.
- query.speculative-execution.policy.percentile is bounded to 0..100
exclusive, while PercentileSpeculativeExecutionPolicy accepts a
percentile of 0.
Such a value is reported as-is and the limitation is documented on the
class: the reporter neither fabricates an in-range value -- which would
misreport a setting an operator may have chosen on purpose, or a policy
3.x does not implement -- nor drops the whole report over one field.
Recorded as a cross-driver schema gap, to be fixed the way
control-plane.schema.agreement.timeout-ms already admits 0.
QueryOptions.setConsistencyLevel now rejects null -- a behavior change
to a public setter. Every query needs a consistency level, so a null
default already failed any statement that did not set one of its own:
SessionManager falls back to it for every request, and
CBUtil.writeConsistencyLevel then dereferences it to write the frame.
That turned a schema-required key into a missing one for a
configuration that could never work. setSerialConsistencyLevel is
deliberately left as it is: the schema makes serial-consistency
optional, so a null there is faithfully reported as an omission rather
than as a missing required key. The reporter keeps omitting a
null it is handed anyway: the field is private, so only a QueryOptions
subclass overriding the getter can still produce one, and letting it
through would throw and cost the whole report rather than one key.
Adds the public getters the report needs: local DC/rack, their explicit
flags and used-hosts-per-remote-DC on DCAwareRoundRobinPolicy, the same
minus used-hosts-per-remote-DC on RackAwareRoundRobinPolicy, replica
ordering on TokenAwarePolicy, and max-executions plus the delay or
percentile on the two built-in speculative execution policies -- whose
parameters are immutable and land in the schema's range exactly, so
they are reported as constant/percentile rather than as custom. Also
makes PagingOptimizingLoadBalancingPolicy implement
ChainableLoadBalancingPolicy so the reporter can unwrap the LB policy
Cluster.Manager wraps at runtime.
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 and the reference row for
everything above it. 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.
Caps the report 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.
Hardens the other two ways reporting could break a connection rather
than merely fail to report:
- The fail-safe catch also covers InternalError, since customPolicy()
calls getClass().getSimpleName() on arbitrary user policy objects
(documented JDK edge case for certain synthetic classes). Not a bare
Error, so OutOfMemoryError/StackOverflowError still surface.
- The load balancing policy 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 the try/catch cannot
contain, because it hangs rather than throws.
A custom load balancing policy is now named after the policy the user
configured rather than PagingOptimizingLoadBalancingPolicy. Cluster
.Manager wraps every session's policy in that internal class, and it is
the outermost element of the chain, so every custom policy was reported
as {"type":"custom","name":"PagingOptimizingLoadBalancingPolicy"}. An
anonymous policy class falls back to its binary name, since it has no
simple name and the schema requires a non-empty one.
Adds a JSON-Schema conformance test suite (mirroring the 4.x sibling
PR scylladb#968): the normative schema block is shipped verbatim as a test
resource -- design-doc revision v5, whose report version field is still
1 -- and validated via com.networknt:json-schema-validator (1.5.x,
the last line still targeting Java 8), covering every discriminated-
union branch and optional group the 3.x reporter can emit. Since one
required key has no value to report, the assertion is that a report
violates the schema in exactly the documented ways and no other, with
a test naming the gap and a negative test proving
additionalProperties=false is enforced.
The report is now built behind a guard at its one call site, so a
classpath without Jackson cannot break connecting. Stage 1 made
jackson-core/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 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 -- so a classpath that merely lacks an
optional serializer went from "the report is skipped" to "no connection
can be established", the inverse of the invariant this class is written
around. Connection.Factory.buildDriverConfigReport now catches
LinkageError -- not just NoClassDefFoundError, so a version-mismatched
Jackson surfacing as ExceptionInInitializerError is covered too, where
probing one class name would pass and still fail -- and reports nothing,
logging at WARN since reporting ships enabled and nobody opted in. Same
fallback SnappyCompressor already applies for its own optional library,
and no contradiction with buildReport() deliberately not catching bare
Error: that is about report building never masking a real JVM failure,
this is a call site tolerating a missing optional dependency.
Both node preference slots are documented as 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, and 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 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
nikagra
added a commit
to nikagra/java-driver
that referenced
this pull request
Aug 11, 2026
…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 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
nikagra
added a commit
to nikagra/java-driver
that referenced
this pull request
Aug 11, 2026
…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 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
nikagra
added a commit
to nikagra/java-driver
that referenced
this pull request
Aug 11, 2026
…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 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
dkropachev
pushed a commit
that referenced
this pull request
Aug 13, 2026
…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 #968, gocql #964 and csharp-driver #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 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bumps ch.qos.logback:logback-classic from 1.2.3 to 1.3.12.
Commits
0df4ec1prepare release 1.3.12189af50ensure JDK 8 compatibility14a71d0cater for array size marked with -1b8eac23prevent DOS attacks using on malicious serialized inputd87dd12further support for Virtual threads, issues 737034aaeeadd support for Virtual threadsd6294e5parameterizable invocation gate delay3b91f6dminor refactoringd94ebecfix guthub issue 715c76b303minor refactoring for better readabilityDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting
@dependabot rebase.Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
@dependabot rebasewill rebase this PR@dependabot recreatewill recreate this PR, overwriting any edits that have been made to it@dependabot mergewill merge this PR after your CI passes on it@dependabot squash and mergewill squash and merge this PR after your CI passes on it@dependabot cancel mergewill cancel a previously requested merge and block automerging@dependabot reopenwill reopen this PR if it is closed@dependabot closewill close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually@dependabot show <dependency name> ignore conditionswill show all of the ignore conditions of the specified dependency@dependabot ignore this major versionwill close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this minor versionwill close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this dependencywill close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)You can disable automated security fix PRs for this repo from the Security Alerts page.