Disable cache store and load only if a remote store is used

Closes #10803
Closes #24766

Signed-off-by: Alexander Schwartz <aschwart@redhat.com>
Co-authored-by: daviddelannoy <16318239+daviddelannoy@users.noreply.github.com>
This commit is contained in:
Alexander Schwartz 2023-11-15 15:40:28 +01:00 committed by Alexander Schwartz
parent 62d5eb0965
commit a45934a762
4 changed files with 33 additions and 18 deletions

View file

@ -21,6 +21,8 @@ import org.infinispan.AdvancedCache;
import org.infinispan.Cache;
import org.infinispan.context.Flag;
import static org.keycloak.connections.infinispan.InfinispanUtil.getRemoteStores;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@ -40,8 +42,15 @@ public class CacheDecorators {
* @param cache
* @return Cache with the flags applied.
*/
public static <K, V> AdvancedCache<K, V> skipCacheLoaders(Cache<K, V> cache) {
return cache.getAdvancedCache().withFlags(Flag.SKIP_CACHE_LOAD, Flag.SKIP_CACHE_STORE);
public static <K, V> AdvancedCache<K, V> skipCacheLoadersIfRemoteStoreIsEnabled(Cache<K, V> cache) {
if (!getRemoteStores(cache).isEmpty()) {
// Disabling of the cache load and cache store is only needed when a remote store is used and handled separately.
return cache.getAdvancedCache().withFlags(Flag.SKIP_CACHE_LOAD, Flag.SKIP_CACHE_STORE);
} else {
// If there is no remote store, use write through for all stores of the cache.
// Mixing remote and non-remote caches is not supported.
return cache.getAdvancedCache().withFlags(Flag.SKIP_CACHE_LOAD);
}
}
/**
@ -49,8 +58,15 @@ public class CacheDecorators {
* @param cache
* @return Cache with the flags applied.
*/
public static <K, V> AdvancedCache<K, V> skipCacheStore(Cache<K, V> cache) {
return cache.getAdvancedCache().withFlags(Flag.SKIP_CACHE_STORE);
public static <K, V> AdvancedCache<K, V> skipCacheStoreIfRemoteCacheIsEnabled(Cache<K, V> cache) {
if (!getRemoteStores(cache).isEmpty()) {
// Disabling of the cache load and cache store is only needed when a remote store is used and handled separately.
return cache.getAdvancedCache().withFlags(Flag.SKIP_CACHE_STORE);
} else {
// If there is no remote store, use write through for all stores of the cache.
// Mixing remote and non-remote caches is not supported.
return cache.getAdvancedCache();
}
}
}

View file

@ -118,7 +118,7 @@ public class InfinispanUserLoginFailureProvider implements UserLoginFailureProvi
Cache<LoginFailureKey, SessionEntityWrapper<LoginFailureEntity>> localCache = CacheDecorators.localCache(loginFailureCache);
Cache<LoginFailureKey, SessionEntityWrapper<LoginFailureEntity>> localCacheStoreIgnore = CacheDecorators.skipCacheLoaders(localCache);
Cache<LoginFailureKey, SessionEntityWrapper<LoginFailureEntity>> localCacheStoreIgnore = CacheDecorators.skipCacheLoadersIfRemoteStoreIsEnabled(localCache);
localCacheStoreIgnore
.entrySet()

View file

@ -394,7 +394,7 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
}
Cache<String, SessionEntityWrapper<UserSessionEntity>> cache = getCache(offline);
cache = CacheDecorators.skipCacheLoaders(cache);
cache = CacheDecorators.skipCacheLoadersIfRemoteStoreIsEnabled(cache);
// return a stream that 'wraps' the infinispan cache stream so that the cache stream's elements are read one by one
// and then mapped locally to avoid serialization issues when trying to manipulate the cache stream directly.
@ -564,7 +564,7 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
}
Cache<String, SessionEntityWrapper<UserSessionEntity>> cache = getCache(offline);
cache = CacheDecorators.skipCacheLoaders(cache);
cache = CacheDecorators.skipCacheLoadersIfRemoteStoreIsEnabled(cache);
return cache.entrySet().stream()
.filter(UserSessionPredicate.create(realm.getId()))
.map(Mappers.authClientSessionSetMapper())
@ -603,7 +603,7 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
protected void removeUserSessions(RealmModel realm, UserModel user, boolean offline) {
Cache<String, SessionEntityWrapper<UserSessionEntity>> cache = getCache(offline);
cache = CacheDecorators.skipCacheLoaders(cache);
cache = CacheDecorators.skipCacheLoadersIfRemoteStoreIsEnabled(cache);
Iterator<UserSessionEntity> itr = cache.entrySet().stream().filter(UserSessionPredicate.create(realm.getId()).user(user.getId())).map(Mappers.userSessionEntity()).iterator();
@ -647,7 +647,7 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
Cache<UUID, SessionEntityWrapper<AuthenticatedClientSessionEntity>> clientSessionCache = getClientSessionCache(offline);
Cache<UUID, SessionEntityWrapper<AuthenticatedClientSessionEntity>> localClientSessionCache = CacheDecorators.localCache(clientSessionCache);
Cache<String, SessionEntityWrapper<UserSessionEntity>> localCacheStoreIgnore = CacheDecorators.skipCacheLoaders(localCache);
Cache<String, SessionEntityWrapper<UserSessionEntity>> localCacheStoreIgnore = CacheDecorators.skipCacheLoadersIfRemoteStoreIsEnabled(localCache);
final AtomicInteger userSessionsSize = new AtomicInteger();
@ -906,7 +906,7 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
.collect(Collectors.toMap(sessionEntityWrapper -> sessionEntityWrapper.getEntity().getId(), Function.identity()));
// Directly put all entities to the infinispan cache
Cache<String, SessionEntityWrapper<UserSessionEntity>> cache = CacheDecorators.skipCacheLoaders(getCache(offline));
Cache<String, SessionEntityWrapper<UserSessionEntity>> cache = CacheDecorators.skipCacheLoadersIfRemoteStoreIsEnabled(getCache(offline));
boolean importWithExpiration = sessionsById.size() == 1;
if (importWithExpiration) {
@ -951,7 +951,7 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
// Import client sessions
Cache<UUID, SessionEntityWrapper<AuthenticatedClientSessionEntity>> clientSessCache =
CacheDecorators.skipCacheLoaders(offline ? offlineClientSessionCache : clientSessionCache);
CacheDecorators.skipCacheLoadersIfRemoteStoreIsEnabled(offline ? offlineClientSessionCache : clientSessionCache);
if (importWithExpiration) {
importSessionsWithExpiration(clientSessionsById, clientSessCache,

View file

@ -24,7 +24,6 @@ import java.util.concurrent.TimeUnit;
import org.infinispan.Cache;
import org.infinispan.context.Flag;
import org.jboss.logging.Logger;
import org.keycloak.models.ClientModel;
import org.keycloak.models.AbstractKeycloakTransaction;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
@ -189,19 +188,19 @@ public class InfinispanChangelogBasedTransaction<K, V extends SessionEntity> ext
switch (operation) {
case REMOVE:
// Just remove it
CacheDecorators.skipCacheStore(cache)
.getAdvancedCache().withFlags(Flag.IGNORE_RETURN_VALUES)
CacheDecorators.skipCacheStoreIfRemoteCacheIsEnabled(cache)
.withFlags(Flag.IGNORE_RETURN_VALUES)
.remove(key);
break;
case ADD:
CacheDecorators.skipCacheStore(cache)
.getAdvancedCache().withFlags(Flag.IGNORE_RETURN_VALUES)
CacheDecorators.skipCacheStoreIfRemoteCacheIsEnabled(cache)
.withFlags(Flag.IGNORE_RETURN_VALUES)
.put(key, sessionWrapper, task.getLifespanMs(), TimeUnit.MILLISECONDS, task.getMaxIdleTimeMs(), TimeUnit.MILLISECONDS);
logger.tracef("Added entity '%s' to the cache '%s' . Lifespan: %d ms, MaxIdle: %d ms", key, cache.getName(), task.getLifespanMs(), task.getMaxIdleTimeMs());
break;
case ADD_IF_ABSENT:
SessionEntityWrapper<V> existing = CacheDecorators.skipCacheStore(cache).putIfAbsent(key, sessionWrapper, task.getLifespanMs(), TimeUnit.MILLISECONDS, task.getMaxIdleTimeMs(), TimeUnit.MILLISECONDS);
SessionEntityWrapper<V> existing = CacheDecorators.skipCacheStoreIfRemoteCacheIsEnabled(cache).putIfAbsent(key, sessionWrapper, task.getLifespanMs(), TimeUnit.MILLISECONDS, task.getMaxIdleTimeMs(), TimeUnit.MILLISECONDS);
if (existing != null) {
logger.debugf("Existing entity in cache for key: %s . Will update it", key);
@ -234,7 +233,7 @@ public class InfinispanChangelogBasedTransaction<K, V extends SessionEntity> ext
SessionEntityWrapper<V> newVersionEntity = generateNewVersionAndWrapEntity(session, oldVersionEntity.getLocalMetadata());
// Atomic cluster-aware replace
replaced = CacheDecorators.skipCacheStore(cache).replace(key, oldVersionEntity, newVersionEntity, lifespanMs, TimeUnit.MILLISECONDS, maxIdleTimeMs, TimeUnit.MILLISECONDS);
replaced = CacheDecorators.skipCacheStoreIfRemoteCacheIsEnabled(cache).replace(key, oldVersionEntity, newVersionEntity, lifespanMs, TimeUnit.MILLISECONDS, maxIdleTimeMs, TimeUnit.MILLISECONDS);
// Replace fail. Need to load latest entity from cache, apply updates again and try to replace in cache again
if (!replaced) {