This is an automated email from the ASF dual-hosted git repository.

lokiore pushed a commit to branch PHOENIX-7562-feature-new
in repository https://gitbox.apache.org/repos/asf/phoenix.git


The following commit(s) were added to refs/heads/PHOENIX-7562-feature-new by 
this push:
     new b45336a8c4 PHOENIX-7870 :- Per-HA-group poller futures and url1/url2 
alternation in GetClusterRoleRecordUtil (ADDENDUM) (#2494)
b45336a8c4 is described below

commit b45336a8c4b815961e25df08185b4ed6b7e830d2
Author: Lokesh Khurana <[email protected]>
AuthorDate: Wed Jun 3 12:58:18 2026 -0700

    PHOENIX-7870 :- Per-HA-group poller futures and url1/url2 alternation in 
GetClusterRoleRecordUtil (ADDENDUM) (#2494)
    
    Pure formatting addendum produced by `mvn spotless:apply -DskipTests -q`
    on the current tip of PHOENIX-7562-feature-new. No source-logic changes.
    
    The original PHOENIX-7870 merge into PHOENIX-7562-feature-new shipped
    without `spotless:apply` being run pre-PR, so the feature branch is
    currently failing `spotless:check`. This addendum brings it back in
    compliance.
    
    
    Generated-by: Claude Code (Opus 4.7)
---
 .../exception/MutationBlockedIOException.java      |   4 +-
 .../exception/StaleClusterRoleRecordException.java |   4 +-
 .../org/apache/phoenix/schema/MetaDataClient.java  |   6 +-
 .../phoenix/util/GetClusterRoleRecordUtil.java     |  25 ++--
 .../IndexRegionObserverMutationBlockingIT.java     | 140 ++++++++++-----------
 .../HaFailoverExceptionInheritanceTest.java        |   9 +-
 .../phoenix/util/GetClusterRoleRecordUtilTest.java |  21 ++--
 7 files changed, 102 insertions(+), 107 deletions(-)

diff --git 
a/phoenix-core-client/src/main/java/org/apache/phoenix/exception/MutationBlockedIOException.java
 
b/phoenix-core-client/src/main/java/org/apache/phoenix/exception/MutationBlockedIOException.java
index c8555d66dd..4c2663cefa 100644
--- 
a/phoenix-core-client/src/main/java/org/apache/phoenix/exception/MutationBlockedIOException.java
+++ 
b/phoenix-core-client/src/main/java/org/apache/phoenix/exception/MutationBlockedIOException.java
@@ -22,8 +22,8 @@ import org.apache.hadoop.hbase.DoNotRetryIOException;
 /**
  * Exception thrown when CLUSTER_ROLE_BASED_MUTATION_BLOCK_ENABLED is set and 
the current cluster
  * role is ACTIVE_TO_STANDBY.
- *
- * <p>Extends {@link DoNotRetryIOException} so HBase's RPC retry layers
+ * <p>
+ * Extends {@link DoNotRetryIOException} so HBase's RPC retry layers
  * ({@code AsyncRequestFutureImpl}, {@code RpcRetryingCallerImpl}) fail-fast 
on the first hit
  * instead of absorbing the brief mutation-block window into the retry budget. 
Phoenix's outer
  * failover-aware retry remains responsible for routing to the new ACTIVE.
diff --git 
a/phoenix-core-client/src/main/java/org/apache/phoenix/exception/StaleClusterRoleRecordException.java
 
b/phoenix-core-client/src/main/java/org/apache/phoenix/exception/StaleClusterRoleRecordException.java
index a1e9e40987..8555c83bf1 100644
--- 
a/phoenix-core-client/src/main/java/org/apache/phoenix/exception/StaleClusterRoleRecordException.java
+++ 
b/phoenix-core-client/src/main/java/org/apache/phoenix/exception/StaleClusterRoleRecordException.java
@@ -22,8 +22,8 @@ import org.apache.hadoop.hbase.DoNotRetryIOException;
 /**
  * Exception thrown when attempting to do operation on STANDBY Cluster of HA 
Connection, indicating
  * that the client has slate Cluster Role Record info for the HAGroup.
- *
- * <p>Extends {@link DoNotRetryIOException} so HBase's RPC retry layers
+ * <p>
+ * Extends {@link DoNotRetryIOException} so HBase's RPC retry layers
  * ({@code AsyncRequestFutureImpl}, {@code RpcRetryingCallerImpl}) fail-fast 
on the first hit
  * instead of consuming the full retry budget against the now-STANDBY cluster. 
Phoenix's outer
  * failover-aware retry remains responsible for routing to the new ACTIVE.
diff --git 
a/phoenix-core-client/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
 
b/phoenix-core-client/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
index 1f57187a2c..edb38da970 100644
--- 
a/phoenix-core-client/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
+++ 
b/phoenix-core-client/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
@@ -4738,9 +4738,9 @@ public class MetaDataClient {
           /**
            * To check if TTL is defined at any of the child below we are 
checking it at
            * {@link 
org.apache.phoenix.coprocessor.MetaDataEndpointImpl#mutateColumn(List, 
ColumnMutator, int, PTable, PTable, boolean)}
-           * level where in function {@link 
org.apache.phoenix.coprocessor.MetaDataEndpointImpl#
-           * validateIfMutationAllowedOnParent(PTable, List, PTableType, long, 
byte[], byte[],
-           * byte[], List, int)} we are already traversing through 
allDescendantViews.
+           * level where in function
+           * {@link org.apache.phoenix.coprocessor.MetaDataEndpointImpl# 
validateIfMutationAllowedOnParent(PTable, List, PTableType, long, byte[], 
byte[], byte[], List, int)}
+           * we are already traversing through allDescendantViews.
            */
         }
 
diff --git 
a/phoenix-core-client/src/main/java/org/apache/phoenix/util/GetClusterRoleRecordUtil.java
 
b/phoenix-core-client/src/main/java/org/apache/phoenix/util/GetClusterRoleRecordUtil.java
index e021c8cc98..5adbedb169 100644
--- 
a/phoenix-core-client/src/main/java/org/apache/phoenix/util/GetClusterRoleRecordUtil.java
+++ 
b/phoenix-core-client/src/main/java/org/apache/phoenix/util/GetClusterRoleRecordUtil.java
@@ -61,10 +61,10 @@ public class GetClusterRoleRecordUtil {
 
   /**
    * Per-HA-group poller futures, keyed on haGroupName. A previous 
implementation kept a single
-   * static {@code pollerFuture} field that was overwritten by each new {@code 
schedulePoller}
-   * call regardless of haGroupName, so cancelling the poller for one HA group 
would cancel the
-   * future most recently scheduled (which may belong to a different HA 
group). Keying by
-   * haGroupName ensures each group's future is cancelled independently.
+   * static {@code pollerFuture} field that was overwritten by each new {@code 
schedulePoller} call
+   * regardless of haGroupName, so cancelling the poller for one HA group 
would cancel the future
+   * most recently scheduled (which may belong to a different HA group). 
Keying by haGroupName
+   * ensures each group's future is cancelled independently.
    */
   private static final Map<String, ScheduledFuture<?>> futureMap = new 
ConcurrentHashMap<>();
 
@@ -184,12 +184,12 @@ public class GetClusterRoleRecordUtil {
    * <p>
    * The poller alternates between {@code url1} and {@code url2} on successive 
ticks. Alternating
    * (rather than pinning to a single URL) avoids stalling if the chosen 
cluster's RegionServer
-   * Endpoint is transiently unreachable while the peer cluster is healthy and 
may already hold
-   * the Active role.
+   * Endpoint is transiently unreachable while the peer cluster is healthy and 
may already hold the
+   * Active role.
    * <p>
    * Each haGroupName gets its own entry in {@link #futureMap} and {@link 
#schedulerMap}. Multiple
-   * HA groups can therefore run independent pollers; cancellation of one HA 
group's poller does
-   * not interfere with another's lifecycle.
+   * HA groups can therefore run independent pollers; cancellation of one HA 
group's poller does not
+   * interfere with another's lifecycle.
    * @param url1           URL of the RegionServer Endpoint Service for 
cluster 1
    * @param url2           URL of the RegionServer Endpoint Service for 
cluster 2
    * @param haGroupName    Name of the HA group
@@ -242,8 +242,9 @@ public class GetClusterRoleRecordUtil {
             }
           }
         } catch (SQLException e) {
-          LOGGER.error("Exception found while polling for ClusterRoleRecord on 
{} for HA group"
-            + " {}: {}", tickUrl, haGroupName, e.getMessage());
+          LOGGER.error(
+            "Exception found while polling for ClusterRoleRecord on {} for HA 
group" + " {}: {}",
+            tickUrl, haGroupName, e.getMessage());
         }
       };
 
@@ -286,8 +287,8 @@ public class GetClusterRoleRecordUtil {
   }
 
   /**
-   * Pick which URL the poller should target on tick {@code tick}. Even ticks 
(0, 2, 4, ...)
-   * select {@code url1}; odd ticks select {@code url2}. Package-private for 
unit-test access.
+   * Pick which URL the poller should target on tick {@code tick}. Even ticks 
(0, 2, 4, ...) select
+   * {@code url1}; odd ticks select {@code url2}. Package-private for 
unit-test access.
    */
   static String selectUrlForTick(String url1, String url2, long tick) {
     return (tick % 2 == 0) ? url1 : url2;
diff --git 
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexRegionObserverMutationBlockingIT.java
 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexRegionObserverMutationBlockingIT.java
index fc6c1ce9c0..f1966e9342 100644
--- 
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexRegionObserverMutationBlockingIT.java
+++ 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexRegionObserverMutationBlockingIT.java
@@ -281,12 +281,12 @@ public class IndexRegionObserverMutationBlockingIT 
extends HABaseIT {
    * Walks the cause chain of a {@link CommitException} looking for a
    * {@link MutationBlockedIOException}. Handles two paths:
    * <ul>
-   *   <li>Direct chain — {@code MutationBlockedIOException} now extends
-   *       {@link org.apache.hadoop.hbase.DoNotRetryIOException}, so HBase's 
RPC retry layers
-   *       fail-fast and propagate the exception without wrapping it in
-   *       {@link RetriesExhaustedWithDetailsException}.</li>
-   *   <li>REWDE-wrapped — the legacy retry path; preserved here for any 
caller that still
-   *       reaches it (defense-in-depth).</li>
+   * <li>Direct chain — {@code MutationBlockedIOException} now extends
+   * {@link org.apache.hadoop.hbase.DoNotRetryIOException}, so HBase's RPC 
retry layers fail-fast
+   * and propagate the exception without wrapping it in
+   * {@link RetriesExhaustedWithDetailsException}.</li>
+   * <li>REWDE-wrapped — the legacy retry path; preserved here for any caller 
that still reaches it
+   * (defense-in-depth).</li>
    * </ul>
    */
   private boolean containsMutationBlockedException(CommitException e) {
@@ -310,25 +310,23 @@ public class IndexRegionObserverMutationBlockingIT 
extends HABaseIT {
 
   /**
    * Regression test for the fail-fast fix on the batched-mutation path. The 
fix is the inheritance
-   * change on {@link MutationBlockedIOException} — it now extends
-   * {@code DoNotRetryIOException}, signaling intent to fail fast.
-   *
-   * <p>Empirical verification: server-side rehydration (via
-   * {@code ProtobufUtil.toException}) delivers a real {@code 
MutationBlockedIOException} instance
-   * to HBase's batched-RPC retry layer ({@code 
AsyncRequestFutureImpl.manageError}); the
-   * {@code instanceof DoNotRetryIOException} check at line 749 returns true 
post-inheritance, so
-   * no retries fire and the failure surfaces immediately. The inheritance 
change alone is
-   * sufficient for the batched path.
-   *
-   * <p>Test asserts:
+   * change on {@link MutationBlockedIOException} — it now extends {@code 
DoNotRetryIOException},
+   * signaling intent to fail fast.
+   * <p>
+   * Empirical verification: server-side rehydration (via {@code 
ProtobufUtil.toException}) delivers
+   * a real {@code MutationBlockedIOException} instance to HBase's batched-RPC 
retry layer
+   * ({@code AsyncRequestFutureImpl.manageError}); the {@code instanceof 
DoNotRetryIOException}
+   * check at line 749 returns true post-inheritance, so no retries fire and 
the failure surfaces
+   * immediately. The inheritance change alone is sufficient for the batched 
path.
+   * <p>
+   * Test asserts:
    * <ol>
-   *   <li>An {@link MutationBlockedIOException} appears somewhere on the 
{@link CommitException}
-   *       cause chain (proves the server gate fired).</li>
-   *   <li>Wall-clock duration of the failed commit is well below the pre-fix 
HBase retry-budget
-   *       tail (which was on the order of tens of seconds for default 16 
retries × per-retry
-   *       timeout). A bound of {@code MAX_FAIL_FAST_DURATION_MS} captures 
this with generous
-   *       headroom for slow CI; on a healthy mini-cluster the actual duration 
is
-   *       sub-second.</li>
+   * <li>An {@link MutationBlockedIOException} appears somewhere on the {@link 
CommitException}
+   * cause chain (proves the server gate fired).</li>
+   * <li>Wall-clock duration of the failed commit is well below the pre-fix 
HBase retry-budget tail
+   * (which was on the order of tens of seconds for default 16 retries × 
per-retry timeout). A bound
+   * of {@code MAX_FAIL_FAST_DURATION_MS} captures this with generous headroom 
for slow CI; on a
+   * healthy mini-cluster the actual duration is sub-second.</li>
    * </ol>
    */
   @Test
@@ -350,8 +348,7 @@ public class IndexRegionObserverMutationBlockingIT extends 
HABaseIT {
           HighAvailabilityPolicy.FAILOVER.toString(), this.peerZkUrl, 
CLUSTERS.getMasterAddress1(),
           CLUSTERS.getMasterAddress2(), CLUSTERS.getHdfsUrl1(), 
CLUSTERS.getHdfsUrl2(), 0L);
       haAdmin.updateHAGroupStoreRecordInZooKeeper(haGroupName, 
haGroupStoreRecord, -1);
-      awaitZkPropagation(haGroupName,
-        HAGroupStoreRecord.HAGroupState.ACTIVE_IN_SYNC_TO_STANDBY);
+      awaitZkPropagation(haGroupName, 
HAGroupStoreRecord.HAGroupState.ACTIVE_IN_SYNC_TO_STANDBY);
 
       long startMs = System.currentTimeMillis();
       try {
@@ -365,12 +362,13 @@ public class IndexRegionObserverMutationBlockingIT 
extends HABaseIT {
           "Expected MutationBlockedIOException somewhere on the cause chain 
(helper walks both "
             + "direct and REWDE-wrapped layouts).",
           containsMutationBlockedException(e));
-        assertTrue("Expected fail-fast: failed commit took " + durationMs
-          + "ms which exceeds the bound of " + MAX_FAIL_FAST_DURATION_MS
-          + "ms. Pre-fix this took on the order of tens of seconds while HBase 
exhausted its "
-          + "retry budget against the now-blocking server. If this assertion 
fails, HBase has "
-          + "started retrying despite DoNotRetryIOException — investigate 
whether the inheritance"
-          + " change on MutationBlockedIOException is still in place.",
+        assertTrue(
+          "Expected fail-fast: failed commit took " + durationMs + "ms which 
exceeds the bound of "
+            + MAX_FAIL_FAST_DURATION_MS
+            + "ms. Pre-fix this took on the order of tens of seconds while 
HBase exhausted its "
+            + "retry budget against the now-blocking server. If this assertion 
fails, HBase has "
+            + "started retrying despite DoNotRetryIOException — investigate 
whether the inheritance"
+            + " change on MutationBlockedIOException is still in place.",
           durationMs < MAX_FAIL_FAST_DURATION_MS);
       }
     }
@@ -378,19 +376,19 @@ public class IndexRegionObserverMutationBlockingIT 
extends HABaseIT {
 
   /**
    * Wall-clock bound for fail-fast on the batched mutation path. Pre-fix, 
HBase's default
-   * {@code hbase.client.retries.number=16} multiplied by per-retry RPC 
timeouts produced tails
-   * on the order of tens of seconds. Post-fix (server-side DNRIOE 
inheritance), the first hit
-   * propagates immediately. The 10-second bound gives generous headroom for 
slow CI hardware
-   * while staying well below any plausible retry tail.
+   * {@code hbase.client.retries.number=16} multiplied by per-retry RPC 
timeouts produced tails on
+   * the order of tens of seconds. Post-fix (server-side DNRIOE inheritance), 
the first hit
+   * propagates immediately. The 10-second bound gives generous headroom for 
slow CI hardware while
+   * staying well below any plausible retry tail.
    */
   private static final long MAX_FAIL_FAST_DURATION_MS = 10_000L;
 
   /**
    * Empirical proof that the DNRIOE inheritance change alone — with no 
Phoenix-side client-code
-   * changes — is sufficient to deliver fail-fast on the batched mutation path 
under elevated
-   * retry settings.
-   *
-   * <p>Server-side rehydration via {@code ProtobufUtil.toException} delivers 
a real
+   * changes — is sufficient to deliver fail-fast on the batched mutation path 
under elevated retry
+   * settings.
+   * <p>
+   * Server-side rehydration via {@code ProtobufUtil.toException} delivers a 
real
    * {@link MutationBlockedIOException} instance to HBase's batched-RPC retry 
layer
    * ({@code AsyncRequestFutureImpl.manageError}); the {@code instanceof 
DoNotRetryIOException}
    * check at line 749 returns true post-inheritance, so no retries fire and 
the failure surfaces
@@ -398,14 +396,14 @@ public class IndexRegionObserverMutationBlockingIT 
extends HABaseIT {
    * {@code hbase.client.pause} to values that would — absent the inheritance 
— force HBase's
    * batched-RPC retry layer to consume many seconds before surfacing the 
failure (16 retries ×
    * ~100ms base pause with exponential backoff yields multi-second tails). 
The wall-clock bound
-   * stays under {@link #MAX_FAIL_FAST_DURATION_MS} only because the 
inheritance change is in
-   * place; the assertion-passing IS the empirical proof of inheritance-alone 
fail-fast.
-   *
-   * <p>Note: even with elevated retry settings, the mini-cluster batched path 
may still surface
-   * only a single attempt before propagation due to harness internals not 
faithfully modeling
-   * the production-perf retry tail observed on real clusters. In that case, 
this test functions
-   * as additional regression coverage rather than a true behavioral 
discriminator; real-cluster
-   * perf testing remains the authoritative validation of the wall-clock 
benefit.
+   * stays under {@link #MAX_FAIL_FAST_DURATION_MS} only because the 
inheritance change is in place;
+   * the assertion-passing IS the empirical proof of inheritance-alone 
fail-fast.
+   * <p>
+   * Note: even with elevated retry settings, the mini-cluster batched path 
may still surface only a
+   * single attempt before propagation due to harness internals not faithfully 
modeling the
+   * production-perf retry tail observed on real clusters. In that case, this 
test functions as
+   * additional regression coverage rather than a true behavioral 
discriminator; real-cluster perf
+   * testing remains the authoritative validation of the wall-clock benefit.
    */
   @Test
   public void testMutationBlockedFailsFastUnderElevatedRetries() throws 
Exception {
@@ -433,8 +431,7 @@ public class IndexRegionObserverMutationBlockingIT extends 
HABaseIT {
           HighAvailabilityPolicy.FAILOVER.toString(), this.peerZkUrl, 
CLUSTERS.getMasterAddress1(),
           CLUSTERS.getMasterAddress2(), CLUSTERS.getHdfsUrl1(), 
CLUSTERS.getHdfsUrl2(), 0L);
       haAdmin.updateHAGroupStoreRecordInZooKeeper(haGroupName, 
haGroupStoreRecord, -1);
-      awaitZkPropagation(haGroupName,
-        HAGroupStoreRecord.HAGroupState.ACTIVE_IN_SYNC_TO_STANDBY);
+      awaitZkPropagation(haGroupName, 
HAGroupStoreRecord.HAGroupState.ACTIVE_IN_SYNC_TO_STANDBY);
 
       long startMs = System.currentTimeMillis();
       try {
@@ -444,15 +441,15 @@ public class IndexRegionObserverMutationBlockingIT 
extends HABaseIT {
         fail("Expected MutationBlockedIOException to be thrown");
       } catch (CommitException e) {
         long durationMs = System.currentTimeMillis() - startMs;
-        assertTrue(
-          "Expected MutationBlockedIOException somewhere on the cause chain.",
+        assertTrue("Expected MutationBlockedIOException somewhere on the cause 
chain.",
           containsMutationBlockedException(e));
-        assertTrue("Expected fail-fast under elevated retry settings: failed 
commit took "
-          + durationMs + "ms which exceeds the bound of " + 
MAX_FAIL_FAST_DURATION_MS
-          + "ms. Under hbase.client.retries.number=16 and 
hbase.client.pause=100, the absence "
-          + "of the DNRIOE inheritance change would surface a multi-second 
retry tail. "
-          + "If this assertion fails, the inheritance change is not in place 
or HBase has "
-          + "started retrying despite DoNotRetryIOException — investigate the 
cause chain.",
+        assertTrue(
+          "Expected fail-fast under elevated retry settings: failed commit 
took " + durationMs
+            + "ms which exceeds the bound of " + MAX_FAIL_FAST_DURATION_MS
+            + "ms. Under hbase.client.retries.number=16 and 
hbase.client.pause=100, the absence "
+            + "of the DNRIOE inheritance change would surface a multi-second 
retry tail. "
+            + "If this assertion fails, the inheritance change is not in place 
or HBase has "
+            + "started retrying despite DoNotRetryIOException — investigate 
the cause chain.",
           durationMs < MAX_FAIL_FAST_DURATION_MS);
       }
     }
@@ -460,27 +457,26 @@ public class IndexRegionObserverMutationBlockingIT 
extends HABaseIT {
 
   /**
    * Polls ZooKeeper for the HAGroupStoreRecord to reflect the {@code 
expectedState} after a
-   * {@code haAdmin.updateHAGroupStoreRecordInZooKeeper} write. Returns as 
soon as the cached
-   * state matches the expected, or after a timeout. Replaces the unconditional
-   * {@code Thread.sleep(ZK_CURATOR_EVENT_PROPAGATION_TIMEOUT_MS)} pattern 
with a bounded
-   * polling loop (with a short between-poll park) so the wait is 
condition-driven rather than
+   * {@code haAdmin.updateHAGroupStoreRecordInZooKeeper} write. Returns as 
soon as the cached state
+   * matches the expected, or after a timeout. Replaces the unconditional
+   * {@code Thread.sleep(ZK_CURATOR_EVENT_PROPAGATION_TIMEOUT_MS)} pattern 
with a bounded polling
+   * loop (with a short between-poll park) so the wait is condition-driven 
rather than
    * fixed-duration.
-   *
-   * <p>The poll interval is short ({@link #ZK_PROPAGATION_POLL_INTERVAL_MS} 
ms) so the typical
-   * wait is well under the propagation budget; the deadline gives generous CI 
headroom. Throws
-   * {@code AssertionError} via {@code fail()} if the state never converges, 
which surfaces the
-   * same failure shape a stale read would (the subsequent UPSERT would 
observe the old state).
-   *
-   * @param haGroupName    the HA group whose state to await
-   * @param expectedState  the {@link HAGroupStoreRecord.HAGroupState} the 
cached record must reach
+   * <p>
+   * The poll interval is short ({@link #ZK_PROPAGATION_POLL_INTERVAL_MS} ms) 
so the typical wait is
+   * well under the propagation budget; the deadline gives generous CI 
headroom. Throws
+   * {@code AssertionError} via {@code fail()} if the state never converges, 
which surfaces the same
+   * failure shape a stale read would (the subsequent UPSERT would observe the 
old state).
+   * @param haGroupName   the HA group whose state to await
+   * @param expectedState the {@link HAGroupStoreRecord.HAGroupState} the 
cached record must reach
    * @throws Exception if reading the cached record throws
    */
   // java:S2925 (Thread.sleep in tests) suppressed: the sleep here is bounded 
between condition
   // checks inside a deadline-bounded polling loop, not an unconditional wait. 
The rule's flake
   // concern (fixed-duration sleeps) does not apply.
   @SuppressWarnings("java:S2925")
-  private void awaitZkPropagation(String haGroupName,
-      HAGroupStoreRecord.HAGroupState expectedState) throws Exception {
+  private void awaitZkPropagation(String haGroupName, 
HAGroupStoreRecord.HAGroupState expectedState)
+    throws Exception {
     long deadlineMs = System.currentTimeMillis() + 
ZK_PROPAGATION_AWAIT_DEADLINE_MS;
     while (System.currentTimeMillis() < deadlineMs) {
       HAGroupStoreRecord cached = 
haAdmin.getHAGroupStoreRecordInZooKeeper(haGroupName).getLeft();
diff --git 
a/phoenix-core/src/test/java/org/apache/phoenix/exception/HaFailoverExceptionInheritanceTest.java
 
b/phoenix-core/src/test/java/org/apache/phoenix/exception/HaFailoverExceptionInheritanceTest.java
index fb83fe2f73..5cf04c1b8f 100644
--- 
a/phoenix-core/src/test/java/org/apache/phoenix/exception/HaFailoverExceptionInheritanceTest.java
+++ 
b/phoenix-core/src/test/java/org/apache/phoenix/exception/HaFailoverExceptionInheritanceTest.java
@@ -24,11 +24,10 @@ import org.apache.hadoop.hbase.DoNotRetryIOException;
 import org.junit.Test;
 
 /**
- * Unit tests for the HA failover signaling exceptions thrown server-side when 
a mutation hits an
- * HA group whose cluster role is in transition. Both classes must extend
- * {@link DoNotRetryIOException} so HBase's RPC retry layers fail-fast on the 
first hit instead of
- * consuming the per-call retry budget; Phoenix's outer failover-aware retry 
handles routing to
- * the new ACTIVE.
+ * Unit tests for the HA failover signaling exceptions thrown server-side when 
a mutation hits an HA
+ * group whose cluster role is in transition. Both classes must extend {@link 
DoNotRetryIOException}
+ * so HBase's RPC retry layers fail-fast on the first hit instead of consuming 
the per-call retry
+ * budget; Phoenix's outer failover-aware retry handles routing to the new 
ACTIVE.
  */
 public class HaFailoverExceptionInheritanceTest {
 
diff --git 
a/phoenix-core/src/test/java/org/apache/phoenix/util/GetClusterRoleRecordUtilTest.java
 
b/phoenix-core/src/test/java/org/apache/phoenix/util/GetClusterRoleRecordUtilTest.java
index c8ebe40dbc..307482684a 100644
--- 
a/phoenix-core/src/test/java/org/apache/phoenix/util/GetClusterRoleRecordUtilTest.java
+++ 
b/phoenix-core/src/test/java/org/apache/phoenix/util/GetClusterRoleRecordUtilTest.java
@@ -38,18 +38,16 @@ import org.junit.Test;
 /**
  * Unit tests for {@link GetClusterRoleRecordUtil}. These tests cover two 
regressions in the
  * non-active CRR poller infrastructure:
- *
  * <ol>
  * <li>Per-HA-group future tracking: a previous implementation kept a single 
static
  * {@code pollerFuture} field that was overwritten by every {@code 
schedulePoller} invocation
  * regardless of HA group, so cancelling one HA group's poller would target 
whichever future was
  * scheduled most recently — possibly belonging to a different HA group. The 
fix keys both the
  * scheduler executor and the future on {@code haGroupName} via concurrent 
maps.</li>
- * <li>URL alternation each tick: a previous implementation pinned each 
scheduled poller to a
- * single URL passed in at schedule time. If that cluster's RegionServer 
Endpoint became
- * transiently unreachable, the poller could never observe the peer cluster's 
CRR even after
- * the peer became Active. The fix has the poller alternate between url1 and 
url2 on each tick.
- * </li>
+ * <li>URL alternation each tick: a previous implementation pinned each 
scheduled poller to a single
+ * URL passed in at schedule time. If that cluster's RegionServer Endpoint 
became transiently
+ * unreachable, the poller could never observe the peer cluster's CRR even 
after the peer became
+ * Active. The fix has the poller alternate between url1 and url2 on each 
tick.</li>
  * </ol>
  */
 public class GetClusterRoleRecordUtilTest {
@@ -73,8 +71,8 @@ public class GetClusterRoleRecordUtilTest {
   }
 
   /**
-   * URL-alternation core: even ticks pick url1, odd ticks pick url2. This 
verifies the helper
-   * that the poller calls each tick to choose its target URL.
+   * URL-alternation core: even ticks pick url1, odd ticks pick url2. This 
verifies the helper that
+   * the poller calls each tick to choose its target URL.
    */
   @Test
   public void testSelectUrlForTickAlternates() {
@@ -94,7 +92,8 @@ public class GetClusterRoleRecordUtilTest {
   public void testSelectUrlForTickHandlesLargeTickValues() {
     assertEquals(URL_1, GetClusterRoleRecordUtil.selectUrlForTick(URL_1, 
URL_2, 1_000_000L));
     assertEquals(URL_2, GetClusterRoleRecordUtil.selectUrlForTick(URL_1, 
URL_2, 1_000_001L));
-    assertEquals(URL_1, GetClusterRoleRecordUtil.selectUrlForTick(URL_1, 
URL_2, Long.MAX_VALUE - 1));
+    assertEquals(URL_1,
+      GetClusterRoleRecordUtil.selectUrlForTick(URL_1, URL_2, Long.MAX_VALUE - 
1));
     assertEquals(URL_2, GetClusterRoleRecordUtil.selectUrlForTick(URL_1, 
URL_2, Long.MAX_VALUE));
   }
 
@@ -131,8 +130,8 @@ public class GetClusterRoleRecordUtilTest {
 
   /**
    * Removal/cancellation isolation: cancelling one HA group's poller cancels 
only that group's
-   * future and does not touch the peer group's future. This is the key 
behavioural invariant
-   * the prior single-static field violated.
+   * future and does not touch the peer group's future. This is the key 
behavioural invariant the
+   * prior single-static field violated.
    */
   @Test
   public void testCancelOneHaGroupDoesNotCancelOthers() {

Reply via email to