lokiore opened a new pull request, #2580:
URL: https://github.com/apache/phoenix/pull/2580

   ### What changes were proposed in this pull request?
   
   `ConnectionQueryServicesImpl.getMetaDataCache()` returned the `volatile 
latestMetaData` field directly, with no null guard:
   
   ```java
   public PMetaData getMetaDataCache() {
     return latestMetaData;
   }
   ```
   
   This PR adds a guard so a closed connection surfaces a descriptive exception 
instead of a bare NPE. The read is done once into a local so the null-check and 
the returned reference are guaranteed to be the same value (no 
time-of-check/time-of-use re-read window):
   
   ```java
   public PMetaData getMetaDataCache() {
     PMetaData cache = latestMetaData;
     if (cache == null) {
       throwConnectionClosedException();
     }
     return cache;
   }
   ```
   
   `throwConnectionClosedException()` is the same private helper that the 
existing `throwConnectionClosedIfNullMetaData()` (used by `addTable`, 
`removeTable`, `pruneTables`, the internal `getTable` path, etc.) delegates to 
— it throws `IllegalStateException("Connection to the cluster is closed")`. 
`getMetaDataCache()` was the one cache accessor missing this guard.
   
   ### Why are the changes needed?
   
   `close()` sets `latestMetaData = null`. When a connection is closed 
concurrently with query compilation (for example, connection-pool teardown or a 
cluster role transition), an in-flight compile reaches the cache via 
`PhoenixConnection.getTableRef()` / `getFunction()` / `getSchema()`, which call 
`getMetaDataCache().getTableRef(key)` (and friends) on the `null` return. The 
result is a **bare, causeless `NullPointerException`** with no message — 
difficult to attribute to a closed connection during triage.
   
   Every other accessor/mutator on this class already guards this state and 
throws the descriptive `IllegalStateException`; `getMetaDataCache()` was 
inconsistent. This change makes the failure mode uniform and diagnosable.
   
   ### Does this PR introduce _any_ user-facing change?
   
   No behavioral change on an open connection: when `latestMetaData` is 
present, the method returns exactly the same cache reference as before. The 
only change is the failure mode when the connection has been closed — an opaque 
`NullPointerException` is upgraded to a descriptive 
`IllegalStateException("Connection to the cluster is closed")`. No caller 
relies on a `null` return (every production caller immediately dereferences the 
result), so no caller is regressed.
   
   ### How was this patch tested?
   
   Added unit tests in `ConnectionQueryServicesImplTest` exercising a **real** 
`ConnectionQueryServicesImpl` instance (not a mock, so the real guard executes):
   
   - `testGetMetaDataCacheThrowsWhenClosed` — reflectively nulls 
`latestMetaData` (closed-connection state) and asserts `getMetaDataCache()` 
throws `IllegalStateException` with message `"Connection to the cluster is 
closed"`.
   - `testGetMetaDataCacheReturnsCacheWhenOpen` — asserts the method returns 
the cache unchanged when present.
   
   Both pass (`Tests run: 2, Failures: 0, Errors: 0`) via a reactor build (`mvn 
-pl phoenix-core -am test`). `mvn spotless:apply` reports the tree clean.
   
   ### Was this patch authored or co-authored using generative AI tooling?
   
   Generated-by: Claude Code (Opus 4.8 (1M context))
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to