mateusaubin opened a new pull request, #16861:
URL: https://github.com/apache/iceberg/pull/16861

   ## What
   
   Make `CachingCatalog` and the Spark catalogs (`SparkCatalog`,
   `SparkSessionCatalog` via `BaseCatalog`) implement `Closeable` and
   forward `close()` to the catalog they wrap, guarding each hop with an
   `instanceof Closeable` check.
   
   ## Why
   
   Catalogs that hold network clients rely on `Catalog.close()` to release
   those resources. The REST catalog, for example, drains its pooled HTTP
   connections on `close()`. That call never reached the wrapped catalog
   through the Spark stack:
   
   - `CachingCatalog` wraps a delegate `Catalog` but did not implement
     `Closeable`, so closing the wrapper never closed the delegate.
   - `SparkCatalog` / `SparkSessionCatalog` (via `BaseCatalog`) were not
     `Closeable`, so the underlying Iceberg catalog was never closed.
   
   On a long-running Spark cluster with frequent catalog changes, every
   discarded catalog left its client connections and local ports open.
   Over time these accumulated and exhausted the available ephemeral
   ports, surfacing as `BindException`.
   
   The fix is generic: any closeable backend (REST, JDBC-backed, cloud SDK
   catalogs, and `FileIO` implementations holding their own pools) now gets
   its `close()` invoked through the same path. Delegates that are not
   `Closeable` are skipped by the guard, so custom/in-memory catalogs are
   unaffected.
   
   ## Changes
   
   - `core`: `CachingCatalog implements Closeable`, forwards `close()` to
     its delegate.
   - `spark` (v3.5 / v4.0 / v4.1): `BaseCatalog implements Closeable`;
     `SparkCatalog` and `SparkSessionCatalog` forward `close()` to their
     underlying Iceberg catalog.
   
   ## Tests
   
   Added contract tests in `TestCachingCatalog`:
   - `closePropagatesToWrappedCatalog` — verifies `close()` reaches a
     closeable delegate (Mockito spy on a real `hadoopCatalog()`).
   - `closeIsSafeWhenWrappedCatalogIsNotCloseable` — verifies the
     `instanceof Closeable` guard makes `close()` a no-op for
     non-closeable delegates.
   
   ## Notes
   
   This addresses connection/port leakage on the close path only. Catalogs
   that are never closed (e.g. orphaned by paths outside our control) are
   out of scope here; an autonomous idle/TTL connection eviction mechanism
   could be considered as a follow-up.
   
   AI assistance was used to draft the commit message and this PR
   description, and to evaluate the completeness of the fix. The
   implementation and design (using `Closeable` for parity with existing
   in-tree catalogs, and guarding each delegate hop) were reviewed and
   verified manually.
   


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


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to