Skip to content

fix(cluster): name the sharding-state shard the way the server sends it - #622

Open
dudanogueira wants to merge 1 commit into
mainfrom
fix/sharding-state-shard-name
Open

fix(cluster): name the sharding-state shard the way the server sends it#622
dudanogueira wants to merge 1 commit into
mainfrom
fix/sharding-state-shard-name

Conversation

@dudanogueira

Copy link
Copy Markdown

Motivation

ShardReplica has no @SerializedName on either component, so Gson looks for the field's own name — shardName — while the server sends shard:

// entities/models/replication_shard_replicas.go
Replicas []string `json:"replicas"`
Shard    string   `json:"shard,omitempty"`

The result is null on every server version, so a sharding-state response cannot say which shard each replica set belongs to.

This is not Gson's default FIELD policy doing something surprising — the client installs its own strategy (JSON.java:74), and PojoDescriptor.propertyName honours only the ORM @Property annotation before falling back to the field name. replicas matches purely because the field name and the wire name coincide.

ClusterITest#test_shardingState never noticed because it only asserts that two shard lists differ; nothing reads the name.

Approach

Annotate both components explicitly, matching the sibling records in this package (Shard, ShardingState, Replication), which annotate every component.

The Java component keeps the name shardName@SerializedName bridges it, so there is no reason to make this a breaking rename. replicas is annotated too: it is a no-op today, but it stops the record depending on a coincidence between the field name and the wire name.

Rejected: renaming the component to shard. It would break callers to no benefit, and shardName is the clearer Java name.

No alternate spelling — nothing was ever stored or sent as shardName, so this is the #612 case rather than the #610 one.

Key areas for review

  • Annotating replicas is defensive rather than a fix. Say if you would rather this PR touched only the broken component.
  • ShardingState and ListShardsResponse were already fully annotated, so the fix is confined to this one record.

Testing

Unit — one round-trip row in JSONTest.testCases() covering a ShardingState carrying one ShardReplica, which drives both test_serialize and test_deserialize.

Verified the test fails without the fix, in both directions — the read side being the one that matters:

expected:<...rdReplica[shardName=[s1], replicas=[node1, n...>
 but was:<...rdReplica[shardName=[null], replicas=[node1, n...>

expected:<...s","shards":[{"shard[]":"s1","replicas":["...>
 but was:<...s","shards":[{"shard[Name]":"s1","replicas":["...>

No integration test: GET /replication/sharding-state answers 501 on a single-node server, so an assertion on the name needs the multi-node harness. ClusterITest#test_shardingState already runs there and would be the place for one — happy to add .extracting(ShardReplica::shardName).doesNotContainNull() if you would like it covered end to end.

Locally green: 384 unit tests.

Breaking changes

None. The Java component name and the accessor are unchanged; only the wire key the record asks for changes, and the old key never matched anything the server sends.

Conflict note

Adds a row at the end of JSONTest.testCases(); #620 adds one in the same place. Whichever merges second wants a trivial rebase — same file, adjacent rows, no shared lines otherwise.

Closes #621

🤖 Generated with Claude Code

https://claude.ai/code/session_01HNeKV7TAYZGDyT9agqJwUf

ShardReplica carried no @SerializedName, so Gson looked for the field's
own name, shardName. The server sends "shard"
(entities/models/replication_shard_replicas.go), so the component was null
on every server version and a sharding-state response could not identify
its shards.

The client installs its own field-naming strategy
(JSON.java:74 -> PropertyFieldNamingStrategy -> PojoDescriptor.propertyName),
which honours only the ORM @Property annotation and otherwise returns the
field name -- so the expected key really was "shardName". "replicas"
matched by coincidence, the field name and the wire name agreeing; it is
annotated here too so the record no longer depends on that.

The Java component keeps its name: @SerializedName bridges it without a
breaking rename.

No alternate spelling -- nothing was ever stored or sent as "shardName".

Closes #621

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HNeKV7TAYZGDyT9agqJwUf

@orca-security-eu orca-security-eu Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Orca Security Scan Summary

Status Check Issues by priority
Passed Passed Infrastructure as Code high 0   medium 0   low 0   info 0 View in Orca
Passed Passed SAST high 0   medium 0   low 0   info 0 View in Orca
Passed Passed Secrets high 0   medium 0   low 0   info 0 View in Orca
Passed Passed Vulnerabilities high 0   medium 0   low 0   info 0 View in Orca

@bevzzz

bevzzz commented Sep 10, 2026

Copy link
Copy Markdown
Collaborator

Please remove all comments from this PR and trim the PR description to what is strictly relevant.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

v6: ShardReplica.shardName has no @SerializedName, so the shard is always null

2 participants