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 eb071af80f PHOENIX-8024 Expose public isHealthy() on
HAGroupStoreClient / HAGroupStoreManager (#2647)
eb071af80f is described below
commit eb071af80f7d9dfeb4735e1b7d6498989e8e07b2
Author: vivek122000 <[email protected]>
AuthorDate: Thu Oct 29 00:40:54 2026 +0530
PHOENIX-8024 Expose public isHealthy() on HAGroupStoreClient /
HAGroupStoreManager (#2647)
Consumers of the HAGroupStateListener pattern that cache callback state as
their source of truth need a way to detect that the underlying ZK watcher
has
disconnected; otherwise their cached snapshot silently goes stale until
Curator
reconnects and delivers a fresh event.
The flag already exists as a private volatile boolean on HAGroupStoreClient,
toggled by the Curator ConnectionStateListener on CONNECTION_LOST /
CONNECTION_SUSPENDED / CONNECTION_RECONNECTED. Today the only way to
observe it
from outside is to call one of the state-reading methods and match on the
"HAGroupStoreClient is not healthy" IOException string, which is brittle and
requires triggering a side-effectful read.
This change adds:
- HAGroupStoreClient#isHealthy(): direct public accessor for the flag.
- HAGroupStoreManager#isHealthy(String): delegate that resolves the client
for
the named HA group and returns its health, consistent with the existing
isMutationBlocked / isHAGroupOnClientStale / getHAGroupStoreRecord shape.
The javadoc describes ZK connection liveness only: CONNECTION_RECONNECTED
sets
the flag back to true immediately, while Curator resyncs the
PathChildrenCache
asynchronously afterward, so consumers needing absolute freshness after a
reconnect should re-read via getHAGroupStoreRecord().
No behavior change; new accessors only. All existing state-reading methods
retain their throw-on-unhealthy contract.
Co-authored-by: Vivek Pandey <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
---
.../apache/phoenix/jdbc/HAGroupStoreClient.java | 34 ++++++++++++++++++++++
.../apache/phoenix/jdbc/HAGroupStoreManager.java | 25 ++++++++++++++++
2 files changed, 59 insertions(+)
diff --git
a/phoenix-core-client/src/main/java/org/apache/phoenix/jdbc/HAGroupStoreClient.java
b/phoenix-core-client/src/main/java/org/apache/phoenix/jdbc/HAGroupStoreClient.java
index f80cf1174e..79f6409eba 100644
---
a/phoenix-core-client/src/main/java/org/apache/phoenix/jdbc/HAGroupStoreClient.java
+++
b/phoenix-core-client/src/main/java/org/apache/phoenix/jdbc/HAGroupStoreClient.java
@@ -369,6 +369,40 @@ public class HAGroupStoreClient implements Closeable {
LOGGER.info("Rebuild Complete for HAGroupStoreClient for HA group {}",
haGroupName);
}
+ /**
+ * Returns whether the underlying ZooKeeper connection for this client is
currently live.
+ * When {@code false}, the Curator connection has been lost/suspended and
any call that
+ * reads shared state ({@link #getHAGroupStoreRecord()}, {@link
#subscribeToTargetState},
+ * etc.) will throw an {@link IOException}.
+ * <p>
+ * Consumers that subscribe an {@link HAGroupStateListener} and cache the
resulting events
+ * in memory (i.e. treat the listener view as the source of truth) should
consult this
+ * before trusting their cached snapshot — a {@code false} return
means the client
+ * has stopped receiving events and the cached view may be arbitrarily stale.
+ * <p>
+ * Flag transitions:
+ * <ul>
+ * <li>Set to {@code true} on successful initial construction, after the
local
+ * {@code PathChildrenCache} has been started and warmed.</li>
+ * <li>Set to {@code false} by the Curator connection-state listener on
+ * {@code CONNECTION_LOST} / {@code CONNECTION_SUSPENDED}.</li>
+ * <li>Set back to {@code true} on {@code CONNECTION_RECONNECTED}. This
tracks the
+ * Curator reconnect event, <em>not</em> cache resynchronization
— Curator
+ * resyncs the {@code PathChildrenCache} asynchronously after
reconnect, so a brief
+ * window exists where {@code isHealthy()} returns {@code true} but
the cache has
+ * not yet observed post-outage state changes. Consumers requiring
absolute
+ * freshness after a reconnect should re-read via {@link
#getHAGroupStoreRecord()}
+ * rather than trust a listener-cached snapshot.</li>
+ * </ul>
+ * The field is {@code volatile}; cross-thread reads are safe.
+ *
+ * @return {@code true} if the ZK connection is live; {@code false} if the
connection has
+ * been lost or suspended
+ */
+ public boolean isHealthy() {
+ return isHealthy;
+ }
+
/**
* Get HAGroupStoreRecord from local quorum.
* @return HAGroupStoreRecord for the specified HA group name, or null if
not found
diff --git
a/phoenix-core-client/src/main/java/org/apache/phoenix/jdbc/HAGroupStoreManager.java
b/phoenix-core-client/src/main/java/org/apache/phoenix/jdbc/HAGroupStoreManager.java
index 5f06e53c4c..6a4d5aeb30 100644
---
a/phoenix-core-client/src/main/java/org/apache/phoenix/jdbc/HAGroupStoreManager.java
+++
b/phoenix-core-client/src/main/java/org/apache/phoenix/jdbc/HAGroupStoreManager.java
@@ -218,6 +218,31 @@ public class HAGroupStoreManager {
return false;
}
+ /**
+ * Returns whether the {@link HAGroupStoreClient} backing {@code
haGroupName} has a live
+ * ZooKeeper connection. See {@link HAGroupStoreClient#isHealthy()} for the
full state
+ * transitions (including the brief post-reconnect window where the flag
returns
+ * {@code true} before Curator has resynchronized the local cache).
+ * <p>
+ * Consumers that subscribe via {@link #subscribeToTargetState} and cache
the resulting
+ * {@link HAGroupStateListener} events in memory should consult this before
trusting the
+ * cached snapshot: a {@code false} return means the client stopped
receiving events and
+ * the cached view may be stale until Curator reconnects. This gives
listener-based
+ * consumers a first-class alternative to matching on the {@code
"HAGroupStoreClient is
+ * not healthy"} {@link IOException} thrown by the state-reading methods.
+ *
+ * @param haGroupName name of the HA group
+ * @return {@code true} if the underlying ZK connection is live; {@code
false} if it has
+ * been lost or suspended
+ * @throws IOException when the {@link HAGroupStoreClient} for {@code
haGroupName} cannot
+ * be resolved or set up
+ */
+ public boolean isHealthy(String haGroupName) throws IOException {
+ HAGroupStoreClient haGroupStoreClient =
+ getHAGroupStoreClientAndSetupFailoverManagement(haGroupName);
+ return haGroupStoreClient.isHealthy();
+ }
+
public boolean isHAGroupOnClientStale(String haGroupName) throws IOException
{
if (checkStaleCRRForEveryMutation) {
HAGroupStoreClient haGroupStoreClient =