-
Notifications
You must be signed in to change notification settings - Fork 3.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Handle map representation of cache in SafeCaches #14732
Handle map representation of cache in SafeCaches #14732
Conversation
@kokosing the CI is unhappy |
lib/trino-collect/src/test/java/io/trino/collect/cache/TestSafeCaches.java
Outdated
Show resolved
Hide resolved
lib/trino-collect/src/test/java/io/trino/collect/cache/TestSafeCaches.java
Outdated
Show resolved
Hide resolved
lib/trino-collect/src/test/java/io/trino/collect/cache/TestSafeCaches.java
Outdated
Show resolved
Hide resolved
cache.invalidateAll(); | ||
cache.asMap().clear(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add assertion that cache gets emptied by each of these
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so. SafeCaches provides forwarding implementation of cache, so it is up to a delegate cache to clear things. So testing if methods are properly implemented should be on a different level, where a delegate cache implementation is.
I would like to implement this anyway, but the challenge is that it is not clear how to put/load data into the cache. Without it I cannot verify if clear clears.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So testing if methods are properly implemented should be on a different level
we don't have tests for SafeCaches's wrappers, which was a mistake. You're adding them now.
where a delegate cache implementation is.
We could want a "smoke test" to verify things generally work. I.e. what if SafeCaches wrapper missed a call to delegate?
Other than that, I agree there is no point in fine grained tests, we don't want to test underlying implementation here, nor concurrency, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but the challenge is that it is not clear how to put/load data into the cache.
maybe we can have something like
private static void verifyClearIsPossible(Cache<Object, Object> cache)
throws Exception
{
Object key = new Object();
Object firstValue = new Object();
cache.get(key, () -> firstValue);
assertSame(cache.getIfPresent(key), firstValue);
cache.invalidateAll();
assertNull(cache.getIfPresent(key));
Object secondValue = new Object();
cache.get(key, () -> secondValue);
assertSame(cache.getIfPresent(key), secondValue);
cache.asMap().clear();
assertNull(cache.getIfPresent(key));
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your example assumes that loading is possible which is no always a case.
Anyway I follow you suggestion, and I will change it later if needed (NonLoadableCache, however it is a different story)
} | ||
|
||
@Override | ||
public boolean replace(K key, V oldValue, V newValue) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one may actually be safe? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we forbid without being sure, we will appear as if being sure.
I am fine with forbidding this, but let's have a comment that we don't know what we're doing.
lib/trino-collect/src/test/java/io/trino/collect/cache/TestSafeCaches.java
Outdated
Show resolved
Hide resolved
lib/trino-collect/src/test/java/io/trino/collect/cache/TestSafeCaches.java
Outdated
Show resolved
Hide resolved
bfcc204
to
b4a6ee9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AC
Please see Expose NonKeyEvictableLoadingCache::unsafeInvalidate
which I had to add as there was actually map used to by bypass forbidden invalidation.
cache.invalidateAll(); | ||
cache.asMap().clear(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so. SafeCaches provides forwarding implementation of cache, so it is up to a delegate cache to clear things. So testing if methods are properly implemented should be on a different level, where a delegate cache implementation is.
I would like to implement this anyway, but the challenge is that it is not clear how to put/load data into the cache. Without it I cannot verify if clear clears.
} | ||
|
||
@Override | ||
public boolean replace(K key, V oldValue, V newValue) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure.
lib/trino-collect/src/main/java/io/trino/collect/cache/NonKeyEvictableLoadingCache.java
Outdated
Show resolved
Hide resolved
lib/trino-collect/src/main/java/io/trino/collect/cache/NonEvictableLoadingCacheImpl.java
Show resolved
Hide resolved
} | ||
|
||
private static void verifyClearIsImpossible(Cache<Object, Object> cache) | ||
{ | ||
assertThatThrownBy(cache::invalidateAll) | ||
.isInstanceOf(UnsupportedOperationException.class) | ||
.hasMessage("invalidateAll does not invalidate ongoing loads, so a stale value may remain in the cache for ever. Use EvictableCache if you need invalidation, or use SafeCaches.buildNonEvictableCacheWithWeakInvalidateAll() if invalidateAll is not required for correctness"); | ||
// TODO test asMap().clear() | ||
Map<Object, Object> map = cache.asMap(); | ||
assertThatThrownBy(map::clear).isInstanceOf(UnsupportedOperationException.class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assert on the message
That method allows invalidation for a key where it is known that there are no ongoing loads for it.
Also makes error messages to be consistent
b4a6ee9
to
fa11f90
Compare
Handle map representation of cache in SafeCaches