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 &mdash; 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 
&mdash; 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 =

Reply via email to