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

   ### What changes were proposed in this pull request?
   
   `MetaDataEndpointImpl.buildTable` holds the SYSTEM.CATALOG region operation 
(read lock) while it builds a `PTable`. On that path the TTL resolution helpers 
`getTTLFromHierarchy` and `getTTLForParentTable` read SYSTEM.CATALOG through an 
HBase **client** scan (`ServerUtil.getHTableForCoprocessorScan`), which, for a 
non-split SYSTEM.CATALOG, targets the very region whose lock the outer call 
holds.
   
   This PR:
   
   - Adds `getSysCatScanner(key, scan)`, used by both helpers. When the local 
SYSTEM.CATALOG region hosts the key, it reads the rows directly from the local 
region (`Region.getScanner`, wrapped in a small `RegionScanner` → 
`ResultScanner` adapter), the same way `buildTable` reads the table's own rows. 
If the region is closing, this read fails immediately with 
`NotServingRegionException`, so the outer `getTable` releases the lock right 
away.
   - Otherwise (splittable SYSTEM.CATALOG with the key in another region) it 
scans through a new `ServerUtil.ConnectionType.METADATA_LOOKUP_CONNECTION`. Its 
configuration (`ServerUtil.getMetadataConfig`) sets the scanner, operation, RPC 
read and meta-lookup timeouts to the new 
`phoenix.metadata.server.lookup.timeout.ms` (default 10 s; non-positive values 
fall back to the default). Region location lookups retry without checking those 
timeouts, so the retries are also limited to the largest count whose client 
backoff fits within the timeout (`getRetriesWithinTimeout`, using the larger of 
`hbase.client.pause` and `hbase.client.pause.server.overloaded`): 7 retries 
with the defaults. Without this, the connection inherits the region server's 
multiplied retries (45 by default) and the meta-lookup timeouts (20 min by 
default).
   - Closes the `Table`/`ResultScanner` the TTL helpers open, which previously 
leaked.
   
   ### Why are the changes needed?
   
   When SYSTEM.CATALOG is closed (region move, drain, RS restart) while a 
`getTable` is resolving TTL for a view without its own TTL, or for an index on 
a table without one, the nested client scan gets `NotServingRegionException: 
... is closing`. The HBase client treats that as retriable and keeps retrying 
with backoff until the next backoff would exceed 
`hbase.client.scanner.timeout.period` (60 s by default), which happens after 
~48 s. All that time the outer handler holds the region read lock, so 
`HRegion.doClose` cannot acquire the write lock. `buildTable` uses 
`startRegionOperation()` (`Operation.ANY`), so the close's interrupt of 
in-flight operations doesn't apply either.
   
   The result is a ~49 s SYSTEM.CATALOG close on every such move. During that 
time all metadata RPCs fail with NSRE, clients retry, and the metadata call 
queues fill up (`CallQueueTooBigException`). The stall also comes within ~11 s 
of `hbase.regionserver.close.wait.time.ms` (60 s), after which a region server 
with `hbase.regionserver.close.wait.abort=true` aborts.
   
   The signature of this stall, seen in a production cluster, is a metadata 
handler thread logging a client-side `SocketTimeoutException: 
callTimeout=60000, callDuration=~68400 ... SYSTEM.CATALOG ... is closing` for 
the same region on the same host, immediately followed by `Acquired close lock 
on SYSTEM.CATALOG ... after waiting ~48600 ms`. The new IT reproduces exactly 
that (`callDuration=68692`, close 49.2 s).
   
   ### Does this PR introduce _any_ user-facing change?
   
   - New server-side configuration `phoenix.metadata.server.lookup.timeout.ms` 
(default `10000`). It only affects TTL lookups whose rows are in a different 
SYSTEM.CATALOG region, i.e. splittable SYSTEM.CATALOG. Such a lookup now fails 
sooner against a slow or unavailable remote region (the client's `getTable` 
retry handles it) instead of retrying for up to the default client limits.
   - Behavior change: closing or moving SYSTEM.CATALOG no longer stalls ~49 s 
when a `getTable` is resolving TTL. The TTL values resolved are unchanged.
   
   ### How was this patch tested?
   
   New tests:
   
   - `SystemCatalogTTLLookupIT` (own mini-cluster, with the default client 
retries and 60 s scanner timeout restored so the old behavior reproduces as in 
production):
     - `testTableWithIndexesDoesNotScanSystemCatalogViaRpc` and 
`testViewHierarchyDoesNotScanSystemCatalogViaRpc` (table → view → view, plus a 
view index) assert the resolved TTLs and that no client scan reaches 
SYSTEM.CATALOG while the PTables are rebuilt. A `preScannerOpen` observer 
counts them; it fires only on the RPC path. A positive control checks the 
observer counts a direct client scan.
     - `testSystemCatalogCloseIsNotStalledByTTLLookup` closes SYSTEM.CATALOG 
while a `getTable` is resolving TTL and asserts the close takes < 10 s.
   - `SystemCatalogTTLLookupSplitIT` (extends `SplitSystemCatalogIT`): tenant 
views whose ancestors are in other SYSTEM.CATALOG regions, including a 
hierarchy where the first hop is already remote. Asserts that the keys are in 
distinct regions, that each view's own (local) rows are not client-scanned, 
that the remote ancestors are, and that the views resolve the table's TTL.
   - `ServerUtilTest`: `getMetadataConfig` timeouts and retries (defaults, 
overrides, larger pause, server-overloaded pause, non-positive timeout), 
`getRetriesWithinTimeout` edge cases, and connection type routing.
   
   All the new ITs fail without the fix (close took 49.2 s; 2 and 8 client 
scans; split IT 1 instead of 0) and pass with it. Both ITs passed 10 
consecutive runs; the SYSTEM.CATALOG close took 187–602 ms.
   
   Existing suites run with the change, all passing: `ViewTTLIT`, 
`TTLAsPhoenixTTLIT`, `ViewTTLWithLongViewIndexEnabledIT`, 
`ViewTTLNotEnabledIT`, `ConditionalTTLExpressionIT`, `StrictTTLPropertyIT`, 
`CDCQueryIT`, `CDCStreamIT`, `CDCStreamCompactionTTLIT`, `ViewIndexIT`, 
`TenantSpecificViewIndexIT`, `TenantSpecificViewIndexSaltedIT`, 
`ReadOnlyViewOnReadOnlyIT`.
   
   Not in this PR (possible follow-up): the `getTableNoCache` call in 
`getTableFromCells` for `PHYSICAL_TABLE` links, which runs only with splittable 
SYSTEM.CATALOG, goes through a server-side Phoenix connection and is not 
bounded by the new connection.
   
   ### Was this patch authored or co-authored using generative AI tooling?
   
   Generated-by: Claude Code (Claude Opus 5.5)
   


-- 
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