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() {