yuqi1129 commented on code in PR #13374:
URL: https://github.com/apache/gravitino/pull/13374#discussion_r4069698912


##########
core/src/main/java/org/apache/gravitino/storage/relational/RelationalEntityStore.java:
##########
@@ -223,9 +251,21 @@ public <E extends Entity & HasIdentifier> List<E> batchGet(
                   return entity.isEmpty();
                 })
             .toList();
+    // Unlike get(), the backend read is not done under the entries' cache 
locks: holding one lock
+    // per key across a batch DB round trip would stall unrelated reads on the 
same segments. So an
+    // invalidation can land between the read and the write-back. The epoch 
sampled here detects
+    // that and skips the write-back, otherwise the stale copy would survive 
until the TTL. The
+    // per-key lock makes the check and the put atomic against an invalidation 
of the same key.
+    long epochBeforeRead = cacheInvalidationEpoch.get();
     List<E> fetchEntities = backend.batchGet(noCacheIdents, entityType);
     for (E entity : fetchEntities) {
-      cache.put(entity);
+      cache.withCacheLock(
+          EntityCacheKey.of(entity.nameIdentifier(), entity.type()),
+          () -> {
+            if (cacheInvalidationEpoch.get() == epochBeforeRead) {
+              cache.put(entity);
+            }
+          });

Review Comment:
   Addressed in bf77580044. For BaseEntityCache, batchGet now skips the per-key 
lock when the entity type cannot be cached. It still calls cache.put, because 
that method runs invalidateOnKeyChange even for non-cacheable entities. The new 
ROLE test checks both that no key lock is taken and that the hook still runs.



##########
core/src/main/java/org/apache/gravitino/storage/relational/RelationalEntityStore.java:
##########
@@ -223,9 +251,21 @@ public <E extends Entity & HasIdentifier> List<E> batchGet(
                   return entity.isEmpty();
                 })
             .toList();
+    // Unlike get(), the backend read is not done under the entries' cache 
locks: holding one lock
+    // per key across a batch DB round trip would stall unrelated reads on the 
same segments. So an
+    // invalidation can land between the read and the write-back. The epoch 
sampled here detects
+    // that and skips the write-back, otherwise the stale copy would survive 
until the TTL. The
+    // per-key lock makes the check and the put atomic against an invalidation 
of the same key.

Review Comment:
   You are right: withGlobalLock does not wait for a key lock already held by 
batchGet. Addressed in bf77580044 by checking the epoch again after cache.put 
and invalidating the just-written key if an invalidation or clear happened 
during the put. A deterministic test triggers clear from inside the put, after 
the first epoch check, and verifies the stale value is absent afterward.



##########
core/src/main/java/org/apache/gravitino/storage/relational/RelationalEntityStore.java:
##########
@@ -75,6 +76,11 @@ public class RelationalEntityStore
   private EntityChangeLogCleaner entityChangeLogCleaner;
   private EntityCache cache;
 
+  // Advanced before every cache invalidation and clear, whether local or 
replayed from the change
+  // log, so that batchGet() can tell that an invalidation happened while its 
backend read was in
+  // flight. Every invalidation must go through invalidateCache() / 
clearCache() for this to hold.
+  private final AtomicLong cacheInvalidationEpoch = new AtomicLong();

Review Comment:
   Addressed in bf77580044. The field comment now states that this 
process-local counter covers only invalidations observed by this store. A 
future SHARED cache without a local change-log listener must provide its own 
distributed version check; the current counter cannot detect changes made by 
another node.



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