Conversation
…plicate group routes When a batch contains two identical group MatchRoutes (protobuf value equality collapses them into one map entry, keeping only the later index), the earlier index remains null in the Code[] array and batchBuilder.addCode(code) throws NPE. The exception escapes before MutationResult is returned, but rangeWriter.done() still commits the buffered writes - leaving route cache / range fact inconsistent with the KV store until the cache expires. Normal routes are unaffected: that branch explicitly assigns codes[i] = OK for every index. The Group branch was missed. Record all positions for a route (List<Integer> instead of Integer) and assign the computed code to every recorded index. The same change applies to batchRemoveRoute (delGroupMatchRecords). Regression test: testAddGroupRouteDuplicatedInOneBatchAllPositionsGetOk. Control experiment: fails on unfixed code (NPE), passes with the fix. Full DistWorkerCoProcTest (18) passes.
ImDanXie
force-pushed
the
fix/dist-dup-group-route
branch
from
September 24, 2026 14:36
dd7a263 to
966a33d
Compare
…unmatch path) Symmetric regression test for batchRemoveRoute: two identical group MatchRoutes in the same tenant batch. The reader returns a RouteGroup protobuf containing the receiver so the removal path is exercised. Without the fix, the earlier index remains null and the NPE path is the same as in the add path. Control: both tests fail on unfixed code.
ImDanXie
force-pushed
the
fix/dist-dup-group-route
branch
from
September 24, 2026 14:40
966a33d to
2a9e2e6
Compare
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.
Fixes #299
Summary
When a tenant batch contains two identical group (shared subscription) MatchRoutes, batchAddRoute throws NullPointerException and leaves the route cache inconsistent with the KV store.
Baseline: main @ eef5e3a.
Root cause
Group routes record "route to its index in the request" in a Map of MatchRoute to Integer. MatchRoute is a protobuf message and compares by value, so two identical group routes in the same batch collapse into a single entry, keeping only the later index. The earlier index remains null in the Code array:
Normal routes are unaffected - that branch explicitly assigns codes[i] = OK for every index in a loop. The Group branch was missed.
The proto field is documented as a deduplicated list, but the client BatchMatchCall.makeBatch does not deduplicate. The Normal branch already has explicit dedup handling and a test for it (testAddNormalRouteDuplicatedInOneBatchOnlyCountOnceAndRefresh); the Group branch was missed.
Consequence
The NPE is thrown before MutationResult is returned, but rangeWriter.done() still commits the buffered writes (normal routes + RouteGroup records land in KV), while the co-processor post-actions (routeCache.refresh, deliverExecutorGroup.refreshOrderedSharedSubRoutes, tenant counters, refreshFact) never execute. The batch is reported as ERROR to the client while the route cache remains inconsistent with the KV store until the cache expires - during which publishes are routed using stale data.
Fix
Record all positions for a route rather than only the last one - the value type of both group maps changes from Integer to List of Integer, and the consumer assigns the computed code to every recorded index. The same change applies to delGroupMatchRecords in batchRemoveRoute.
Testing
Two symmetric regression tests in DistWorkerCoProcTest:
Control experiment: on unfixed code both tests fail (NPE / null slot); with the fix all 19 tests in DistWorkerCoProcTest pass.