Move organization membership cache entries to the user cache
Closes #33412 Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com>
This commit is contained in:
parent
2be2b2ffe5
commit
13111daceb
6 changed files with 38 additions and 18 deletions
|
@ -226,4 +226,7 @@ public abstract class CacheManager {
|
||||||
|
|
||||||
protected abstract void addInvalidationsFromEvent(InvalidationEvent event, Set<String> invalidations);
|
protected abstract void addInvalidationsFromEvent(InvalidationEvent event, Set<String> invalidations);
|
||||||
|
|
||||||
|
public void invalidateCacheKey(String key, Set<String> invalidations) {
|
||||||
|
invalidations.add(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,10 +120,6 @@ public class RealmCacheManager extends CacheManager {
|
||||||
addInvalidations(InClientPredicate.create().client(clientUUID), invalidations);
|
addInvalidations(InClientPredicate.create().client(clientUUID), invalidations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void invalidateCacheKey(String key, Set<String> invalidations) {
|
|
||||||
invalidations.add(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void addInvalidationsFromEvent(InvalidationEvent event, Set<String> invalidations) {
|
protected void addInvalidationsFromEvent(InvalidationEvent event, Set<String> invalidations) {
|
||||||
invalidations.add(event.getId());
|
invalidations.add(event.getId());
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
|
|
||||||
package org.keycloak.models.cache.infinispan;
|
package org.keycloak.models.cache.infinispan;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
@ -221,8 +220,8 @@ public class RealmCacheSession implements CacheRealmProvider {
|
||||||
return groupDelegate;
|
return groupDelegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<String> getInvalidations() {
|
public boolean isInvalid(String key) {
|
||||||
return Collections.unmodifiableSet(invalidations);
|
return invalidations.contains(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RealmCacheManager getCache() {
|
public RealmCacheManager getCache() {
|
||||||
|
|
|
@ -24,6 +24,7 @@ import org.keycloak.credential.CredentialInput;
|
||||||
import org.keycloak.models.ClientScopeModel;
|
import org.keycloak.models.ClientScopeModel;
|
||||||
import org.keycloak.models.CredentialValidationOutput;
|
import org.keycloak.models.CredentialValidationOutput;
|
||||||
import org.keycloak.models.IdentityProviderModel;
|
import org.keycloak.models.IdentityProviderModel;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.CacheKeyInvalidatedEvent;
|
||||||
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
||||||
import org.keycloak.common.constants.ServiceAccountConstants;
|
import org.keycloak.common.constants.ServiceAccountConstants;
|
||||||
import org.keycloak.component.ComponentModel;
|
import org.keycloak.component.ComponentModel;
|
||||||
|
@ -996,4 +997,21 @@ public class UserCacheSession implements UserCache, OnCreateComponent, OnUpdateC
|
||||||
.anyMatch((org) -> (organizationProvider.isEnabled() && org.isManaged(delegate) && !org.isEnabled()) ||
|
.anyMatch((org) -> (organizationProvider.isEnabled() && org.isManaged(delegate) && !org.isEnabled()) ||
|
||||||
(!organizationProvider.isEnabled() && org.isManaged(delegate)));
|
(!organizationProvider.isEnabled() && org.isManaged(delegate)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UserCacheManager getCache() {
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getStartupRevision() {
|
||||||
|
return startupRevision;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerInvalidation(String id) {
|
||||||
|
cache.invalidateCacheKey(id, invalidations);
|
||||||
|
invalidationEvents.add(new CacheKeyInvalidatedEvent(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInvalid(String key) {
|
||||||
|
return invalidations.contains(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -426,7 +426,7 @@ public class InfinispanIdentityProviderStorageProvider implements IdentityProvid
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isInvalid(String cacheKey) {
|
private boolean isInvalid(String cacheKey) {
|
||||||
return realmCache.getInvalidations().contains(cacheKey);
|
return realmCache.isInvalid(cacheKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IdentityProviderModel createOrganizationAwareIdentityProviderModel(IdentityProviderModel idp) {
|
private IdentityProviderModel createOrganizationAwareIdentityProviderModel(IdentityProviderModel idp) {
|
||||||
|
|
|
@ -26,8 +26,10 @@ import org.keycloak.models.OrganizationModel;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.cache.CacheRealmProvider;
|
import org.keycloak.models.cache.CacheRealmProvider;
|
||||||
|
import org.keycloak.models.cache.UserCache;
|
||||||
import org.keycloak.models.cache.infinispan.CachedCount;
|
import org.keycloak.models.cache.infinispan.CachedCount;
|
||||||
import org.keycloak.models.cache.infinispan.RealmCacheSession;
|
import org.keycloak.models.cache.infinispan.RealmCacheSession;
|
||||||
|
import org.keycloak.models.cache.infinispan.UserCacheSession;
|
||||||
import org.keycloak.organization.OrganizationProvider;
|
import org.keycloak.organization.OrganizationProvider;
|
||||||
|
|
||||||
import static org.keycloak.models.cache.infinispan.idp.InfinispanIdentityProviderStorageProvider.cacheKeyOrgId;
|
import static org.keycloak.models.cache.infinispan.idp.InfinispanIdentityProviderStorageProvider.cacheKeyOrgId;
|
||||||
|
@ -38,6 +40,7 @@ public class InfinispanOrganizationProvider implements OrganizationProvider {
|
||||||
private static final String ORG_MEMBERS_COUNT_KEY_SUFFIX = ".members.count";
|
private static final String ORG_MEMBERS_COUNT_KEY_SUFFIX = ".members.count";
|
||||||
|
|
||||||
private final KeycloakSession session;
|
private final KeycloakSession session;
|
||||||
|
private final UserCacheSession userCache;
|
||||||
private OrganizationProvider orgDelegate;
|
private OrganizationProvider orgDelegate;
|
||||||
private final RealmCacheSession realmCache;
|
private final RealmCacheSession realmCache;
|
||||||
private final Map<String, OrganizationAdapter> managedOrganizations = new HashMap<>();
|
private final Map<String, OrganizationAdapter> managedOrganizations = new HashMap<>();
|
||||||
|
@ -45,6 +48,7 @@ public class InfinispanOrganizationProvider implements OrganizationProvider {
|
||||||
public InfinispanOrganizationProvider(KeycloakSession session) {
|
public InfinispanOrganizationProvider(KeycloakSession session) {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
this.realmCache = (RealmCacheSession) session.getProvider(CacheRealmProvider.class);
|
this.realmCache = (RealmCacheSession) session.getProvider(CacheRealmProvider.class);
|
||||||
|
this.userCache = (UserCacheSession) session.getProvider(UserCache.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String cacheKeyOrgCount(RealmModel realm) {
|
private static String cacheKeyOrgCount(RealmModel realm) {
|
||||||
|
@ -201,14 +205,14 @@ public class InfinispanOrganizationProvider implements OrganizationProvider {
|
||||||
return getDelegate().getMemberById(organization, user.getId());
|
return getDelegate().getMemberById(organization, user.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
CachedMembership cached = realmCache.getCache().get(cacheKey, CachedMembership.class);
|
CachedMembership cached = userCache.getCache().get(cacheKey, CachedMembership.class);
|
||||||
|
|
||||||
if (cached == null) {
|
if (cached == null) {
|
||||||
boolean isManaged = getDelegate().isManagedMember(organization, user);
|
boolean isManaged = getDelegate().isManagedMember(organization, user);
|
||||||
Long loaded = realmCache.getCache().getCurrentRevision(cacheKey);
|
Long loaded = userCache.getCache().getCurrentRevision(cacheKey);
|
||||||
UserModel member = getDelegate().getMemberById(organization, user.getId());
|
UserModel member = getDelegate().getMemberById(organization, user.getId());
|
||||||
cached = new CachedMembership(loaded, cacheKey, realm, isManaged, member != null);
|
cached = new CachedMembership(loaded, cacheKey, realm, isManaged, member != null);
|
||||||
realmCache.getCache().addRevisioned(cached, realmCache.getStartupRevision());
|
userCache.getCache().addRevisioned(cached, userCache.getStartupRevision());
|
||||||
}
|
}
|
||||||
|
|
||||||
return cached.isMember() ? user : null;
|
return cached.isMember() ? user : null;
|
||||||
|
@ -222,13 +226,13 @@ public class InfinispanOrganizationProvider implements OrganizationProvider {
|
||||||
return getDelegate().getByMember(member);
|
return getDelegate().getByMember(member);
|
||||||
}
|
}
|
||||||
|
|
||||||
CachedOrganizationIds cached = realmCache.getCache().get(cacheKey, CachedOrganizationIds.class);
|
CachedOrganizationIds cached = userCache.getCache().get(cacheKey, CachedOrganizationIds.class);
|
||||||
|
|
||||||
if (cached == null) {
|
if (cached == null) {
|
||||||
Long loaded = realmCache.getCache().getCurrentRevision(cacheKey);
|
Long loaded = userCache.getCache().getCurrentRevision(cacheKey);
|
||||||
Stream<OrganizationModel> model = getDelegate().getByMember(member);
|
Stream<OrganizationModel> model = getDelegate().getByMember(member);
|
||||||
cached = new CachedOrganizationIds(loaded, cacheKey, getRealm(), model);
|
cached = new CachedOrganizationIds(loaded, cacheKey, getRealm(), model);
|
||||||
realmCache.getCache().addRevisioned(cached, realmCache.getStartupRevision());
|
userCache.getCache().addRevisioned(cached, userCache.getStartupRevision());
|
||||||
}
|
}
|
||||||
|
|
||||||
return cached.getOrgIds().stream().map(this::getById);
|
return cached.getOrgIds().stream().map(this::getById);
|
||||||
|
@ -241,7 +245,7 @@ public class InfinispanOrganizationProvider implements OrganizationProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
String cacheKey = cacheKeyMembership(getRealm(), organization, user);
|
String cacheKey = cacheKeyMembership(getRealm(), organization, user);
|
||||||
CachedMembership cached = realmCache.getCache().get(cacheKey, CachedMembership.class);
|
CachedMembership cached = userCache.getCache().get(cacheKey, CachedMembership.class);
|
||||||
|
|
||||||
if (cached == null || isInvalid(cacheKey)) {
|
if (cached == null || isInvalid(cacheKey)) {
|
||||||
// this will not cache the result as calling getMemberById() to have a full caching entry would lead to a recursion
|
// this will not cache the result as calling getMemberById() to have a full caching entry would lead to a recursion
|
||||||
|
@ -351,12 +355,12 @@ public class InfinispanOrganizationProvider implements OrganizationProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerMemberInvalidation(OrganizationModel organization, UserModel member) {
|
void registerMemberInvalidation(OrganizationModel organization, UserModel member) {
|
||||||
realmCache.registerInvalidation(cacheKeyByMember(member));
|
userCache.registerInvalidation(cacheKeyByMember(member));
|
||||||
realmCache.registerInvalidation(cacheKeyMembership(getRealm(), organization, member));
|
userCache.registerInvalidation(cacheKeyMembership(getRealm(), organization, member));
|
||||||
realmCache.registerInvalidation(cacheKeyOrgMemberCount(getRealm(), organization));
|
realmCache.registerInvalidation(cacheKeyOrgMemberCount(getRealm(), organization));
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isInvalid(String cacheKey) {
|
private boolean isInvalid(String cacheKey) {
|
||||||
return realmCache.getInvalidations().contains(cacheKey);
|
return realmCache.isInvalid(cacheKey) || userCache.isInvalid(cacheKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue