This is an automated email from the ASF dual-hosted git repository.
roryqi pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git
The following commit(s) were added to refs/heads/main by this push:
new a8414f6de3 [#9745][followup] fix(core): Fix ReverseIndexRules for
GenericEntity to skip entities with namespace (#10000)
a8414f6de3 is described below
commit a8414f6de3cbc3e507113ee1eba1594e3303756b
Author: Bharath Krishna <[email protected]>
AuthorDate: Mon Feb 16 06:02:57 2026 +0530
[#9745][followup] fix(core): Fix ReverseIndexRules for GenericEntity to
skip entities with namespace (#10000)
### What changes were proposed in this pull request?
Fixed GENERIC_METADATA_OBJECT_REVERSE_RULE in ReverseIndexRules.java to
only process GenericEntity objects without namespace (policy metadata
objects). Added a namespace check (genericEntity.namespace() == null ||
genericEntity.namespace().isEmpty()) to skip entities with namespace.
### Why are the changes needed?
Views don't support tags or policies (see
TagManager.SUPPORTED_METADATA_OBJECT_TYPES_FOR_TAGS), so they should NOT
be indexed in the reverse cache at all. Creating reverse index entries
for views wastes memory and has no purpose.
When views are cached as GenericEntity (during auto-import in
ViewOperationDispatcher.loadView(), they were triggering
GENERIC_METADATA_OBJECT_REVERSE_RULE which was trying to create
meaningless reverse index entries.
Fix: #9745
### Does this PR introduce _any_ user-facing change?
No. This is an internal cache optimization fix.
### How was this patch tested?
Added test
---
.../apache/gravitino/cache/ReverseIndexRules.java | 8 ++-
.../storage/TestEntityStorageRelationCache.java | 69 ++++++++++++++++++++++
2 files changed, 75 insertions(+), 2 deletions(-)
diff --git
a/core/src/main/java/org/apache/gravitino/cache/ReverseIndexRules.java
b/core/src/main/java/org/apache/gravitino/cache/ReverseIndexRules.java
index 1c9f4d6532..a58e31ed8a 100644
--- a/core/src/main/java/org/apache/gravitino/cache/ReverseIndexRules.java
+++ b/core/src/main/java/org/apache/gravitino/cache/ReverseIndexRules.java
@@ -115,12 +115,16 @@ public class ReverseIndexRules {
// Keep policies/tags to objects reverse index for metadata objects, so the
key are objects and
// the values are policies/tags.
+ // Only processes GenericEntity objects without namespace (metadata objects
from tag/policy
+ // queries).
+ // Entities with namespace (views, tables) are skipped.
public static final ReverseIndexCache.ReverseIndexRule
GENERIC_METADATA_OBJECT_REVERSE_RULE =
(entity, key, reverseIndexCache) -> {
- // Name in GenericEntity contains no metalake.
GenericEntity genericEntity = (GenericEntity) entity;
EntityType type = entity.type();
- if (genericEntity.name() != null) {
+ if (genericEntity.name() != null
+ && (genericEntity.namespace() == null ||
genericEntity.namespace().isEmpty())) {
+ // Name contains catalog.schema.object format without metalake, so
prepend it.
String[] levels = genericEntity.name().split("\\.");
String metalakeName = key.identifier().namespace().levels()[0];
NameIdentifier objectNameIdentifier =
diff --git
a/core/src/test/java/org/apache/gravitino/storage/TestEntityStorageRelationCache.java
b/core/src/test/java/org/apache/gravitino/storage/TestEntityStorageRelationCache.java
index b645d8126a..2b73260790 100644
---
a/core/src/test/java/org/apache/gravitino/storage/TestEntityStorageRelationCache.java
+++
b/core/src/test/java/org/apache/gravitino/storage/TestEntityStorageRelationCache.java
@@ -773,4 +773,73 @@ public class TestEntityStorageRelationCache extends
AbstractEntityStorageTest {
destroy(type);
}
}
+
+ @ParameterizedTest
+ @MethodSource("storageProvider")
+ void testViewNotIndexedInReverseCache(String type, boolean enableCache)
throws Exception {
+ Config config = Mockito.mock(Config.class);
+ Mockito.when(config.get(Configs.CACHE_ENABLED)).thenReturn(enableCache);
+ init(type, config);
+
+ AuditInfo auditInfo =
+
AuditInfo.builder().withCreator("creator").withCreateTime(Instant.now()).build();
+
+ try (EntityStore store = EntityStoreFactory.createEntityStore(config)) {
+ store.initialize(config);
+
+ // Create parent entities required by relational store
+ BaseMetalake metalake =
+ createBaseMakeLake(RandomIdGenerator.INSTANCE.nextId(), "metalake",
auditInfo);
+ store.put(metalake, false);
+
+ CatalogEntity catalog =
+ createCatalog(
+ RandomIdGenerator.INSTANCE.nextId(),
+ NamespaceUtil.ofCatalog("metalake"),
+ "catalog",
+ auditInfo);
+ store.put(catalog, false);
+
+ SchemaEntity schema =
+ createSchemaEntity(
+ RandomIdGenerator.INSTANCE.nextId(),
+ Namespace.of("metalake", "catalog"),
+ "schema",
+ auditInfo);
+ store.put(schema, false);
+
+ Namespace viewNamespace = Namespace.of("metalake", "catalog", "schema");
+ GenericEntity view =
+ GenericEntity.builder()
+ .withId(RandomIdGenerator.INSTANCE.nextId())
+ .withName("test_view")
+ .withNamespace(viewNamespace)
+ .withEntityType(Entity.EntityType.VIEW)
+ .build();
+
+ // Use store.put() to trigger the actual cache + reverse index flow
+ store.put(view, false);
+
+ // Verify view IS in forward cache (performance cache for get operations)
+ GenericEntity retrievedView =
+ store.get(view.nameIdentifier(), Entity.EntityType.VIEW,
GenericEntity.class);
+ Assertions.assertNotNull(retrievedView);
+ Assertions.assertEquals(view.id(), retrievedView.id());
+ Assertions.assertEquals(view.name(), retrievedView.name());
+
+ // Get reverse index cache to verify view is NOT indexed
+ ReverseIndexCache reverseIndexCache =
+ ((CaffeineEntityCache) ((RelationalEntityStore)
store).getCache()).getReverseIndex();
+
+ // Verify view is NOT in reverse index cache
+ // Views have namespace and should be skipped by
GENERIC_METADATA_OBJECT_REVERSE_RULE
+ List<EntityCacheKey> reverseIndexValue =
+ reverseIndexCache.get(view.nameIdentifier(), Entity.EntityType.VIEW);
+ Assertions.assertNull(
+ reverseIndexValue,
+ "Views should NOT be indexed in reverse cache - they have namespace
and don't support tags/policies");
+
+ destroy(type);
+ }
+ }
}