Skip to content

Fix application state router isolation across service chains - #16546

Open
xiaobaicai66695 wants to merge 2 commits into
apache:3.3from
xiaobaicai66695:fix/app-state-router-per-service-16545
Open

xiaobaicai66695 wants to merge 2 commits into
apache:3.3from
xiaobaicai66695:fix/app-state-router-per-service-16545

Conversation

@xiaobaicai66695

@xiaobaicai66695 xiaobaicai66695 commented Oct 26, 2026 •

Copy link
Copy Markdown

What is the purpose of the change?

Fixes #16545.

AppStateRouterFactory returned one mutable AppStateRouter for every service reference in the same module. Building a second service's SingleRouterChain calls setNextRouter on that shared object, which changes the first chain's successor. In the linked reproduction, the Order service's application script rule is loaded but its script router is skipped after the User reference is initialized.

This change uses the existing CacheableStateRouterFactory to cache AppStateRouter instances by service key, consistent with the other service and application script router factories. It adds a regression test that builds two service chains in either order and checks that the first chain still filters its invokers after the second chain is built.

Verification

  • Before the fix, both regression cases failed: the first chain returned two invokers where only one was allowed.
  • After the fix, AppStateRouterFactoryTest passed on JDK 8 and JDK 21: 2 tests, 0 failures, 0 errors on each runtime.
  • On JDK 21, ./mvnw -pl dubbo-cluster -am spotless:check passed, matching the CI formatting gate.
  • Real RPC reproduction from [Bug] Script routing bypassed with two service references #16545: ZooKeeper registry, Nacos 2.5.2 configuration center, two Order provider JVMs and one User provider JVM, JDK 8. With the JDK 8 compatible AppStateRouterFactory compiled from this branch loaded ahead of the Dubbo 3.3.6 runtime, five fresh consumer JVMs each sent 20 Order RPCs and all 20 reached order-v2. The unmodified 3.3.6 control leaked Order calls to order-v1 in all five runs. The complete demo source and rule are in [Bug] Script routing bypassed with two service references #16545.

Checklist

  • Linked the reproducing issue.
  • Added regression coverage for both service-chain construction orders.
  • Ran the focused test and local real-RPC reproduction.
  • GitHub Actions passed on commit 9666cb4 (formatting, build, license, unit tests on JDK 8/11/17/21/25, samples and integration tests).

Cache application state routers by service key so building another service chain cannot rewrite the first chain's successor. Add regression coverage for both construction orders.

Fixes apache#16545
@codecov-commenter

codecov-commenter commented Oct 26, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 60.87%. Comparing base (843b98b) to head (9666cb4).

Additional details and impacted files
@@             Coverage Diff              @@
##                3.3   #16546      +/-   ##
============================================
- Coverage     60.90%   60.87%   -0.03%     
  Complexity       15       15              
============================================
  Files          1953     1953              
  Lines         89280    89273       -7     
  Branches      13476    13476              
============================================
- Hits          54376    54349      -27     
- Misses        29323    29340      +17     
- Partials       5581     5584       +3     
Flag Coverage Δ
integration-tests-java21 32.06% <100.00%> (-0.02%) ⬇️
integration-tests-java8 32.14% <100.00%> (-0.01%) ⬇️
samples-tests-java21 32.12% <100.00%> (-0.01%) ⬇️
samples-tests-java8 29.74% <100.00%> (-0.03%) ⬇️
unit-tests-java11 59.16% <100.00%> (+0.04%) ⬆️
unit-tests-java17 58.61% <100.00%> (+<0.01%) ⬆️
unit-tests-java21 58.62% <100.00%> (-0.02%) ⬇️
unit-tests-java25 58.56% <100.00%> (-0.04%) ⬇️
unit-tests-java8 59.14% <100.00%> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@EarthChen EarthChen left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM. Confirmed the bug: AppStateRouterFactory cached one router per module, but SingleRouterChain calls setNextRouter on it for each chain, so the chain built last overwrote nextRouter for all earlier chains. Extending CacheableStateRouterFactory (cache by service key) is consistent with the sibling factories. AppStateRouterFactoryTest passes locally.

Non-blocking: the test uses hand-written downstream routers, and the main/backup chains built for the same URL share one cached router instance (harmless today).

This branch has not been deployed

No deployments
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.

[Bug] Script routing bypassed with two service references

3 participants