Class RealmCacheSession
java.lang.Object
org.keycloak.models.cache.infinispan.RealmCacheSession
- All Implemented Interfaces:
CacheRealmProvider,ClientProvider,ClientScopeProvider,GroupProvider,RealmProvider,RoleProvider,Provider,ClientLookupProvider,ClientScopeLookupProvider,GroupLookupProvider,RoleLookupProvider
- the high level architecture of this cache is an invalidation cache.
- the cache is manual/custom versioned. When a model is updated, we remove it from the cache
which causes an invalidation message to be sent across the cluster.
- We had to do it this way because Infinispan REPEATABLE_READ
wouldn't cut it in invalidation mode. Also, REPEATABLE_READ doesn't work very well on relationships and items that are
not in the cache.
- There are two Infinispan caches. One clustered that holds actual objects and a another local one that holds revision
numbers of cached objects. Whenever a cached object is removed (invalidated), the local revision
cache number or that key is bumped higher based on a local version counter. Whenever a cache entry is fetched, this
revision number is also fetched and compared against the revision number in the cache entry to see if the cache entry
is stale. Whenever a cache entry is added, this revision number is also checked against the revision cache.
- Revision entries are actually never removed (although they could be evicted by cache eviction policies). The reason for this
is that it is possible for a stale object to be inserted if one thread loads and the data is updated in the database before
it is added to the cache. So, we keep the version number around for this.
- In a transaction, objects are registered to be invalidated. If an object is marked for invalidation within a transaction
a cached object should never be returned. An DB adapter should always be returned.
- After DB commits, the objects marked for invalidation are invalidated, or rather removed from the cache. At this time
the revision cache entry for this object has its version number bumped.
- Whenever an object is marked for invalidation, the cache is also searched for any objects that are related to this object
and need to also be evicted/removed. We use the Infinispan Stream SPI for this.
ClientList caches:
- lists of clients are cached in a specific cache entry i.e. realm clients, find client by clientId
- realm client lists need to be invalidated and evited whenever a client is added or removed from a realm. RealmProvider
now has addClient/removeClient at its top level. All adapters should use these methods so that the appropriate invalidations
can be registered.
- whenever a client is added/removed the realm of the client is added to a listInvalidations set
this set must be checked before sending back or caching a cached query. This check is required to
avoid caching an uncommitted removal/add in a query cache.
- when a client is removed, any queries that contain that client must also be removed.
- a client removal will also cause anything that is contained and cached within that client to be removed
Clustered caches:
- There is a Infinispan @Listener registered. If an invalidation event happens, this is treated like
the object was removed from the database and will perform evictions based on that assumption.
- Eviction events will also cascade other evictions, but not assume this is a db removal.
- With an invalidation cache, if you remove an entry on node 1 and this entry does not exist on node 2, node 2 will not receive a @Listener invalidation event.
so, hat we have to put a marker entry in the invalidation cache before we read from the DB, so if the DB changes in between reading and adding a cache entry, the cache will be notified and bump
the version information.
DBs with Repeatable Read:
- DBs like MySQL are Repeatable Read by default. So, if you query a Client for instance, it will always return the same result in the same transaction even if the DB
was updated in between these queries. This makes it possible to store stale cache entries. To avoid this problem, this class stores the current local version counter
at the beginning of the transaction. Whenever an entry is added to the cache, the current counter is compared against the counter at the beginning of the tx. If the current
is greater, then don't cache.
Groups and Roles:
- roles are tricky because of composites. Composite lists are cached too. So, when a role is removed
we also iterate and invalidate any role or group that contains that role being removed.
- any relationship should be resolved from session.realms(). For example if JPA.getClientByClientId() is invoked,
JPA should find the id of the client and then call session.realms().getClientById(). THis is to ensure that the cached
object is invoked and all proper invalidation are being invoked.
- Version:
- $Revision: 1 $
- Author:
- Bill Burke
-
Field Summary
FieldsModifier and TypeFieldDescriptionprotected RealmCacheManagerprotected ClientProviderprotected ClientScopeProviderprotected GroupProviderprotected Set<InvalidationEvent>protected static final org.jboss.logging.Loggerprotected Map<String,ClientModel> protected Map<String,ClientScopeAdapter> protected Map<String,GroupAdapter> protected Map<String,RealmAdapter> protected Map<String,RoleAdapter> static final Stringprotected RealmProviderprotected RoleProviderstatic final Stringprotected KeycloakSessionprotected booleanprotected final longprotected booleanFields inherited from interface org.keycloak.models.GroupProvider
DEFAULT_ESCAPE_SLASHES -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionaddClient(RealmModel realm, String clientId) addClient(RealmModel realm, String id, String clientId) addClientRole(ClientModel client, String name) addClientRole(ClientModel client, String id, String name) addClientScope(RealmModel realm, String name) addClientScope(RealmModel realm, String id, String name) voidaddClientScopes(RealmModel realm, ClientModel client, Set<ClientScopeModel> clientScopes, boolean defaultScope) voidaddClientScopeToAllClients(RealmModel realm, ClientScopeModel clientScope, boolean defaultClientScope) addRealmRole(RealmModel realm, String name) addRealmRole(RealmModel realm, String id, String name) voidaddTopLevelGroup(RealmModel realm, GroupModel subGroup) protected ClientModelcacheClient(RealmModel realm, ClientModel delegate, Long revision) voidclear()voidclose()createClientInitialAccessModel(RealmModel realm, int expiration, int count) createGroup(RealmModel realm, String id, String name, GroupModel toParent) createRealm(String name) createRealm(String id, String name) booleandeleteLocalizationText(RealmModel realm, String locale, String key) booleandeleteLocalizationTextsByLocale(RealmModel realm, String locale) voidevictRealmOnRemoval(RealmModel realm) getClientByClientId(RealmModel realm, String clientId) getClientById(RealmModel realm, String id) getClientInitialAccessModel(RealmModel realm, String id) getClientRole(ClientModel client, String name) getClientRolesStream(ClientModel client) getClientRolesStream(ClientModel client, Integer first, Integer max) getClientScopeById(RealmModel realm, String id) getClientScopes(RealmModel realm, ClientModel client, boolean defaultScopes) getClientScopesStream(RealmModel realm) longgetClientsCount(RealmModel realm) getClientsStream(RealmModel realm) getClientsStream(RealmModel realm, Integer firstResult, Integer maxResults) getGroupById(RealmModel realm, String id) getGroupByName(RealmModel realm, GroupModel parent, String name) getGroupsByRoleStream(RealmModel realm, RoleModel role, Integer firstResult, Integer maxResults) getGroupsCount(RealmModel realm, Boolean onlyTopGroups) getGroupsCount(RealmModel realm, Stream<String> ids, String search) getGroupsCountByNameContaining(RealmModel realm, String search) getGroupsStream(RealmModel realm) getGroupsStream(RealmModel realm, Stream<String> ids, String search, Integer first, Integer max) getLocalizationTextsById(RealmModel realm, String locale, String key) getRealmByName(String name) getRealmRole(RealmModel realm, String name) getRealmRolesStream(RealmModel realm) getRealmRolesStream(RealmModel realm, Integer first, Integer max) getRealmsWithProviderTypeStream(Class<?> type) getRoleById(RealmModel realm, String id) getRolesStream(RealmModel realm, Stream<String> ids, String search, Integer first, Integer max) getTopLevelGroupsStream(RealmModel realm, String search, Boolean exact, Integer first, Integer max) voidmoveGroup(RealmModel realm, GroupModel group, GroupModel toParent) voidregisterClientInvalidation(String id, String clientId, String realmId) voidregisterClientScopeInvalidation(String id, String realmId) voidvoidregisterRealmInvalidation(String id, String name) voidregisterRoleInvalidation(String id, String roleName, String roleContainerId) booleanremoveClient(RealmModel realm, String id) voidremoveClientInitialAccessModel(RealmModel realm, String id) voidremoveClients(RealmModel realm) booleanremoveClientScope(RealmModel realm, String id) voidremoveClientScope(RealmModel realm, ClientModel client, ClientScopeModel clientScope) voidremoveClientScopes(RealmModel realm) voidbooleanremoveGroup(RealmModel realm, GroupModel group) booleanremoveRealm(String id) booleanremoveRole(RoleModel role) voidremoveRoles(ClientModel client) voidremoveRoles(RealmModel realm) protected voidvoidsaveLocalizationText(RealmModel realm, String locale, String key, String text) voidsaveLocalizationTexts(RealmModel realm, String locale, Map<String, String> localizationTexts) searchClientsByAttributes(RealmModel realm, Map<String, String> attributes, Integer firstResult, Integer maxResults) searchClientsByAuthenticationFlowBindingOverrides(RealmModel realm, Map<String, String> overrides, Integer firstResult, Integer maxResults) searchClientsByClientIdStream(RealmModel realm, String clientId, Integer firstResult, Integer maxResults) searchForClientRolesStream(ClientModel client, String search, Integer first, Integer max) searchForClientRolesStream(RealmModel realm, String search, Stream<String> excludedIds, Integer first, Integer max) searchForClientRolesStream(RealmModel realm, Stream<String> ids, String search, Integer first, Integer max) searchForGroupByNameStream(RealmModel realm, String search, Boolean exact, Integer firstResult, Integer maxResults) searchForGroupByNameStream(RealmModel realm, String search, Integer first, Integer max) searchForRolesStream(RealmModel realm, String search, Integer first, Integer max) searchGroupsByAttributes(RealmModel realm, Map<String, String> attributes, Integer firstResult, Integer maxResults) booleanupdateLocalizationText(RealmModel realm, String locale, String key, String text) protected ClientModelvalidateCache(RealmModel realm, CachedClient cached) Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitMethods inherited from interface org.keycloak.models.GroupProvider
createGroup, createGroup, createGroup, getGroupsStream, getGroupsStream, getTopLevelGroupsStream, getTopLevelGroupsStreamMethods inherited from interface org.keycloak.models.RealmProvider
decreaseRemainingCount
-
Field Details
-
logger
protected static final org.jboss.logging.Logger logger -
REALM_CLIENTS_QUERY_SUFFIX
- See Also:
-
ROLES_QUERY_SUFFIX
- See Also:
-
cache
-
session
-
realmDelegate
-
clientDelegate
-
clientScopeDelegate
-
groupDelegate
-
roleDelegate
-
transactionActive
protected boolean transactionActive -
setRollbackOnly
protected boolean setRollbackOnly -
managedRealms
-
managedApplications
-
managedClientScopes
-
managedRoles
-
managedGroups
-
listInvalidations
-
invalidations
-
invalidationEvents
-
startupRevision
protected final long startupRevision
-
-
Constructor Details
-
RealmCacheSession
-
-
Method Details
-
clear
public void clear()- Specified by:
clearin interfaceCacheRealmProvider
-
getRealmDelegate
- Specified by:
getRealmDelegatein interfaceCacheRealmProvider
-
getClientDelegate
-
getClientScopeDelegate
-
getRoleDelegate
-
getGroupDelegate
-
registerRealmInvalidation
- Specified by:
registerRealmInvalidationin interfaceCacheRealmProvider
-
registerClientInvalidation
- Specified by:
registerClientInvalidationin interfaceCacheRealmProvider
-
registerClientScopeInvalidation
- Specified by:
registerClientScopeInvalidationin interfaceCacheRealmProvider
-
registerRoleInvalidation
- Specified by:
registerRoleInvalidationin interfaceCacheRealmProvider
-
registerGroupInvalidation
- Specified by:
registerGroupInvalidationin interfaceCacheRealmProvider
-
runInvalidations
protected void runInvalidations() -
createRealm
- Specified by:
createRealmin interfaceRealmProvider
-
createRealm
- Specified by:
createRealmin interfaceRealmProvider
-
getRealm
- Specified by:
getRealmin interfaceRealmProvider
-
getRealmByName
- Specified by:
getRealmByNamein interfaceRealmProvider
-
getRealmsWithProviderTypeStream
- Specified by:
getRealmsWithProviderTypeStreamin interfaceRealmProvider
-
getRealmsStream
- Specified by:
getRealmsStreamin interfaceRealmProvider
-
removeRealm
- Specified by:
removeRealmin interfaceRealmProvider
-
evictRealmOnRemoval
-
addClient
- Specified by:
addClientin interfaceClientProvider
-
addClient
- Specified by:
addClientin interfaceClientProvider
-
getClientsStream
public Stream<ClientModel> getClientsStream(RealmModel realm, Integer firstResult, Integer maxResults) - Specified by:
getClientsStreamin interfaceClientProvider
-
getClientsStream
- Specified by:
getClientsStreamin interfaceClientProvider
-
getAlwaysDisplayInConsoleClientsStream
- Specified by:
getAlwaysDisplayInConsoleClientsStreamin interfaceClientProvider
-
getAllRedirectUrisOfEnabledClients
- Specified by:
getAllRedirectUrisOfEnabledClientsin interfaceClientProvider
-
removeClients
- Specified by:
removeClientsin interfaceClientProvider
-
removeClient
- Specified by:
removeClientin interfaceClientProvider
-
close
public void close() -
addRealmRole
- Specified by:
addRealmRolein interfaceRoleProvider
-
addRealmRole
- Specified by:
addRealmRolein interfaceRoleProvider
-
getRealmRolesStream
- Specified by:
getRealmRolesStreamin interfaceRoleProvider
-
getClientRolesStream
- Specified by:
getClientRolesStreamin interfaceRoleProvider
-
getRealmRolesStream
- Specified by:
getRealmRolesStreamin interfaceRoleProvider
-
getRolesStream
public Stream<RoleModel> getRolesStream(RealmModel realm, Stream<String> ids, String search, Integer first, Integer max) - Specified by:
getRolesStreamin interfaceRoleProvider
-
getClientRolesStream
- Specified by:
getClientRolesStreamin interfaceRoleProvider
-
searchForClientRolesStream
public Stream<RoleModel> searchForClientRolesStream(ClientModel client, String search, Integer first, Integer max) - Specified by:
searchForClientRolesStreamin interfaceRoleLookupProvider
-
searchForClientRolesStream
public Stream<RoleModel> searchForClientRolesStream(RealmModel realm, Stream<String> ids, String search, Integer first, Integer max) - Specified by:
searchForClientRolesStreamin interfaceRoleLookupProvider
-
searchForClientRolesStream
public Stream<RoleModel> searchForClientRolesStream(RealmModel realm, String search, Stream<String> excludedIds, Integer first, Integer max) - Specified by:
searchForClientRolesStreamin interfaceRoleLookupProvider
-
searchForRolesStream
public Stream<RoleModel> searchForRolesStream(RealmModel realm, String search, Integer first, Integer max) - Specified by:
searchForRolesStreamin interfaceRoleLookupProvider
-
addClientRole
- Specified by:
addClientRolein interfaceRoleProvider
-
addClientRole
- Specified by:
addClientRolein interfaceRoleProvider
-
getRealmRole
- Specified by:
getRealmRolein interfaceRoleLookupProvider
-
getClientRole
- Specified by:
getClientRolein interfaceRoleLookupProvider
-
removeRole
- Specified by:
removeRolein interfaceRoleProvider
-
removeRoles
- Specified by:
removeRolesin interfaceRoleProvider
-
removeRoles
- Specified by:
removeRolesin interfaceRoleProvider
-
getRoleById
- Specified by:
getRoleByIdin interfaceRoleLookupProvider
-
getGroupById
- Specified by:
getGroupByIdin interfaceGroupLookupProvider
-
getGroupByName
- Specified by:
getGroupByNamein interfaceGroupLookupProvider
-
moveGroup
- Specified by:
moveGroupin interfaceGroupProvider
-
getGroupsStream
- Specified by:
getGroupsStreamin interfaceGroupProvider
-
getGroupsStream
public Stream<GroupModel> getGroupsStream(RealmModel realm, Stream<String> ids, String search, Integer first, Integer max) - Specified by:
getGroupsStreamin interfaceGroupProvider
-
getGroupsCount
- Specified by:
getGroupsCountin interfaceGroupProvider
-
getGroupsCount
- Specified by:
getGroupsCountin interfaceGroupProvider
-
getClientsCount
- Specified by:
getClientsCountin interfaceClientProvider
-
getGroupsCountByNameContaining
- Specified by:
getGroupsCountByNameContainingin interfaceGroupProvider
-
getGroupsByRoleStream
public Stream<GroupModel> getGroupsByRoleStream(RealmModel realm, RoleModel role, Integer firstResult, Integer maxResults) - Specified by:
getGroupsByRoleStreamin interfaceGroupProvider
-
getTopLevelGroupsStream
public Stream<GroupModel> getTopLevelGroupsStream(RealmModel realm, String search, Boolean exact, Integer first, Integer max) - Specified by:
getTopLevelGroupsStreamin interfaceGroupProvider
-
searchForGroupByNameStream
public Stream<GroupModel> searchForGroupByNameStream(RealmModel realm, String search, Integer first, Integer max) - Specified by:
searchForGroupByNameStreamin interfaceGroupLookupProvider
-
searchForGroupByNameStream
public Stream<GroupModel> searchForGroupByNameStream(RealmModel realm, String search, Boolean exact, Integer firstResult, Integer maxResults) - Specified by:
searchForGroupByNameStreamin interfaceGroupLookupProvider
-
searchGroupsByAttributes
public Stream<GroupModel> searchGroupsByAttributes(RealmModel realm, Map<String, String> attributes, Integer firstResult, Integer maxResults) - Specified by:
searchGroupsByAttributesin interfaceGroupLookupProvider
-
removeGroup
- Specified by:
removeGroupin interfaceGroupProvider
-
createGroup
- Specified by:
createGroupin interfaceGroupProvider
-
addTopLevelGroup
- Specified by:
addTopLevelGroupin interfaceGroupProvider
-
getClientById
- Specified by:
getClientByIdin interfaceClientLookupProvider
-
cacheClient
-
validateCache
-
searchClientsByClientIdStream
public Stream<ClientModel> searchClientsByClientIdStream(RealmModel realm, String clientId, Integer firstResult, Integer maxResults) - Specified by:
searchClientsByClientIdStreamin interfaceClientLookupProvider
-
searchClientsByAttributes
public Stream<ClientModel> searchClientsByAttributes(RealmModel realm, Map<String, String> attributes, Integer firstResult, Integer maxResults) - Specified by:
searchClientsByAttributesin interfaceClientLookupProvider
-
searchClientsByAuthenticationFlowBindingOverrides
public Stream<ClientModel> searchClientsByAuthenticationFlowBindingOverrides(RealmModel realm, Map<String, String> overrides, Integer firstResult, Integer maxResults) - Specified by:
searchClientsByAuthenticationFlowBindingOverridesin interfaceClientLookupProvider
-
getClientByClientId
- Specified by:
getClientByClientIdin interfaceClientLookupProvider
-
getClientScopeById
- Specified by:
getClientScopeByIdin interfaceClientScopeLookupProvider
-
getClientScopesStream
- Specified by:
getClientScopesStreamin interfaceClientScopeProvider
-
addClientScope
- Specified by:
addClientScopein interfaceClientScopeProvider
-
addClientScope
- Specified by:
addClientScopein interfaceClientScopeProvider
-
removeClientScope
- Specified by:
removeClientScopein interfaceClientScopeProvider
-
removeClientScopes
- Specified by:
removeClientScopesin interfaceClientScopeProvider
-
addClientScopes
public void addClientScopes(RealmModel realm, ClientModel client, Set<ClientScopeModel> clientScopes, boolean defaultScope) - Specified by:
addClientScopesin interfaceClientProvider
-
removeClientScope
- Specified by:
removeClientScopein interfaceClientProvider
-
getClientScopes
public Map<String,ClientScopeModel> getClientScopes(RealmModel realm, ClientModel client, boolean defaultScopes) - Specified by:
getClientScopesin interfaceClientLookupProvider
-
addClientScopeToAllClients
public void addClientScopeToAllClients(RealmModel realm, ClientScopeModel clientScope, boolean defaultClientScope) - Specified by:
addClientScopeToAllClientsin interfaceClientProvider
-
createClientInitialAccessModel
public ClientInitialAccessModel createClientInitialAccessModel(RealmModel realm, int expiration, int count) - Specified by:
createClientInitialAccessModelin interfaceRealmProvider
-
getClientInitialAccessModel
- Specified by:
getClientInitialAccessModelin interfaceRealmProvider
-
removeClientInitialAccessModel
- Specified by:
removeClientInitialAccessModelin interfaceRealmProvider
-
listClientInitialAccessStream
- Specified by:
listClientInitialAccessStreamin interfaceRealmProvider
-
removeExpiredClientInitialAccess
public void removeExpiredClientInitialAccess()- Specified by:
removeExpiredClientInitialAccessin interfaceRealmProvider
-
saveLocalizationText
- Specified by:
saveLocalizationTextin interfaceRealmProvider
-
saveLocalizationTexts
public void saveLocalizationTexts(RealmModel realm, String locale, Map<String, String> localizationTexts) - Specified by:
saveLocalizationTextsin interfaceRealmProvider
-
updateLocalizationText
- Specified by:
updateLocalizationTextin interfaceRealmProvider
-
deleteLocalizationTextsByLocale
- Specified by:
deleteLocalizationTextsByLocalein interfaceRealmProvider
-
deleteLocalizationText
- Specified by:
deleteLocalizationTextin interfaceRealmProvider
-
getLocalizationTextsById
- Specified by:
getLocalizationTextsByIdin interfaceRealmProvider
-