Skip to content

fix(pd): return PDException body from task/balanceLeaders - #3233

Open
bitflicker64 wants to merge 2 commits into
apache:masterfrom
hugegraph:fix/pd-taskapi-pdexception-3231
Open

bitflicker64 wants to merge 2 commits into
apache:masterfrom
hugegraph:fix/pd-taskapi-pdexception-3231

Conversation

@bitflicker64

@bitflicker64 bitflicker64 commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

Purpose of the PR

GET /v1/task/balanceLeaders declares throws PDException and has no handler. When PD refuses the leader balance, for example within 180 s of a balancePartitions call while the balance-shard key is set, the caller gets a bare Spring 500 ({"timestamp":...,"status":500,"error":"Internal Server Error","path":"/v1/task/balanceLeaders"}) and the reason (balance shard is processing, please try later!, TaskScheduleService.java:478) only reaches the PD log. The sibling task endpoints patrolStores, patrolPartitions and splitPartitions catch the exception and answer toJSON(e). StoreAPI serves the same operation at GET /v1/balanceLeaders and had the same gap.

Part 2 of #3231 (what the task endpoints answer on a follower or on a no-op, and whether the body reports what was done) is out of scope here. It needs a design decision and stays open in the issue. This PR does not change response semantics beyond the error path below.

Main Changes

  • TaskAPI.balanceLeaders now catches PDException and returns toJSON(e), copying the handler used by patrolStores, patrolPartitions and splitPartitions, including produces = APPLICATION_JSON_VALUE and @ResponseBody.
  • The refused case now answers {"status":1001,"error":"balance shard is processing, please try later!"} with the same HTTP status the siblings use for their error bodies.
  • The success body is unchanged. The leader map is serialized with API.toJSON(Object) (Jackson), so {"1":2} stays {"1":2} and the content type stays application/json.
  • StoreAPI.balanceLeaders (GET /v1/balanceLeaders) gets the same catch, in the form the other StoreAPI endpoints use, so both routes answer the same error body.
  • New unit test BalanceLeadersAPITest in hg-pd-service, next to StoreAPIReadyTest, covering both routes.

Verifying these changes

  • Trivial rework / code cleanup without any test coverage. (No Need)
  • Already covered by existing tests, such as (please modify tests here).
  • Need tests and can be verified as follows:
    • BalanceLeadersAPITest.test{Task,Store}RouteRefusedBalanceReturnsErrorBody: a PDRestService stub throws PDException(1001, "balance shard is processing, please try later!"); each route returns a body with status 1001 and that error text.
    • BalanceLeadersAPITest.test{Task,Store}RouteSuccessfulBalanceKeepsBody: a stub returns {1: 2}; each route returns {"1":2}, the same body as before.
    • Run on JDK 11: mvn test -pl hugegraph-pd/hg-pd-service -am -Dtest='StoreAPIReadyTest,BalanceLeadersAPITest,AuthenticationTest' -DfailIfNoTests=false gives 17 tests, 0 failures (all test classes in hg-pd-service). mvn editorconfig:check -pl hugegraph-pd/hg-pd-service passes.

Does this PR potentially affect the following parts?

  • Dependencies (add/update license info & regenerate_known_dependencies.sh)
  • Modify configurations
  • The public API (error response of GET /v1/task/balanceLeaders and GET /v1/balanceLeaders only; the success body is unchanged)
  • Other affects (typed here)
  • Nope

Documentation Status

Select one option and provide the documentation location when applicable.

  • Doc - TODO: required documentation is pending; complete it before merging.
  • Doc - Done: documentation is included here or linked below.
  • Doc - No Need: no user-visible documentation is affected.

Documentation files in this PR or paired hugegraph-doc PR:

GET /v1/task/balanceLeaders declared "throws PDException" with no
handler, so a refused balance (for example within 180 s of
balancePartitions, while the balance-shard key is set) surfaced as a
bare HTTP 500 and the reason only reached the PD log. Catch it and
answer toJSON(e) like patrolStores, patrolPartitions and
splitPartitions do. The success body is unchanged.

Part 1 of apache#3231.
@codecov

codecov Bot commented Sep 23, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 35.26%. Comparing base (83ef9f3) to head (45c0c9b).

❗ There is a different number of reports uploaded between BASE (83ef9f3) and HEAD (45c0c9b). Click for more details.

HEAD has 2 uploads less than BASE
Flag BASE (83ef9f3) HEAD (45c0c9b)
7 5
Additional details and impacted files
@@             Coverage Diff              @@
##             master    #3233      +/-   ##
============================================
- Coverage     41.35%   35.26%   -6.09%     
+ Complexity     7299     6062    -1237     
============================================
  Files           802      782      -20     
  Lines         69688    67372    -2316     
  Branches       9291     8966     -325     
============================================
- Hits          28816    23761    -5055     
- Misses        37576    40822    +3246     
+ Partials       3296     2789     -507     

☔ 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.

@bitflicker64 bitflicker64 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Blocking: no. Summary: The change fixes the error body of GET /v1/task/balanceLeaders as described: a refused balance now answers {"status":1001,"error":...} like patrolStores, patrolPartitions and splitPartitions, and the success body stays {"1":2}. One minor gap remains: StoreAPI serves the same operation at GET /v1/balanceLeaders and still returns a bare HTTP 500 for the same refusal. Evidence: read TaskAPI, StoreAPI, API.toJSON overloads and TaskScheduleService.balancePartitionLeader at c4e8ab4; confirmed toJSON(leaders) resolves to toJSON(Object) and toJSON(e) to toJSON(PDException); searched hugegraph-pd for @ExceptionHandler and @ControllerAdvice (none); the pd CI job log at this head shows TaskAPIBalanceLeadersTest ran with 2 tests, 0 failures.

StoreAPI serves the same leader balance at GET /v1/balanceLeaders and
had the same missing handler, so a refused balance still answered a
bare HTTP 500 on that route. Catch it and answer toJSON(e) like the
other StoreAPI endpoints. The success body is unchanged.

The test now covers both routes and is renamed to
BalanceLeadersAPITest.
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.

1 participant