yuqi1129 commented on PR #12852:
URL: https://github.com/apache/gravitino/pull/12852#issuecomment-5510161015

   Thanks for the fix. Before going into the details, I want to ask one thing 
about the premise, and suggest another place to fix it.
   
   ### Is `catalog-backend=memory` + auxiliary Iceberg REST a combination we 
want to support?
   
   The memory backend is basically a test/demo backend. Its data is gone when 
the process restarts, and it is also gone when `CatalogManager` evicts the 
catalog from `catalogCache` 
(`expireAfterAccess(CATALOG_CACHE_EVICTION_INTERVAL_MS)`), because the borrowed 
`InMemoryCatalog` is dropped together with the old `IcebergCatalogOperations`.
   
   So before we add API for it: do we have a real use case for this 
combination, or does it only show up in demos and ITs? If it is the latter, the 
cheapest fix is to fail fast when a memory-backend catalog is used with the 
auxiliary REST service. Today it returns a 500 anyway, so we would only be 
replacing a confusing error with a clear one.
   
   If we do want to support it, I think there is a simpler place to fix it.
   
   ### Suggestion: intern the memory catalog instead of passing the instance 
around
   
   The current approach hands a live Iceberg `Catalog` from `CatalogManager` to 
the REST wrapper. That single decision brings in everything else in this PR: 
the new `IcebergCatalogBackendProvider` interface, the `closeCatalogOnClose` 
flag, the `default_catalog` alias resolution, and a dependency between two 
caches that have different lifecycles.
   
   Instead, `IcebergCatalogUtil.loadMemoryCatalog()` could return the same 
instance for the same Gravitino catalog, i.e. keep them in a 
`ConcurrentHashMap` instead of calling `new 
MemoryCatalogWithMetadataLocationSupport()` every time.
   
   This works across the isolated class loader: `IcebergCatalogUtil` is in 
`org.apache.gravitino.iceberg.common.utils`, which matches no prefix in 
`IsolatedClassLoader.isCatalogClass()`, so it is a shared class and is loaded 
by the base class loader. There is only one copy of that static state in the 
process, no matter how many catalog class loaders exist.
   
   Then both sides just call `loadCatalogBackend()` as they do today and get 
the same instance. We would not need:
   
   - the new interface, or exposing a raw Iceberg `Catalog` on 
`CatalogOperations`
   - `closeCatalogOnClose`
   - the `default_catalog` alias resolution
   - the `auxMode && MEMORY && DynamicIcebergConfigProvider` condition, since 
it works whichever side creates the catalog first
   
   Two details to be careful about if you go this way:
   
   1. Do not use `getCatalogBackendName()` as the map key. 
`IcebergPropertiesUtils.getCatalogBackendName()` falls back to the backend type 
string `"memory"` when `catalog-backend-name` is not set, so two memory 
catalogs in the same metalake would collide. 
`IcebergCatalogOperations.initialize()` already puts `catalog_uuid` into the 
config (nothing reads it today), and 
`DynamicIcebergConfigProvider.resolveProps()` has the Gravitino `Catalog` 
object at hand, so a stable key is one line away on each side.
   2. Remove the entry when the catalog is dropped, otherwise it leaks. It 
should not be removed on idle eviction though, that would throw away the data.
   
   ### A problem in the current approach that this would also avoid
   
   The listener registered in `IcebergCatalogWrapperManager` invalidates 
`catalogWrapperCache` by `ident.name()`, but a client that connects without a 
warehouse prefix is cached under `default_catalog` 
(`IcebergRESTUtils.getCatalogName("")`). The two keys do not match, so the 
`default_catalog` entry keeps the evicted backend. I wrote a small test for 
this:
   
   ```
   default_catalog still borrows the evicted backend: true
   written into evicted backend : true
   visible in current backend   : false      <- #12851 again
   named catalog re-borrows new backend: true
   ```
   
   `CatalogManager.catalogCache` uses `expireAfterAccess`, so this is not a 
corner case. With a named prefix it works, but a client using the default 
catalog silently falls back into the bug this PR fixes once the catalog is 
evicted, until the REST side cache expires as well.
   
   This can of course be fixed inside the current design (also invalidate 
`default_catalog` when `ident.name()` equals 
`configProvider.getDefaultCatalogName()`). I mention it mainly because looking 
the catalog up by identity, instead of holding a reference to it, makes this 
whole class of problem go away.
   
   I have more comments on the tests, but let's agree on the direction first.
   


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