This is an automated email from the ASF dual-hosted git repository.
jshao 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 4ea6d94ca7 [#7177] feat(core): Add a Caffeine-based implementation for
EntityCache (#7330)
4ea6d94ca7 is described below
commit 4ea6d94ca7f317990307f4bca680681366b3ab11
Author: Lord of Abyss <[email protected]>
AuthorDate: Wed Jun 18 00:09:59 2025 +0800
[#7177] feat(core): Add a Caffeine-based implementation for EntityCache
(#7330)
### What changes were proposed in this pull request?
Fix some bugs in EntityCache and add test cases.
1. Move the database access logic to `BaseEntityCache` for better reuse
and abstraction.
2. Add an `allFields` parameter to `loadEntitiesByRelation` to align
with `SupportsRelationOperations#listEntitiesByRelation`.
3. Add an entityCache field to `GravitinoEnv` for direct access to the
cache from components.
- [X] Implement the methods related to the `SupportsEntityStoreCache`
and `SupportsRelationEntityCache` interface in `CaffeineEntityCache`.
- [X] Add unit tests for both index and cache.
- [ ] Use JCStress to perform multi-threaded testing on
`CaffeineEntityCache` and the `CacheIndex`.
| **Category** | **Test Case Description** | **Method(s)** |
| ----------------------- |
------------------------------------------------- |
------------------------------------------------------------ |
| **Basic Functionality** | Basic put/get/getIfPresent operations |
`testPutAndGet`, `testGetIfPresent` |
| | Same identifier with different entity types |
`testPutSameIdentifierEntities` |
| | Size counting | `testSize` |
| | Clear the cache | `testClear` |
| **Invalidation** | Invalidate by METALAKE/CATALOG/SCHEMA/TABLE level |
`testInvalidateMetalake`, `testInvalidateCatalog`,
`testInvalidateSchema`, `testInvalidateTable` |
| | Invalidate non-existent entity | `testRemoveNonExistentEntity` |
| **Relation Handling** | Put/Get/Invalidate entity relations | Covered
in multiple tests (e.g., `testPutAndGet`, `testGetIfPresent`) |
| **Eviction Policies** | Expire by time | `testExpireByTime` |
| | Expire by weight | `testExpireByWeight` |
| | Exceed max weight immediately | `testExpireByWeightExceedMaxWeight`
|
| | Expire by size | `testExpireBySize` |
| **Weight Logic** | Correctness of entity weight calculation |
`testWeightCalculation` |
| **Error & Boundary** | Null argument checks |
`testGetIfPresentWithNull`, `testContainsWithNull`,
`testInvalidateWithNull`, `testPutWithNull` |
### Why are the changes needed?
Fix: #7177
### Does this PR introduce _any_ user-facing change?
no
### How was this patch tested?
local test.
---
.../hadoop/TestHadoopCatalogOperations.java | 1 +
.../catalog/kafka/TestKafkaCatalogOperations.java | 1 +
.../catalog/model/TestModelCatalogOperations.java | 1 +
.../main/java/org/apache/gravitino/Configs.java | 9 +
.../org/apache/gravitino/cache/CacheFactory.java | 55 +++
.../storage/relational/RelationalEntityStore.java | 5 +-
.../authorization/TestAccessControlManager.java | 1 +
.../gravitino/authorization/TestOwnerManager.java | 1 +
.../apache/gravitino/cache/TestCacheConfig.java | 1 +
...{TestCacheConfig.java => TestCacheFactory.java} | 32 +-
.../org/apache/gravitino/cache/TestCacheIndex.java | 226 ++++++++++
.../gravitino/cache/TestCaffeineEntityCache.java | 454 +++++++++++++++++++--
.../gravitino/storage/TestEntityStorage.java | 1 +
.../org/apache/gravitino/tag/TestTagManager.java | 1 +
14 files changed, 743 insertions(+), 46 deletions(-)
diff --git
a/catalogs/catalog-hadoop/src/test/java/org/apache/gravitino/catalog/hadoop/TestHadoopCatalogOperations.java
b/catalogs/catalog-hadoop/src/test/java/org/apache/gravitino/catalog/hadoop/TestHadoopCatalogOperations.java
index 4b1b936632..35c34a07db 100644
---
a/catalogs/catalog-hadoop/src/test/java/org/apache/gravitino/catalog/hadoop/TestHadoopCatalogOperations.java
+++
b/catalogs/catalog-hadoop/src/test/java/org/apache/gravitino/catalog/hadoop/TestHadoopCatalogOperations.java
@@ -226,6 +226,7 @@ public class TestHadoopCatalogOperations {
Mockito.when(config.get(Configs.CACHE_EXPIRATION_TIME)).thenReturn(3_600_000L);
Mockito.when(config.get(Configs.CACHE_WEIGHER_ENABLED)).thenReturn(true);
Mockito.when(config.get(Configs.CACHE_STATS_ENABLED)).thenReturn(false);
+
Mockito.when(config.get(Configs.CACHE_IMPLEMENTATION)).thenReturn("caffeine");
store = EntityStoreFactory.createEntityStore(config);
store.initialize(config);
diff --git
a/catalogs/catalog-kafka/src/test/java/org/apache/gravitino/catalog/kafka/TestKafkaCatalogOperations.java
b/catalogs/catalog-kafka/src/test/java/org/apache/gravitino/catalog/kafka/TestKafkaCatalogOperations.java
index e820b8dd4d..007477271d 100644
---
a/catalogs/catalog-kafka/src/test/java/org/apache/gravitino/catalog/kafka/TestKafkaCatalogOperations.java
+++
b/catalogs/catalog-kafka/src/test/java/org/apache/gravitino/catalog/kafka/TestKafkaCatalogOperations.java
@@ -157,6 +157,7 @@ public class TestKafkaCatalogOperations extends
KafkaClusterEmbedded {
Mockito.when(config.get(Configs.CACHE_EXPIRATION_TIME)).thenReturn(3_600_000L);
Mockito.when(config.get(Configs.CACHE_WEIGHER_ENABLED)).thenReturn(true);
Mockito.when(config.get(Configs.CACHE_STATS_ENABLED)).thenReturn(false);
+
Mockito.when(config.get(Configs.CACHE_IMPLEMENTATION)).thenReturn("caffeine");
// Mock
MetalakeMetaService metalakeMetaService =
MetalakeMetaService.getInstance();
diff --git
a/catalogs/catalog-model/src/test/java/org/apache/gravtitino/catalog/model/TestModelCatalogOperations.java
b/catalogs/catalog-model/src/test/java/org/apache/gravtitino/catalog/model/TestModelCatalogOperations.java
index 709999fd81..930e29f8ad 100644
---
a/catalogs/catalog-model/src/test/java/org/apache/gravtitino/catalog/model/TestModelCatalogOperations.java
+++
b/catalogs/catalog-model/src/test/java/org/apache/gravtitino/catalog/model/TestModelCatalogOperations.java
@@ -126,6 +126,7 @@ public class TestModelCatalogOperations {
Mockito.when(config.get(Configs.CACHE_EXPIRATION_TIME)).thenReturn(3_600_000L);
Mockito.when(config.get(Configs.CACHE_WEIGHER_ENABLED)).thenReturn(true);
Mockito.when(config.get(Configs.CACHE_STATS_ENABLED)).thenReturn(false);
+
Mockito.when(config.get(Configs.CACHE_IMPLEMENTATION)).thenReturn("caffeine");
store = EntityStoreFactory.createEntityStore(config);
store.initialize(config);
diff --git a/core/src/main/java/org/apache/gravitino/Configs.java
b/core/src/main/java/org/apache/gravitino/Configs.java
index 95af2e0f0f..76f5235f6f 100644
--- a/core/src/main/java/org/apache/gravitino/Configs.java
+++ b/core/src/main/java/org/apache/gravitino/Configs.java
@@ -389,4 +389,13 @@ public class Configs {
.version(ConfigConstants.VERSION_1_0_0)
.booleanConf()
.createWithDefault(true);
+
+ // Provider name for cache
+ public static final ConfigEntry<String> CACHE_IMPLEMENTATION =
+ new ConfigBuilder("gravitino.cache.implementation")
+ .doc("Which cache implementation to use")
+ .version(ConfigConstants.VERSION_1_0_0)
+ .stringConf()
+ .checkValue(StringUtils::isNotBlank,
ConfigConstants.NOT_BLANK_ERROR_MSG)
+ .createWithDefault("caffeine");
}
diff --git a/core/src/main/java/org/apache/gravitino/cache/CacheFactory.java
b/core/src/main/java/org/apache/gravitino/cache/CacheFactory.java
new file mode 100644
index 0000000000..db4ff36374
--- /dev/null
+++ b/core/src/main/java/org/apache/gravitino/cache/CacheFactory.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.gravitino.cache;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.gravitino.Config;
+import org.apache.gravitino.Configs;
+
+/** Factory class for creating {@link org.apache.gravitino.cache.EntityCache}
instances. */
+public final class CacheFactory {
+
+ // Register EntityCache's short name to its full qualified class name in the
map. So that user
+ // doesn't need to specify the full qualified class name when creating an
EntityCache instance.
+ public static final ImmutableMap<String, String> ENTITY_CACHES =
+ ImmutableMap.of("caffeine",
CaffeineEntityCache.class.getCanonicalName());
+
+ // Private constructor to prevent instantiation of this factory class.
+ private CacheFactory() {}
+
+ /**
+ * Creates a new {@link org.apache.gravitino.cache.EntityCache} using the
cache type specified in
+ * the configuration.
+ *
+ * @param config The configuration.
+ * @return A cache instance
+ */
+ public static EntityCache getEntityCache(Config config) {
+ String name = config.get(Configs.CACHE_IMPLEMENTATION);
+ String className = ENTITY_CACHES.getOrDefault(name, name);
+
+ try {
+ return (EntityCache)
+
Class.forName(className).getDeclaredConstructor(Config.class).newInstance(config);
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to create and initialize EntityCache:
" + name, e);
+ }
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/RelationalEntityStore.java
b/core/src/main/java/org/apache/gravitino/storage/relational/RelationalEntityStore.java
index 2bc2075f70..296629e518 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/RelationalEntityStore.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/RelationalEntityStore.java
@@ -35,7 +35,7 @@ import org.apache.gravitino.MetadataObject;
import org.apache.gravitino.NameIdentifier;
import org.apache.gravitino.Namespace;
import org.apache.gravitino.SupportsRelationOperations;
-import org.apache.gravitino.cache.CaffeineEntityCache;
+import org.apache.gravitino.cache.CacheFactory;
import org.apache.gravitino.cache.EntityCache;
import org.apache.gravitino.cache.NoOpsCache;
import org.apache.gravitino.exceptions.NoSuchEntityException;
@@ -65,10 +65,9 @@ public class RelationalEntityStore
this.backend = createRelationalEntityBackend(config);
this.garbageCollector = new RelationalGarbageCollector(backend, config);
this.garbageCollector.start();
- // TODO USE SPI to load the cache
this.cache =
config.get(Configs.CACHE_ENABLED)
- ? new CaffeineEntityCache(config)
+ ? CacheFactory.getEntityCache(config)
: new NoOpsCache(config);
}
diff --git
a/core/src/test/java/org/apache/gravitino/authorization/TestAccessControlManager.java
b/core/src/test/java/org/apache/gravitino/authorization/TestAccessControlManager.java
index e93deab223..21d4dcb477 100644
---
a/core/src/test/java/org/apache/gravitino/authorization/TestAccessControlManager.java
+++
b/core/src/test/java/org/apache/gravitino/authorization/TestAccessControlManager.java
@@ -137,6 +137,7 @@ public class TestAccessControlManager {
Mockito.when(config.get(Configs.CACHE_EXPIRATION_TIME)).thenReturn(3_600_000L);
Mockito.when(config.get(Configs.CACHE_WEIGHER_ENABLED)).thenReturn(true);
Mockito.when(config.get(Configs.CACHE_STATS_ENABLED)).thenReturn(false);
+
Mockito.when(config.get(Configs.CACHE_IMPLEMENTATION)).thenReturn("caffeine");
Mockito.doReturn(100000L).when(config).get(TREE_LOCK_MAX_NODE_IN_MEMORY);
Mockito.doReturn(1000L).when(config).get(TREE_LOCK_MIN_NODE_IN_MEMORY);
diff --git
a/core/src/test/java/org/apache/gravitino/authorization/TestOwnerManager.java
b/core/src/test/java/org/apache/gravitino/authorization/TestOwnerManager.java
index 95dd6fcd21..889e4a120f 100644
---
a/core/src/test/java/org/apache/gravitino/authorization/TestOwnerManager.java
+++
b/core/src/test/java/org/apache/gravitino/authorization/TestOwnerManager.java
@@ -110,6 +110,7 @@ public class TestOwnerManager {
Mockito.when(config.get(Configs.CACHE_EXPIRATION_TIME)).thenReturn(3_600_000L);
Mockito.when(config.get(Configs.CACHE_WEIGHER_ENABLED)).thenReturn(true);
Mockito.when(config.get(Configs.CACHE_STATS_ENABLED)).thenReturn(false);
+
Mockito.when(config.get(Configs.CACHE_IMPLEMENTATION)).thenReturn("caffeine");
Mockito.doReturn(100000L).when(config).get(TREE_LOCK_MAX_NODE_IN_MEMORY);
Mockito.doReturn(1000L).when(config).get(TREE_LOCK_MIN_NODE_IN_MEMORY);
diff --git a/core/src/test/java/org/apache/gravitino/cache/TestCacheConfig.java
b/core/src/test/java/org/apache/gravitino/cache/TestCacheConfig.java
index 4316b777f5..50d714d1fc 100644
--- a/core/src/test/java/org/apache/gravitino/cache/TestCacheConfig.java
+++ b/core/src/test/java/org/apache/gravitino/cache/TestCacheConfig.java
@@ -37,6 +37,7 @@ public class TestCacheConfig {
Assertions.assertEquals(10_000, config.get(Configs.CACHE_MAX_ENTRIES));
Assertions.assertEquals(3_600_000L,
config.get(Configs.CACHE_EXPIRATION_TIME));
Assertions.assertEquals(200_302_000L, EntityCacheWeigher.getMaxWeight());
+ Assertions.assertEquals("caffeine",
config.get(Configs.CACHE_IMPLEMENTATION));
}
@Test
diff --git a/core/src/test/java/org/apache/gravitino/cache/TestCacheConfig.java
b/core/src/test/java/org/apache/gravitino/cache/TestCacheFactory.java
similarity index 53%
copy from core/src/test/java/org/apache/gravitino/cache/TestCacheConfig.java
copy to core/src/test/java/org/apache/gravitino/cache/TestCacheFactory.java
index 4316b777f5..562c2d9f13 100644
--- a/core/src/test/java/org/apache/gravitino/cache/TestCacheConfig.java
+++ b/core/src/test/java/org/apache/gravitino/cache/TestCacheFactory.java
@@ -19,31 +19,29 @@
package org.apache.gravitino.cache;
-import com.google.common.collect.Lists;
-import java.util.ArrayList;
-import java.util.Optional;
import org.apache.gravitino.Config;
import org.apache.gravitino.Configs;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInstance;
+
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
+public class TestCacheFactory {
-public class TestCacheConfig {
@Test
- void testDefaultCacheConfig() {
- Config config = new Config(false) {};
- Assertions.assertFalse(config.get(Configs.CACHE_STATS_ENABLED));
- Assertions.assertTrue(config.get(Configs.CACHE_ENABLED));
- Assertions.assertTrue(config.get(Configs.CACHE_WEIGHER_ENABLED));
- Assertions.assertEquals(10_000, config.get(Configs.CACHE_MAX_ENTRIES));
- Assertions.assertEquals(3_600_000L,
config.get(Configs.CACHE_EXPIRATION_TIME));
- Assertions.assertEquals(200_302_000L, EntityCacheWeigher.getMaxWeight());
+ void testGetCache() {
+ Config config = new Config() {};
+ EntityCache entityCache = CacheFactory.getEntityCache(config);
+ Assertions.assertInstanceOf(CaffeineEntityCache.class, entityCache);
+
+ entityCache = CacheFactory.getEntityCache(config);
+ Assertions.assertInstanceOf(CaffeineEntityCache.class, entityCache);
}
@Test
- void test() {
- ArrayList<Integer> list = Lists.newArrayList();
- Optional<Integer> i =
- Optional.ofNullable(list).filter(entities ->
!entities.isEmpty()).map(l -> l.get(0));
- Assertions.assertFalse(i.isPresent());
+ void testCreateCacheWithInvalidName() {
+ Config config = new Config() {};
+ config.set(Configs.CACHE_IMPLEMENTATION, "InvalidCacheName");
+ Assertions.assertThrows(RuntimeException.class, () ->
CacheFactory.getEntityCache(config));
}
}
diff --git a/core/src/test/java/org/apache/gravitino/cache/TestCacheIndex.java
b/core/src/test/java/org/apache/gravitino/cache/TestCacheIndex.java
new file mode 100644
index 0000000000..d87995fdea
--- /dev/null
+++ b/core/src/test/java/org/apache/gravitino/cache/TestCacheIndex.java
@@ -0,0 +1,226 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.gravitino.cache;
+
+import com.google.common.collect.ImmutableList;
+import com.googlecode.concurrenttrees.radix.ConcurrentRadixTree;
+import com.googlecode.concurrenttrees.radix.RadixTree;
+import
com.googlecode.concurrenttrees.radix.node.concrete.DefaultCharArrayNodeFactory;
+import java.util.List;
+import org.apache.gravitino.Entity;
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.SupportsRelationOperations;
+import org.apache.gravitino.utils.NameIdentifierUtil;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class TestCacheIndex {
+ private RadixTree<EntityCacheKey> indexTree;
+
+ private NameIdentifier ident1;
+ private NameIdentifier ident2;
+ private NameIdentifier ident3;
+ private NameIdentifier ident4;
+ private NameIdentifier ident5;
+ private NameIdentifier ident6;
+ private NameIdentifier ident7;
+ private NameIdentifier ident8;
+ private NameIdentifier ident9;
+ private NameIdentifier ident10;
+ private NameIdentifier ident11;
+ private NameIdentifier ident12;
+
+ private EntityCacheKey key1;
+ private EntityCacheKey key2;
+ private EntityCacheKey key3;
+ private EntityCacheKey key4;
+ private EntityCacheKey key5;
+ private EntityCacheKey key6;
+ private EntityCacheKey key7;
+ private EntityCacheKey key8;
+ private EntityCacheKey key9;
+ private EntityCacheKey key10;
+ private EntityCacheKey key11;
+ private EntityCacheKey key12;
+
+ @BeforeEach
+ void setUp() {
+ indexTree = new ConcurrentRadixTree<>(new DefaultCharArrayNodeFactory());
+ ident1 = NameIdentifier.of("metalake1", "catalog1", "schema1");
+ ident2 = NameIdentifier.of("metalake2", "catalog2", "schema2");
+ ident3 = NameIdentifier.of("metalake1", "catalog1", "schema1", "table");
+ ident4 = NameIdentifier.of("metalake1", "catalog1", "schema1", "topic");
+ ident5 = NameIdentifier.of("metalake1", "catalog2", "schema1", "table");
+ ident6 = NameIdentifier.of("metalake1", "catalog1", "schema2", "table");
+
+ ident7 = NameIdentifierUtil.ofRole("metalake1", "role1");
+ ident8 = NameIdentifierUtil.ofRole("metalake2", "role2");
+
+ ident9 = NameIdentifierUtil.ofGroup("metalake1", "group1");
+ ident10 = NameIdentifierUtil.ofGroup("metalake1", "group2");
+
+ ident11 = NameIdentifierUtil.ofUser("metalake2", "user1");
+ ident12 = NameIdentifierUtil.ofUser("metalake2", "user2");
+
+ key1 = EntityCacheKey.of(ident1, Entity.EntityType.SCHEMA);
+ key2 = EntityCacheKey.of(ident2, Entity.EntityType.SCHEMA);
+ key3 = EntityCacheKey.of(ident3, Entity.EntityType.TABLE);
+ key4 = EntityCacheKey.of(ident4, Entity.EntityType.TOPIC);
+ key5 = EntityCacheKey.of(ident5, Entity.EntityType.TABLE);
+ key6 = EntityCacheKey.of(ident6, Entity.EntityType.TABLE);
+
+ key7 =
+ EntityCacheKey.of(
+ ident7, Entity.EntityType.ROLE,
SupportsRelationOperations.Type.ROLE_GROUP_REL);
+ key8 =
+ EntityCacheKey.of(
+ ident8, Entity.EntityType.ROLE,
SupportsRelationOperations.Type.ROLE_USER_REL);
+
+ key9 = EntityCacheKey.of(ident9, Entity.EntityType.GROUP);
+ key10 = EntityCacheKey.of(ident10, Entity.EntityType.GROUP);
+ key11 = EntityCacheKey.of(ident11, Entity.EntityType.USER);
+ key12 = EntityCacheKey.of(ident12, Entity.EntityType.USER);
+
+ addIndex(indexTree, key12);
+ addIndex(indexTree, key11);
+ addIndex(indexTree, key10);
+ addIndex(indexTree, key9);
+ addIndex(indexTree, key8);
+ addIndex(indexTree, key7);
+ addIndex(indexTree, key6);
+ addIndex(indexTree, key5);
+ addIndex(indexTree, key4);
+ addIndex(indexTree, key3);
+ addIndex(indexTree, key2);
+ addIndex(indexTree, key1);
+ }
+
+ @Test
+ void testAddIndex() {
+ Assertions.assertEquals(12, indexTree.size());
+ }
+
+ @Test
+ void testGetFromByMetalakePrefix() {
+ List<EntityCacheKey> storeEntityCacheKeys =
+
ImmutableList.copyOf(indexTree.getValuesForKeysStartingWith("metalake1"));
+
+ Assertions.assertEquals(8, storeEntityCacheKeys.size());
+ Assertions.assertTrue(storeEntityCacheKeys.contains(key1));
+ Assertions.assertTrue(storeEntityCacheKeys.contains(key3));
+ Assertions.assertTrue(storeEntityCacheKeys.contains(key4));
+ Assertions.assertTrue(storeEntityCacheKeys.contains(key5));
+ Assertions.assertTrue(storeEntityCacheKeys.contains(key6));
+ Assertions.assertTrue(storeEntityCacheKeys.contains(key7));
+ Assertions.assertTrue(storeEntityCacheKeys.contains(key9));
+ Assertions.assertTrue(storeEntityCacheKeys.contains(key10));
+
+ List<EntityCacheKey> storeEntityCacheKeys2 =
+
ImmutableList.copyOf(indexTree.getValuesForKeysStartingWith("metalake2"));
+
+ Assertions.assertEquals(4, storeEntityCacheKeys2.size());
+ Assertions.assertTrue(storeEntityCacheKeys2.contains(key2));
+ Assertions.assertTrue(storeEntityCacheKeys2.contains(key8));
+ Assertions.assertTrue(storeEntityCacheKeys2.contains(key11));
+ Assertions.assertTrue(storeEntityCacheKeys2.contains(key12));
+ }
+
+ @Test
+ void testGetByCatalogPrefix() {
+ List<EntityCacheKey> storeEntityCacheKeys =
+
ImmutableList.copyOf(indexTree.getValuesForKeysStartingWith("metalake1.catalog1"));
+
+ Assertions.assertEquals(4, storeEntityCacheKeys.size());
+ Assertions.assertTrue(storeEntityCacheKeys.contains(key1));
+ Assertions.assertTrue(storeEntityCacheKeys.contains(key3));
+ Assertions.assertTrue(storeEntityCacheKeys.contains(key4));
+ Assertions.assertTrue(storeEntityCacheKeys.contains(key6));
+
+ storeEntityCacheKeys =
+
ImmutableList.copyOf(indexTree.getValuesForKeysStartingWith("metalake1.catalog2"));
+ Assertions.assertEquals(1, storeEntityCacheKeys.size());
+ Assertions.assertTrue(storeEntityCacheKeys.contains(key5));
+ }
+
+ @Test
+ void testGetBySchemaPrefix() {
+ List<EntityCacheKey> storeEntityCacheKeys =
+
ImmutableList.copyOf(indexTree.getValuesForKeysStartingWith("metalake1.catalog1.schema1"));
+
+ Assertions.assertEquals(3, storeEntityCacheKeys.size());
+ Assertions.assertTrue(storeEntityCacheKeys.contains(key1));
+ Assertions.assertTrue(storeEntityCacheKeys.contains(key3));
+ Assertions.assertTrue(storeEntityCacheKeys.contains(key4));
+
+ storeEntityCacheKeys =
+
ImmutableList.copyOf(indexTree.getValuesForKeysStartingWith("metalake1.catalog1.schema2"));
+ Assertions.assertEquals(1, storeEntityCacheKeys.size());
+ Assertions.assertTrue(storeEntityCacheKeys.contains(key6));
+
+ storeEntityCacheKeys =
+
ImmutableList.copyOf(indexTree.getValuesForKeysStartingWith("metalake1.catalog2.schema1"));
+ Assertions.assertEquals(1, storeEntityCacheKeys.size());
+ Assertions.assertTrue(storeEntityCacheKeys.contains(key5));
+ }
+
+ @Test
+ void testGetByExactKey() {
+ EntityCacheKey storeEntityCacheKey =
indexTree.getValueForExactKey(key1.toString());
+ Assertions.assertEquals(key1, storeEntityCacheKey);
+
+ storeEntityCacheKey = indexTree.getValueForExactKey(key2.toString());
+ Assertions.assertEquals(key2, storeEntityCacheKey);
+
+ storeEntityCacheKey = indexTree.getValueForExactKey(key3.toString());
+ Assertions.assertEquals(key3, storeEntityCacheKey);
+
+ storeEntityCacheKey = indexTree.getValueForExactKey(key4.toString());
+ Assertions.assertEquals(key4, storeEntityCacheKey);
+
+ storeEntityCacheKey = indexTree.getValueForExactKey(key5.toString());
+ Assertions.assertEquals(key5, storeEntityCacheKey);
+
+ storeEntityCacheKey = indexTree.getValueForExactKey(key6.toString());
+ Assertions.assertEquals(key6, storeEntityCacheKey);
+
+ storeEntityCacheKey = indexTree.getValueForExactKey(key7.toString());
+ Assertions.assertEquals(key7, storeEntityCacheKey);
+
+ storeEntityCacheKey = indexTree.getValueForExactKey(key8.toString());
+ Assertions.assertEquals(key8, storeEntityCacheKey);
+
+ storeEntityCacheKey = indexTree.getValueForExactKey(key9.toString());
+ Assertions.assertEquals(key9, storeEntityCacheKey);
+
+ storeEntityCacheKey = indexTree.getValueForExactKey(key10.toString());
+ Assertions.assertEquals(key10, storeEntityCacheKey);
+
+ storeEntityCacheKey = indexTree.getValueForExactKey(key11.toString());
+ Assertions.assertEquals(key11, storeEntityCacheKey);
+
+ storeEntityCacheKey = indexTree.getValueForExactKey(key12.toString());
+ Assertions.assertEquals(key12, storeEntityCacheKey);
+ }
+
+ private void addIndex(RadixTree<EntityCacheKey> indexTree, EntityCacheKey
storeEntityCacheKey) {
+ indexTree.put(storeEntityCacheKey.toString(), storeEntityCacheKey);
+ }
+}
diff --git
a/core/src/test/java/org/apache/gravitino/cache/TestCaffeineEntityCache.java
b/core/src/test/java/org/apache/gravitino/cache/TestCaffeineEntityCache.java
index 57a60f1f4b..68e414bf7c 100644
--- a/core/src/test/java/org/apache/gravitino/cache/TestCaffeineEntityCache.java
+++ b/core/src/test/java/org/apache/gravitino/cache/TestCaffeineEntityCache.java
@@ -19,10 +19,12 @@
package org.apache.gravitino.cache;
-import static org.mockito.Mockito.spy;
-
+import com.github.benmanes.caffeine.cache.Cache;
import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.gravitino.Config;
+import org.apache.gravitino.Configs;
import org.apache.gravitino.Entity;
import org.apache.gravitino.NameIdentifier;
import org.apache.gravitino.Namespace;
@@ -48,9 +50,6 @@ import org.junit.jupiter.api.TestInstance;
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class TestCaffeineEntityCache {
- private CaffeineEntityCache real;
- private CaffeineEntityCache cache;
-
private NameIdentifier ident1;
private NameIdentifier ident2;
private NameIdentifier ident3;
@@ -80,6 +79,19 @@ public class TestCaffeineEntityCache {
private RoleEntity entity12;
private RoleEntity entity13;
+ private static Object getCacheDataFrom(EntityCache cache) {
+ try {
+ Object object = FieldUtils.readDeclaredField(cache, "cacheData", true);
+ if (object instanceof Cache) {
+ return object;
+ } else {
+ throw new RuntimeException("Unexpected cache data type: " +
object.getClass());
+ }
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
@BeforeAll
void init() {
initTestNameIdentifier();
@@ -88,8 +100,7 @@ public class TestCaffeineEntityCache {
@Test
void testPutAllTypeInCache() {
-
- initCache();
+ EntityCache cache = new CaffeineEntityCache(new Config() {});
BaseMetalake testMetalake = TestUtil.getTestMetalake();
CatalogEntity testCatalogEntity = TestUtil.getTestCatalogEntity();
@@ -179,9 +190,74 @@ public class TestCaffeineEntityCache {
}
@Test
- void testGetIfPresent() {
+ void testPutSameIdentifierEntities() {
+ EntityCache cache = new CaffeineEntityCache(new Config() {});
+
+ UserEntity testUserEntity = TestUtil.getTestUserEntity();
+ TableEntity testTableEntity =
+ TestUtil.getTestTableEntity(
+ 12L, "test_user", Namespace.of("test_metalake", "system", "user"));
+
+ cache.put(testUserEntity);
+ cache.put(testTableEntity);
+
+ Assertions.assertEquals(2, cache.size());
+ Assertions.assertTrue(
+ cache.contains(testTableEntity.nameIdentifier(),
Entity.EntityType.TABLE));
+ Assertions.assertTrue(cache.contains(testUserEntity.nameIdentifier(),
Entity.EntityType.USER));
+ }
+
+ @Test
+ void testPutAndGet() {
+ EntityCache cache = new CaffeineEntityCache(new Config() {});
+
+ cache.put(entity1);
+ cache.put(entity2);
+ cache.put(entity3);
+ cache.put(entity4);
+ cache.put(entity5);
+ cache.put(entity6);
+ cache.put(entity7);
+ cache.put(entity8);
+ cache.put(entity9);
+ cache.put(entity10);
+ cache.put(entity11);
+
+ cache.put(
+ entity12.nameIdentifier(),
+ Entity.EntityType.ROLE,
+ SupportsRelationOperations.Type.ROLE_USER_REL,
+ ImmutableList.of(entity8, entity9));
+ cache.put(
+ entity13.nameIdentifier(),
+ Entity.EntityType.ROLE,
+ SupportsRelationOperations.Type.ROLE_GROUP_REL,
+ ImmutableList.of(entity10, entity11));
+
+ Assertions.assertTrue(cache.contains(ident1, Entity.EntityType.SCHEMA));
+ Assertions.assertTrue(cache.contains(ident2, Entity.EntityType.SCHEMA));
+ Assertions.assertTrue(cache.contains(ident3, Entity.EntityType.TABLE));
+ Assertions.assertTrue(cache.contains(ident4, Entity.EntityType.TABLE));
+ Assertions.assertTrue(cache.contains(ident5, Entity.EntityType.TABLE));
+ Assertions.assertTrue(cache.contains(ident6, Entity.EntityType.CATALOG));
+ Assertions.assertTrue(cache.contains(ident7, Entity.EntityType.METALAKE));
+
+ Assertions.assertTrue(cache.contains(ident8, Entity.EntityType.USER));
+ Assertions.assertTrue(cache.contains(ident9, Entity.EntityType.USER));
+ Assertions.assertTrue(cache.contains(ident10, Entity.EntityType.GROUP));
+ Assertions.assertTrue(cache.contains(ident11, Entity.EntityType.GROUP));
+
+ Assertions.assertTrue(
+ cache.contains(
+ ident12, Entity.EntityType.ROLE,
SupportsRelationOperations.Type.ROLE_USER_REL));
+ Assertions.assertTrue(
+ cache.contains(
+ ident13, Entity.EntityType.ROLE,
SupportsRelationOperations.Type.ROLE_GROUP_REL));
+ }
- initCache();
+ @Test
+ void testGetIfPresent() {
+ EntityCache cache = new CaffeineEntityCache(new Config() {});
cache.put(entity1);
cache.put(entity2);
@@ -210,8 +286,7 @@ public class TestCaffeineEntityCache {
@Test
void testContains() {
-
- initCache();
+ EntityCache cache = new CaffeineEntityCache(new Config() {});
cache.put(entity1);
cache.put(entity2);
@@ -228,8 +303,7 @@ public class TestCaffeineEntityCache {
@Test
void testSize() {
-
- initCache();
+ EntityCache cache = new CaffeineEntityCache(new Config() {});
cache.put(entity1);
cache.put(entity2);
@@ -240,8 +314,7 @@ public class TestCaffeineEntityCache {
@Test
void testClear() {
-
- initCache();
+ EntityCache cache = new CaffeineEntityCache(new Config() {});
cache.put(entity1);
cache.put(entity2);
@@ -287,8 +360,7 @@ public class TestCaffeineEntityCache {
@Test
void testInvalidateMetalake() {
-
- initCache();
+ EntityCache cache = new CaffeineEntityCache(new Config() {});
cache.put(entity1);
cache.put(entity2);
@@ -333,15 +405,348 @@ public class TestCaffeineEntityCache {
Assertions.assertFalse(cache.contains(ident7, Entity.EntityType.TABLE));
}
- private void initCache() {
- initCache(new Config() {});
+ @Test
+ void testInvalidateCatalog() {
+ EntityCache cache = new CaffeineEntityCache(new Config() {});
+
+ cache.put(entity1);
+ cache.put(entity2);
+ cache.put(entity3);
+ cache.put(entity4);
+ cache.put(entity5);
+ cache.put(entity6);
+ cache.put(entity7);
+
+ Assertions.assertEquals(7, cache.size());
+ Assertions.assertTrue(cache.contains(ident1, Entity.EntityType.SCHEMA));
+ Assertions.assertTrue(cache.contains(ident2, Entity.EntityType.SCHEMA));
+ Assertions.assertTrue(cache.contains(ident3, Entity.EntityType.TABLE));
+ Assertions.assertTrue(cache.contains(ident4, Entity.EntityType.TABLE));
+ Assertions.assertTrue(cache.contains(ident5, Entity.EntityType.TABLE));
+ Assertions.assertTrue(cache.contains(ident6, Entity.EntityType.CATALOG));
+ Assertions.assertTrue(cache.contains(ident7, Entity.EntityType.METALAKE));
+
+ cache.invalidate(ident6, Entity.EntityType.CATALOG);
+ Assertions.assertEquals(3, cache.size());
+
+ Assertions.assertTrue(cache.getIfPresent(ident7,
Entity.EntityType.METALAKE).isPresent());
+ Assertions.assertTrue(cache.getIfPresent(ident4,
Entity.EntityType.TABLE).isPresent());
+ Assertions.assertTrue(cache.getIfPresent(ident2,
Entity.EntityType.SCHEMA).isPresent());
+
+ Assertions.assertFalse(cache.getIfPresent(ident1,
Entity.EntityType.SCHEMA).isPresent());
+ Assertions.assertFalse(cache.getIfPresent(ident3,
Entity.EntityType.TABLE).isPresent());
+ Assertions.assertFalse(cache.getIfPresent(ident5,
Entity.EntityType.TABLE).isPresent());
+ Assertions.assertFalse(cache.getIfPresent(ident6,
Entity.EntityType.TABLE).isPresent());
+ }
+
+ @Test
+ void testInvalidateSchema() {
+ EntityCache cache = new CaffeineEntityCache(new Config() {});
+
+ cache.put(entity1);
+ cache.put(entity2);
+ cache.put(entity3);
+ cache.put(entity4);
+ cache.put(entity5);
+ cache.put(entity6);
+ cache.put(entity7);
+
+ Assertions.assertEquals(7, cache.size());
+ Assertions.assertTrue(cache.contains(ident1, Entity.EntityType.SCHEMA));
+ Assertions.assertTrue(cache.contains(ident2, Entity.EntityType.SCHEMA));
+ Assertions.assertTrue(cache.contains(ident3, Entity.EntityType.TABLE));
+ Assertions.assertTrue(cache.contains(ident4, Entity.EntityType.TABLE));
+ Assertions.assertTrue(cache.contains(ident5, Entity.EntityType.TABLE));
+ Assertions.assertTrue(cache.contains(ident6, Entity.EntityType.CATALOG));
+ Assertions.assertTrue(cache.contains(ident7, Entity.EntityType.METALAKE));
+
+ cache.invalidate(ident1, Entity.EntityType.SCHEMA);
+
+ Assertions.assertEquals(5, cache.size());
+
+ Assertions.assertTrue(cache.getIfPresent(ident2,
Entity.EntityType.SCHEMA).isPresent());
+ Assertions.assertTrue(cache.getIfPresent(ident4,
Entity.EntityType.TABLE).isPresent());
+ Assertions.assertTrue(cache.getIfPresent(ident5,
Entity.EntityType.TABLE).isPresent());
+ Assertions.assertTrue(cache.getIfPresent(ident6,
Entity.EntityType.CATALOG).isPresent());
+ Assertions.assertTrue(cache.getIfPresent(ident7,
Entity.EntityType.METALAKE).isPresent());
+
+ Assertions.assertFalse(cache.getIfPresent(ident1,
Entity.EntityType.SCHEMA).isPresent());
+ Assertions.assertFalse(cache.getIfPresent(ident3,
Entity.EntityType.TABLE).isPresent());
+ }
+
+ @Test
+ void testInvalidateTable() {
+ EntityCache cache = new CaffeineEntityCache(new Config() {});
+
+ cache.put(entity1);
+ cache.put(entity2);
+ cache.put(entity3);
+ cache.put(entity4);
+ cache.put(entity5);
+ cache.put(entity6);
+ cache.put(entity7);
+
+ Assertions.assertEquals(7, cache.size());
+ Assertions.assertTrue(cache.contains(ident1, Entity.EntityType.SCHEMA));
+ Assertions.assertTrue(cache.contains(ident2, Entity.EntityType.SCHEMA));
+ Assertions.assertTrue(cache.contains(ident3, Entity.EntityType.TABLE));
+ Assertions.assertTrue(cache.contains(ident4, Entity.EntityType.TABLE));
+ Assertions.assertTrue(cache.contains(ident5, Entity.EntityType.TABLE));
+ Assertions.assertTrue(cache.contains(ident6, Entity.EntityType.CATALOG));
+ Assertions.assertTrue(cache.contains(ident7, Entity.EntityType.METALAKE));
+
+ cache.invalidate(ident3, Entity.EntityType.TABLE);
+
+ Assertions.assertEquals(6, cache.size());
+ Assertions.assertTrue(cache.getIfPresent(ident1,
Entity.EntityType.SCHEMA).isPresent());
+ Assertions.assertTrue(cache.getIfPresent(ident2,
Entity.EntityType.SCHEMA).isPresent());
+ Assertions.assertTrue(cache.getIfPresent(ident4,
Entity.EntityType.TABLE).isPresent());
+ Assertions.assertTrue(cache.getIfPresent(ident5,
Entity.EntityType.TABLE).isPresent());
+ Assertions.assertTrue(cache.getIfPresent(ident6,
Entity.EntityType.CATALOG).isPresent());
+ Assertions.assertTrue(cache.getIfPresent(ident7,
Entity.EntityType.METALAKE).isPresent());
+
+ Assertions.assertFalse(cache.contains(ident3, Entity.EntityType.TABLE));
+ }
+
+ @Test
+ void testRemoveNonExistentEntity() {
+ EntityCache cache = new CaffeineEntityCache(new Config() {});
+
+ cache.put(entity1);
+
+ Assertions.assertEquals(1, cache.size());
+ Assertions.assertTrue(cache.contains(ident1, Entity.EntityType.SCHEMA));
+
+ Assertions.assertDoesNotThrow(() -> cache.invalidate(ident2,
Entity.EntityType.SCHEMA));
+ Assertions.assertFalse(cache.invalidate(ident2, Entity.EntityType.SCHEMA));
+
+ Assertions.assertDoesNotThrow(() -> cache.invalidate(ident7,
Entity.EntityType.METALAKE));
+ Assertions.assertFalse(cache.invalidate(ident7,
Entity.EntityType.METALAKE));
+ }
+
+ @Test
+ void testExpireByTime() throws InterruptedException {
+ int waitTime = 3_000;
+ long expireTime = 1_000L;
+
+ Config config = new Config() {};
+ config.set(Configs.CACHE_EXPIRATION_TIME, expireTime);
+ config.set(Configs.CACHE_WEIGHER_ENABLED, false);
+ EntityCache cache = new CaffeineEntityCache(config);
+
+ cache.put(entity1);
+ Thread.sleep(waitTime);
+ cache.put(entity2);
+
+ Cache<EntityCacheKey, List<Entity>> caffeineObject =
+ (Cache<EntityCacheKey, List<Entity>>) getCacheDataFrom(cache);
+ caffeineObject.cleanUp();
+
+ Assertions.assertEquals(1, cache.size());
+ Assertions.assertFalse(cache.contains(entity1.nameIdentifier(),
Entity.EntityType.SCHEMA));
+ Assertions.assertTrue(cache.contains(entity2.nameIdentifier(),
Entity.EntityType.SCHEMA));
+ }
+
+ @Test
+ void testExpireByWeightExceedMaxWeight() {
+ Config config = new Config() {};
+ long oldMaxWeight = EntityCacheWeigher.MAX_WEIGHT;
+ EntityCacheWeigher.MAX_WEIGHT = 75;
+ config.set(Configs.CACHE_WEIGHER_ENABLED, true);
+ EntityCache cache = new CaffeineEntityCache(config);
+
+ cache.put(entity7);
+ Cache<EntityCacheKey, List<Entity>> caffeineObject =
+ (Cache<EntityCacheKey, List<Entity>>) getCacheDataFrom(cache);
+ caffeineObject.cleanUp();
+
+ Assertions.assertEquals(0, cache.size());
+ Assertions.assertFalse(cache.contains(entity7.nameIdentifier(),
Entity.EntityType.METALAKE));
+
+ EntityCacheWeigher.MAX_WEIGHT = oldMaxWeight;
}
- // TODO Add other tests for cache
+ @Test
+ void testExpireByWeight() {
+ Config config = new Config() {};
+ long maxWeight = EntityCacheWeigher.MAX_WEIGHT;
+ EntityCacheWeigher.MAX_WEIGHT = 100;
+ config.set(Configs.CACHE_WEIGHER_ENABLED, true);
+ EntityCache cache = new CaffeineEntityCache(config);
+
+ cache.put(entity7);
+ Assertions.assertEquals(1, cache.size());
+ Assertions.assertTrue(cache.contains(entity7.nameIdentifier(),
Entity.EntityType.METALAKE));
+
+ cache.put(entity1);
+ cache.put(entity2);
+ Cache<EntityCacheKey, List<Entity>> caffeineObject =
+ (Cache<EntityCacheKey, List<Entity>>) getCacheDataFrom(cache);
+ caffeineObject.cleanUp();
+
+ Assertions.assertEquals(2, cache.size());
+ Assertions.assertTrue(cache.contains(entity1.nameIdentifier(),
Entity.EntityType.SCHEMA));
+ Assertions.assertTrue(cache.contains(entity2.nameIdentifier(),
Entity.EntityType.SCHEMA));
- private void initCache(Config config) {
- real = new CaffeineEntityCache(config);
- cache = spy(real);
+ EntityCacheWeigher.MAX_WEIGHT = maxWeight;
+ }
+
+ @Test
+ void testExpireBySize() {
+ Config config = new Config() {};
+ config.set(Configs.CACHE_WEIGHER_ENABLED, false);
+ config.set(Configs.CACHE_MAX_ENTRIES, 1);
+ EntityCache cache = new CaffeineEntityCache(config);
+
+ Cache<EntityCacheKey, List<Entity>> caffeineObject =
+ (Cache<EntityCacheKey, List<Entity>>) getCacheDataFrom(cache);
+
+ cache.put(entity1);
+ caffeineObject.cleanUp();
+ Assertions.assertEquals(1, cache.size());
+ Assertions.assertTrue(cache.contains(entity1.nameIdentifier(),
Entity.EntityType.SCHEMA));
+
+ cache.put(entity2);
+ caffeineObject.cleanUp();
+ Assertions.assertEquals(1, cache.size());
+ Assertions.assertTrue(cache.contains(entity2.nameIdentifier(),
Entity.EntityType.SCHEMA));
+
+ cache.put(entity3);
+ caffeineObject.cleanUp();
+ Assertions.assertEquals(1, cache.size());
+ Assertions.assertTrue(cache.contains(entity3.nameIdentifier(),
Entity.EntityType.TABLE));
+ }
+
+ @Test
+ void testWeightCalculation() {
+ int metalakeWeight =
+ EntityCacheWeigher.getInstance()
+ .weigh(
+ EntityCacheKey.of(ident7, Entity.EntityType.METALAKE),
ImmutableList.of(entity7));
+ Assertions.assertEquals(100, metalakeWeight);
+
+ int catalogWeight =
+ EntityCacheWeigher.getInstance()
+ .weigh(EntityCacheKey.of(ident6, Entity.EntityType.CATALOG),
ImmutableList.of(entity6));
+ Assertions.assertEquals(75, catalogWeight);
+
+ int schemaWeight =
+ EntityCacheWeigher.getInstance()
+ .weigh(EntityCacheKey.of(ident1, Entity.EntityType.SCHEMA),
ImmutableList.of(entity1));
+ Assertions.assertEquals(50, schemaWeight);
+
+ int tableWeight =
+ EntityCacheWeigher.getInstance()
+ .weigh(EntityCacheKey.of(ident3, Entity.EntityType.TABLE),
ImmutableList.of(entity3));
+ Assertions.assertEquals(15, tableWeight);
+
+ int multiUserWeight =
+ EntityCacheWeigher.getInstance()
+ .weigh(
+ EntityCacheKey.of(
+ ident12, Entity.EntityType.ROLE,
SupportsRelationOperations.Type.ROLE_USER_REL),
+ ImmutableList.of(entity8, entity9));
+
+ Assertions.assertEquals(30, multiUserWeight);
+ }
+
+ @Test
+ void testGetIfPresentWithNull() {
+ EntityCache cache = new CaffeineEntityCache(new Config() {});
+ cache.put(entity1);
+
+ Assertions.assertThrows(
+ IllegalArgumentException.class, () -> cache.getIfPresent(null,
Entity.EntityType.SCHEMA));
+ Assertions.assertThrows(IllegalArgumentException.class, () ->
cache.getIfPresent(ident1, null));
+
+ Assertions.assertThrows(
+ IllegalArgumentException.class,
+ () -> cache.getIfPresent(null, ident12, Entity.EntityType.ROLE));
+ Assertions.assertThrows(
+ IllegalArgumentException.class,
+ () ->
+ cache.getIfPresent(
+ SupportsRelationOperations.Type.ROLE_USER_REL, null,
Entity.EntityType.ROLE));
+ Assertions.assertThrows(
+ IllegalArgumentException.class,
+ () ->
cache.getIfPresent(SupportsRelationOperations.Type.ROLE_USER_REL, ident12,
null));
+ Assertions.assertThrows(
+ IllegalArgumentException.class,
+ () ->
cache.getIfPresent(SupportsRelationOperations.Type.ROLE_USER_REL, ident12,
null));
+ }
+
+ @Test
+ void testContainsWithNull() {
+ EntityCache cache = new CaffeineEntityCache(new Config() {});
+
+ Assertions.assertThrows(
+ IllegalArgumentException.class, () -> cache.contains(null,
Entity.EntityType.SCHEMA));
+ Assertions.assertThrows(IllegalArgumentException.class, () ->
cache.contains(ident7, null));
+
+ Assertions.assertThrows(
+ IllegalArgumentException.class,
+ () ->
+ cache.contains(
+ null, Entity.EntityType.ROLE,
SupportsRelationOperations.Type.ROLE_USER_REL));
+ Assertions.assertThrows(
+ IllegalArgumentException.class,
+ () -> cache.contains(ident12, null,
SupportsRelationOperations.Type.ROLE_USER_REL));
+ Assertions.assertThrows(
+ IllegalArgumentException.class,
+ () -> cache.contains(ident12, Entity.EntityType.ROLE, null));
+ }
+
+ @Test
+ void testInvalidateWithNull() {
+ EntityCache cache = new CaffeineEntityCache(new Config() {});
+
+ Assertions.assertThrows(
+ IllegalArgumentException.class, () -> cache.invalidate(null,
Entity.EntityType.CATALOG));
+ Assertions.assertThrows(IllegalArgumentException.class, () ->
cache.invalidate(ident7, null));
+
+ Assertions.assertThrows(
+ IllegalArgumentException.class,
+ () ->
+ cache.invalidate(
+ null, Entity.EntityType.ROLE,
SupportsRelationOperations.Type.ROLE_USER_REL));
+ Assertions.assertThrows(
+ IllegalArgumentException.class,
+ () -> cache.invalidate(ident12, null,
SupportsRelationOperations.Type.ROLE_USER_REL));
+ Assertions.assertThrows(
+ IllegalArgumentException.class,
+ () -> cache.invalidate(ident12, Entity.EntityType.ROLE, null));
+ }
+
+ @Test
+ void testPutWithNull() {
+ EntityCache cache = new CaffeineEntityCache(new Config() {});
+
+ Assertions.assertThrows(IllegalArgumentException.class, () ->
cache.put(null));
+
+ Assertions.assertThrows(
+ IllegalArgumentException.class,
+ () ->
+ cache.put(
+ null,
+ Entity.EntityType.ROLE,
+ SupportsRelationOperations.Type.ROLE_USER_REL,
+ ImmutableList.of()));
+ Assertions.assertThrows(
+ IllegalArgumentException.class,
+ () ->
+ cache.put(
+ ident12, null, SupportsRelationOperations.Type.ROLE_USER_REL,
ImmutableList.of()));
+ Assertions.assertThrows(
+ IllegalArgumentException.class,
+ () -> cache.put(ident12, Entity.EntityType.ROLE, null,
ImmutableList.of()));
+ Assertions.assertThrows(
+ IllegalArgumentException.class,
+ () ->
+ cache.put(
+ ident12,
+ Entity.EntityType.ROLE,
+ SupportsRelationOperations.Type.ROLE_USER_REL,
+ null));
}
private void initTestNameIdentifier() {
@@ -361,9 +766,6 @@ public class TestCaffeineEntityCache {
ident12 = NameIdentifierUtil.ofRole("metalake1", "role1");
ident13 = NameIdentifierUtil.ofRole("metalake2", "role2");
-
- // TODO remove next PR
- System.out.println(ident8 + " " + ident9);
}
private void initTestEntities() {
diff --git
a/core/src/test/java/org/apache/gravitino/storage/TestEntityStorage.java
b/core/src/test/java/org/apache/gravitino/storage/TestEntityStorage.java
index 686c61a323..69914c91ed 100644
--- a/core/src/test/java/org/apache/gravitino/storage/TestEntityStorage.java
+++ b/core/src/test/java/org/apache/gravitino/storage/TestEntityStorage.java
@@ -146,6 +146,7 @@ public class TestEntityStorage {
Mockito.when(config.get(Configs.CACHE_EXPIRATION_TIME)).thenReturn(3_600_000L);
Mockito.when(config.get(Configs.CACHE_WEIGHER_ENABLED)).thenReturn(true);
Mockito.when(config.get(Configs.CACHE_STATS_ENABLED)).thenReturn(false);
+
Mockito.when(config.get(Configs.CACHE_IMPLEMENTATION)).thenReturn("caffeine");
BaseIT baseIT = new BaseIT();
diff --git a/core/src/test/java/org/apache/gravitino/tag/TestTagManager.java
b/core/src/test/java/org/apache/gravitino/tag/TestTagManager.java
index 3506e1755e..5a7fc87d32 100644
--- a/core/src/test/java/org/apache/gravitino/tag/TestTagManager.java
+++ b/core/src/test/java/org/apache/gravitino/tag/TestTagManager.java
@@ -138,6 +138,7 @@ public class TestTagManager {
Mockito.when(config.get(Configs.CACHE_EXPIRATION_TIME)).thenReturn(3_600_000L);
Mockito.when(config.get(Configs.CACHE_WEIGHER_ENABLED)).thenReturn(true);
Mockito.when(config.get(Configs.CACHE_STATS_ENABLED)).thenReturn(false);
+
Mockito.when(config.get(Configs.CACHE_IMPLEMENTATION)).thenReturn("caffeine");
Mockito.doReturn(100000L).when(config).get(TREE_LOCK_MAX_NODE_IN_MEMORY);
Mockito.doReturn(1000L).when(config).get(TREE_LOCK_MIN_NODE_IN_MEMORY);