client/resource_group: enforce a single active ResourceGroupsController per process
- Dominant language
- Go
- Stars
- 1.2k
- Forks
- 783
- Avg merge
- 5d 21h
- Merged PRs (30d)
- 36
Description
## Enhancement Task
### Context
Current TiDB production code creates one `ResourceGroupsController` per process, and we have not found a supported production path that requires multiple controllers to coexist. However, this is only an implicit caller-side convention; `pd/client` does not enforce it.
Several process-global integrations, metrics, and cleanup paths already assume a unique controller owner, while the public APIs still allow multiple controllers to be constructed and started. This leaves an unsupported state available to future callers.
### Proposed enhancement
Make the single-controller model an explicit lifecycle contract:
- Allow at most one `ResourceGroupsController` acquired through the supported API to be usable in a process at a time, and return a deterministic error for a second acquisition.
- Allow replacement only after the previous controller has fully stopped and released ownership; cleanup and release must be idempotent and safe on initialization failures.
- Update TiDB startup, retry, handoff, and shutdown paths to preserve the contract.
- Convert existing multi-controller tests to sequential coverage where appropriate and add focused tests for rejection and replacement.
The change should preserve current production behavior while preventing future code from relying on unsupported multi-controller semantics.
### Related work
The implementation in tikv/pd#10588 assumes that only one `ResourceGroupsController` exists in the process. Similar assumptions already exist elsewhere in the controller lifecycle and process-global integration code, so this issue tracks the invariant as an overall contract rather than a PR-specific fix.
Contributor guide
Research direction
Start in pd/client at the ResourceGroupsController construction, start, stop, and release paths, then trace the TiDB startup, retry, handoff, and shutdown callers. Review the existing multi-controller tests and add focused coverage for rejection, replacement after full stop, and initialization-failure cleanup. Done means the supported API permits one active controller, rejects a second deterministically, and preserves current production lifecycle behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- backend, distributed-systems
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100