PHOENIX-7787 Make CCF HAGroupStore ZK Updates backward compatible with existing ZK based client#2476
Open
ritegarg wants to merge 5 commits into
Open
Conversation
…h existing ZK based client Co-authored-by: Cursor <cursoragent@cursor.com>
- Replace raw-int sentinels in PhoenixHAAdmin.createOrUpdateClusterRoleRecordWithCAS
with a typed PhoenixHAAdmin.LegacyCrrWriteMode { CREATE_NEW, FORCE_OVERWRITE,
CAS_WITH_VERSION } and (mode, expectedStatVersion) signature. Negative versions
are rejected only for CAS_WITH_VERSION.
- In HAGroupStoreClient.syncLegacyCRRIfRoleChanged, when the NodeCache snapshot
shows the legacy znode as absent, fall back to an authoritative ZK read before
the logical-equality check and CAS. Prevents an unnecessary rewrite when the
cache lags behind the actual znode (avoids CREATE_NEW vs CAS misroute and the
stat-version bump that follows).
- Rename testLegacyCrrCASWithConcurrentWriters_OneSucceedsOneStales to
testLegacyCrrCasErrorMappingAndModeDispatch and update its Javadoc to reflect
what it actually tests (sequential CAS error mapping and mode dispatch).
- Add backward-compat JSON tests in ClusterRoleRecordTest covering: missing
registryType -> defaults to RPC; explicit RPC round-trips; explicit ZK
round-trips; full ZK toJson/fromJson round-trip preserves registryType.
Backed by three new JSON fixtures.
- Bump "CAS lost" log from DEBUG to INFO so sustained CAS contention is visible
in standard operational logs.
- Trim Javadoc and inline comments across the touched files for brevity.
Generated-by: Cursor (Claude).
Co-authored-by: Cursor <cursoragent@cursor.com>
- PhoenixHAAdmin.getHAGroupStoreRecordInZooKeeper: restore @param/@return/@throws from the pre-PR Javadoc, keeping the atomic-read note. - ClusterRoleRecord canonical and convenience constructors: restore per-parameter @param tags; on the @JsonCreator constructor also restore the URL-normalization note and document the registryType backward-compat default. No behavior change. Generated-by: Cursor (Claude). Co-authored-by: Cursor <cursoragent@cursor.com>
…ecord ctor Restores L155-L162 of the pre-PR ClusterRoleRecord.java verbatim (8-line URL-normalization rationale). No behavior change. Generated-by: Cursor (Claude). Co-authored-by: Cursor <cursoragent@cursor.com>
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.
What changes were proposed in this pull request?
Adds an opt-in sync from
/phoenix/consistentHA/<G>to the legacy/phoenix/ha/<G>znode ineach region server's
HAGroupStoreClient. Each client derives a combinedClusterRoleRecord(local role + peer role) and writes it to its local
/phoenix/havia ZK stat-version CAS, sopre-consistentHA ZK-registry clients keep reading a current view of the HA group.
New config keys (in
QueryServices/QueryServicesOptions):phoenix.ha.legacy.crr.sync.enabled— master switch (defaultfalse).phoenix.ha.legacy.crr.reconciliation.interval.seconds— periodic reconciliation cadence(default
60;0disables only the periodic loop, the event-driven path still runs).Convergence model:
CHILD_ADDED/CHILD_UPDATED(LOCAL or PEER).NodeCachewatcher on the legacy znode itself, so per-sync reads are in-memoryrather than a ZK round-trip. The NodeCache is eventually consistent, so on apparent absence
the sync path falls back to one authoritative
getData()to disambiguate "absent" from"not-yet-cached" before deciding
CREATE_NEWvsCAS_WITH_VERSION.BadVersion: log at INFO and bail. The NodeCache watch + next event/periodic cyclereconverges. No inline retry.
Code-level changes:
ClusterRoleRecord: new explicit-RegistryTypector;@JsonCreatornow round-tripsregistryType(legacy znode is always written withRegistryType.ZKfor backwardcompatibility, and must read back as ZK). New
isLogicallyEqualIgnoringVersionAndRegistryhelper used as the rewrite short-circuit.
PhoenixHAAdmin:getClusterRoleRecordAndStatInZooKeeper— atomic (data, stat) read viastoringStatIn.createOrUpdateClusterRoleRecordWithCAS(name, record, LegacyCrrWriteMode mode, int expectedStatVersion)— typed write API.LegacyCrrWriteModeis a public enum withvalues
CREATE_NEW,FORCE_OVERWRITE,CAS_WITH_VERSION; theintargument ismeaningful only for
CAS_WITH_VERSION(validated>= 0at entry). BothBadVersion(CAS lost) and
NodeExists(create lost) surface asStaleClusterRoleRecordVersionExceptionso callers retry uniformly.getHAGroupStoreRecordInZooKeeper(replaces apre-existing 2-RPC pattern that could return a stat version not matching its data
bytes).
HAGroupStoreClient:legacyHaAdmin+legacyCrrNodeCache+ privatelegacyCrrSyncLockCHILD_ADDED/CHILD_UPDATED.CHILD_REMOVEDis intentionally a no-op — the legacy/phoenix/haznode is never deletedby this client.
StaleClusterRoleRecordVersionException(CRR-specific analog ofStaleHAGroupStoreRecordVersionException).Why are the changes needed?
The Consistent Cluster Failover work moved HA group state from
/phoenix/ha(which held aClusterRoleRecord) to/phoenix/consistentHA(which holds anHAGroupStoreRecordand usesan RPC-registry view of CRRs). Existing Phoenix clients built against the older ZK-registry
contract still read
/phoenix/ha/<G>and expect:registryTypeto beZK.Without this patch, after a CCF rollout the
/phoenix/haznode goes stale or absent, and oldZK-registry clients break. This change keeps
/phoenix/hain sync with the new authoritative/phoenix/consistentHArecords on a per-RS basis, gated by an opt-in flag so it only runswhere the operator needs it.
Does this PR introduce any user-facing change?
Yes, but the new behavior is gated entirely behind the new master switch
(
phoenix.ha.legacy.crr.sync.enabled), which defaults tofalse.When the flag is enabled:
HAGroupStoreClientwrites to (and maintains) the legacy/phoenix/ha/<G>znode onits local ZK.
/phoenix/hawill see fresh recordsagain.
One incidental visible change independent of the flag:
ClusterRoleRecordJSONdeserialization now respects the persisted
registryTypefield. Previously it was hard-codedto
RPCregardless of JSON content. Existing JSON without aregistryTypefield stilldefaults to
RPC, so deployments not exposed to legacy-sync writes see no behavior change.How was this patch tested?
HAGroupStoreClientITcovering: feature-off no-op, initial create,role-changing transition, state-only transition (no rewrite), peer-driven role flip,
peer-absent →
role2=UNKNOWN→ recovery, pre-existing stale znode overwrite,CAS error mapping + write-mode dispatch (
CREATE_NEW,FORCE_OVERWRITE,CAS_WITH_VERSIONnegative-version rejection), LOCAL/PEERCHILD_REMOVED(znode preserved),
registryTypestays ZK across multiple role cycles, reconciliationinterval
=0(event-driven still works), and periodic-loop recovery after an externaldivergence.
ClusterRoleRecordTestcovering JSON backward-compat: missingregistryTypedefaults to RPC, explicit RPC round-trips, explicit ZK round-trips, andfull ZK toJson/fromJson round-trip preserves
registryType. Backed by three JSONfixtures under
phoenix-core/src/test/resources/json/.HAGroupStoreClientIT: 39/39 pass.ClusterRoleRecordTest(unit): 16/16 pass.mvn spotless:checkclean across the touched modules.Was this patch authored or co-authored using generative AI tooling?
Generated-by: Claude (Anthropic).