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
public class RealmCacheSession extends Object implements CacheRealmProvider
- 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 adapaters 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 beginningof the transaction. Whenever an entry is added to the cache, the current coutner 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
Fields Modifier and Type Field Description protected RealmCacheManagercacheprotected booleanclearAllprotected ClientProviderclientDelegateprotected ClientScopeProviderclientScopeDelegateprotected GroupProvidergroupDelegateprotected Set<InvalidationEvent>invalidationEventsprotected Set<String>invalidationsprotected Set<String>listInvalidationsprotected static org.jboss.logging.Loggerloggerprotected Map<String,ClientModel>managedApplicationsprotected Map<String,ClientScopeAdapter>managedClientScopesprotected Map<String,GroupAdapter>managedGroupsprotected Map<String,RealmAdapter>managedRealmsprotected Map<String,RoleAdapter>managedRolesstatic StringREALM_CLIENTS_QUERY_SUFFIXprotected RealmProviderrealmDelegateprotected RoleProviderroleDelegatestatic StringROLES_QUERY_SUFFIXprotected KeycloakSessionsessionprotected booleansetRollbackOnlyprotected longstartupRevisionprotected booleantransactionActive
-
Constructor Summary
Constructors Constructor Description RealmCacheSession(RealmCacheManager cache, KeycloakSession session)
-
Method Summary
-
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
-
Methods inherited from interface org.keycloak.models.GroupProvider
getGroupsStream, getGroupsStream
-
Methods inherited from interface org.keycloak.models.RealmProvider
addClientRole, addClientRole, createGroup, createGroup, createGroup, decreaseRemainingCount, getClientRole, getClientRoles, getClientRoles, getClientScopeById, getRealmRoles, getRoleById, removeRole, searchForClientRoles, searchForRoles
-
-
-
-
Field Detail
-
logger
protected static final org.jboss.logging.Logger logger
-
REALM_CLIENTS_QUERY_SUFFIX
public static final String REALM_CLIENTS_QUERY_SUFFIX
- See Also:
- Constant Field Values
-
ROLES_QUERY_SUFFIX
public static final String ROLES_QUERY_SUFFIX
- See Also:
- Constant Field Values
-
cache
protected RealmCacheManager cache
-
session
protected KeycloakSession session
-
realmDelegate
protected RealmProvider realmDelegate
-
clientDelegate
protected ClientProvider clientDelegate
-
clientScopeDelegate
protected ClientScopeProvider clientScopeDelegate
-
groupDelegate
protected GroupProvider groupDelegate
-
roleDelegate
protected RoleProvider roleDelegate
-
transactionActive
protected boolean transactionActive
-
setRollbackOnly
protected boolean setRollbackOnly
-
managedRealms
protected Map<String,RealmAdapter> managedRealms
-
managedApplications
protected Map<String,ClientModel> managedApplications
-
managedClientScopes
protected Map<String,ClientScopeAdapter> managedClientScopes
-
managedRoles
protected Map<String,RoleAdapter> managedRoles
-
managedGroups
protected Map<String,GroupAdapter> managedGroups
-
invalidationEvents
protected Set<InvalidationEvent> invalidationEvents
-
clearAll
protected boolean clearAll
-
startupRevision
protected final long startupRevision
-
-
Constructor Detail
-
RealmCacheSession
public RealmCacheSession(RealmCacheManager cache, KeycloakSession session)
-
-
Method Detail
-
getStartupRevision
public long getStartupRevision()
-
isInvalid
public boolean isInvalid(String id)
-
clear
public void clear()
- Specified by:
clearin interfaceCacheRealmProvider
-
getRealmDelegate
public RealmProvider getRealmDelegate()
- Specified by:
getRealmDelegatein interfaceCacheRealmProvider
-
getClientDelegate
public ClientProvider getClientDelegate()
-
getClientScopeDelegate
public ClientScopeProvider getClientScopeDelegate()
-
getRoleDelegate
public RoleProvider getRoleDelegate()
-
getGroupDelegate
public GroupProvider getGroupDelegate()
-
registerRealmInvalidation
public void registerRealmInvalidation(String id, String name)
- Specified by:
registerRealmInvalidationin interfaceCacheRealmProvider
-
registerClientInvalidation
public void registerClientInvalidation(String id, String clientId, String realmId)
- Specified by:
registerClientInvalidationin interfaceCacheRealmProvider
-
registerClientScopeInvalidation
public void registerClientScopeInvalidation(String id, String realmId)
- Specified by:
registerClientScopeInvalidationin interfaceCacheRealmProvider
-
registerRoleInvalidation
public void registerRoleInvalidation(String id, String roleName, String roleContainerId)
- Specified by:
registerRoleInvalidationin interfaceCacheRealmProvider
-
registerGroupInvalidation
public void registerGroupInvalidation(String id)
- Specified by:
registerGroupInvalidationin interfaceCacheRealmProvider
-
runInvalidations
protected void runInvalidations()
-
createRealm
public RealmModel createRealm(String name)
- Specified by:
createRealmin interfaceRealmProvider
-
createRealm
public RealmModel createRealm(String id, String name)
- Specified by:
createRealmin interfaceRealmProvider
-
getRealm
public RealmModel getRealm(String id)
- Specified by:
getRealmin interfaceRealmProvider
-
getRealmByName
public RealmModel getRealmByName(String name)
- Specified by:
getRealmByNamein interfaceRealmProvider
-
getRealmsWithProviderTypeStream
public Stream<RealmModel> getRealmsWithProviderTypeStream(Class<?> type)
- Specified by:
getRealmsWithProviderTypeStreamin interfaceRealmProvider
-
getRealmsStream
public Stream<RealmModel> getRealmsStream()
- Specified by:
getRealmsStreamin interfaceRealmProvider
-
removeRealm
public boolean removeRealm(String id)
- Specified by:
removeRealmin interfaceRealmProvider
-
evictRealmOnRemoval
public void evictRealmOnRemoval(RealmModel realm)
-
addClient
public ClientModel addClient(RealmModel realm, String clientId)
- Specified by:
addClientin interfaceClientProvider- Specified by:
addClientin interfaceRealmProvider
-
addClient
public ClientModel addClient(RealmModel realm, String id, String clientId)
- Specified by:
addClientin interfaceClientProvider- Specified by:
addClientin interfaceRealmProvider
-
getClientsStream
public Stream<ClientModel> getClientsStream(RealmModel realm, Integer firstResult, Integer maxResults)
- Specified by:
getClientsStreamin interfaceClientProvider
-
getClientsStream
public Stream<ClientModel> getClientsStream(RealmModel realm)
- Specified by:
getClientsStreamin interfaceClientProvider
-
getAlwaysDisplayInConsoleClientsStream
public Stream<ClientModel> getAlwaysDisplayInConsoleClientsStream(RealmModel realm)
- Specified by:
getAlwaysDisplayInConsoleClientsStreamin interfaceClientProvider
-
getAllRedirectUrisOfEnabledClients
public Map<ClientModel,Set<String>> getAllRedirectUrisOfEnabledClients(RealmModel realm)
- Specified by:
getAllRedirectUrisOfEnabledClientsin interfaceClientProvider
-
removeClients
public void removeClients(RealmModel realm)
- Specified by:
removeClientsin interfaceClientProvider
-
removeClient
public boolean removeClient(RealmModel realm, String id)
- Specified by:
removeClientin interfaceClientProvider
-
addRealmRole
public RoleModel addRealmRole(RealmModel realm, String name)
- Specified by:
addRealmRolein interfaceRealmProvider- Specified by:
addRealmRolein interfaceRoleProvider
-
addRealmRole
public RoleModel addRealmRole(RealmModel realm, String id, String name)
- Specified by:
addRealmRolein interfaceRealmProvider- Specified by:
addRealmRolein interfaceRoleProvider
-
getRealmRolesStream
public Stream<RoleModel> getRealmRolesStream(RealmModel realm)
- Specified by:
getRealmRolesStreamin interfaceRoleProvider
-
getClientRolesStream
public Stream<RoleModel> getClientRolesStream(ClientModel client)
- Specified by:
getClientRolesStreamin interfaceRoleProvider
-
getRealmRolesStream
public Stream<RoleModel> getRealmRolesStream(RealmModel realm, Integer first, Integer max)
- 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
public Stream<RoleModel> getClientRolesStream(ClientModel client, Integer first, Integer max)
- Specified by:
getClientRolesStreamin interfaceRoleProvider
-
searchForClientRolesStream
public Stream<RoleModel> searchForClientRolesStream(ClientModel client, String search, 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
public RoleModel addClientRole(ClientModel client, String name)
- Specified by:
addClientRolein interfaceRoleProvider
-
addClientRole
public RoleModel addClientRole(ClientModel client, String id, String name)
- Specified by:
addClientRolein interfaceRoleProvider
-
getRealmRole
public RoleModel getRealmRole(RealmModel realm, String name)
- Specified by:
getRealmRolein interfaceRealmProvider- Specified by:
getRealmRolein interfaceRoleLookupProvider
-
getClientRole
public RoleModel getClientRole(ClientModel client, String name)
- Specified by:
getClientRolein interfaceRoleLookupProvider
-
removeRole
public boolean removeRole(RoleModel role)
- Specified by:
removeRolein interfaceRoleProvider
-
removeRoles
public void removeRoles(RealmModel realm)
- Specified by:
removeRolesin interfaceRoleProvider
-
removeRoles
public void removeRoles(ClientModel client)
- Specified by:
removeRolesin interfaceRoleProvider
-
getRoleById
public RoleModel getRoleById(RealmModel realm, String id)
- Specified by:
getRoleByIdin interfaceRoleLookupProvider
-
getGroupById
public GroupModel getGroupById(RealmModel realm, String id)
- Specified by:
getGroupByIdin interfaceGroupLookupProvider- Specified by:
getGroupByIdin interfaceRealmProvider
-
moveGroup
public void moveGroup(RealmModel realm, GroupModel group, GroupModel toParent)
- Specified by:
moveGroupin interfaceGroupProvider- Specified by:
moveGroupin interfaceRealmProvider
-
getGroupsStream
public Stream<GroupModel> getGroupsStream(RealmModel realm)
- 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
public Long getGroupsCount(RealmModel realm, Stream<String> ids, String search)
- Specified by:
getGroupsCountin interfaceGroupProvider
-
getGroupsCount
public Long getGroupsCount(RealmModel realm, Boolean onlyTopGroups)
- Specified by:
getGroupsCountin interfaceGroupProvider- Specified by:
getGroupsCountin interfaceRealmProvider
-
getClientsCount
public long getClientsCount(RealmModel realm)
- Specified by:
getClientsCountin interfaceClientProvider- Specified by:
getClientsCountin interfaceRealmProvider
-
getGroupsCountByNameContaining
public Long getGroupsCountByNameContaining(RealmModel realm, String search)
- Specified by:
getGroupsCountByNameContainingin interfaceGroupProvider- Specified by:
getGroupsCountByNameContainingin interfaceRealmProvider
-
getGroupsByRoleStream
public Stream<GroupModel> getGroupsByRoleStream(RealmModel realm, RoleModel role, Integer firstResult, Integer maxResults)
- Specified by:
getGroupsByRoleStreamin interfaceGroupProvider
-
getTopLevelGroupsStream
public Stream<GroupModel> getTopLevelGroupsStream(RealmModel realm)
- Specified by:
getTopLevelGroupsStreamin interfaceGroupProvider
-
getTopLevelGroupsStream
public Stream<GroupModel> getTopLevelGroupsStream(RealmModel realm, 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
public boolean removeGroup(RealmModel realm, GroupModel group)
- Specified by:
removeGroupin interfaceGroupProvider- Specified by:
removeGroupin interfaceRealmProvider
-
createGroup
public GroupModel createGroup(RealmModel realm, String id, String name, GroupModel toParent)
- Specified by:
createGroupin interfaceGroupProvider- Specified by:
createGroupin interfaceRealmProvider
-
addTopLevelGroup
public void addTopLevelGroup(RealmModel realm, GroupModel subGroup)
- Specified by:
addTopLevelGroupin interfaceGroupProvider- Specified by:
addTopLevelGroupin interfaceRealmProvider
-
getClientById
public ClientModel getClientById(RealmModel realm, String id)
- Specified by:
getClientByIdin interfaceClientLookupProvider
-
cacheClient
protected ClientModel cacheClient(RealmModel realm, ClientModel delegate, Long revision)
-
validateCache
protected ClientModel validateCache(RealmModel realm, CachedClient cached)
-
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
-
getClientByClientId
public ClientModel getClientByClientId(RealmModel realm, String clientId)
- Specified by:
getClientByClientIdin interfaceClientLookupProvider
-
getClientScopeById
public ClientScopeModel getClientScopeById(RealmModel realm, String id)
- Specified by:
getClientScopeByIdin interfaceClientScopeLookupProvider- Specified by:
getClientScopeByIdin interfaceRealmProvider
-
getClientScopesStream
public Stream<ClientScopeModel> getClientScopesStream(RealmModel realm)
- Specified by:
getClientScopesStreamin interfaceClientScopeProvider
-
addClientScope
public ClientScopeModel addClientScope(RealmModel realm, String name)
- Specified by:
addClientScopein interfaceClientScopeProvider
-
addClientScope
public ClientScopeModel addClientScope(RealmModel realm, String id, String name)
- Specified by:
addClientScopein interfaceClientScopeProvider
-
removeClientScope
public boolean removeClientScope(RealmModel realm, String id)
- Specified by:
removeClientScopein interfaceClientScopeProvider
-
removeClientScopes
public void removeClientScopes(RealmModel realm)
- Specified by:
removeClientScopesin interfaceClientScopeProvider
-
addClientScopes
public void addClientScopes(RealmModel realm, ClientModel client, Set<ClientScopeModel> clientScopes, boolean defaultScope)
- Specified by:
addClientScopesin interfaceClientProvider
-
removeClientScope
public void removeClientScope(RealmModel realm, ClientModel client, ClientScopeModel clientScope)
- Specified by:
removeClientScopein interfaceClientProvider
-
getClientScopes
public Map<String,ClientScopeModel> getClientScopes(RealmModel realm, ClientModel client, boolean defaultScopes)
- Specified by:
getClientScopesin interfaceClientLookupProvider
-
createClientInitialAccessModel
public ClientInitialAccessModel createClientInitialAccessModel(RealmModel realm, int expiration, int count)
- Specified by:
createClientInitialAccessModelin interfaceRealmProvider
-
getClientInitialAccessModel
public ClientInitialAccessModel getClientInitialAccessModel(RealmModel realm, String id)
- Specified by:
getClientInitialAccessModelin interfaceRealmProvider
-
removeClientInitialAccessModel
public void removeClientInitialAccessModel(RealmModel realm, String id)
- Specified by:
removeClientInitialAccessModelin interfaceRealmProvider
-
listClientInitialAccessStream
public Stream<ClientInitialAccessModel> listClientInitialAccessStream(RealmModel realm)
- Specified by:
listClientInitialAccessStreamin interfaceRealmProvider
-
removeExpiredClientInitialAccess
public void removeExpiredClientInitialAccess()
- Specified by:
removeExpiredClientInitialAccessin interfaceRealmProvider
-
saveLocalizationText
public void saveLocalizationText(RealmModel realm, String locale, String key, String text)
- Specified by:
saveLocalizationTextin interfaceRealmProvider
-
saveLocalizationTexts
public void saveLocalizationTexts(RealmModel realm, String locale, Map<String,String> localizationTexts)
- Specified by:
saveLocalizationTextsin interfaceRealmProvider
-
updateLocalizationText
public boolean updateLocalizationText(RealmModel realm, String locale, String key, String text)
- Specified by:
updateLocalizationTextin interfaceRealmProvider
-
deleteLocalizationTextsByLocale
public boolean deleteLocalizationTextsByLocale(RealmModel realm, String locale)
- Specified by:
deleteLocalizationTextsByLocalein interfaceRealmProvider
-
deleteLocalizationText
public boolean deleteLocalizationText(RealmModel realm, String locale, String key)
- Specified by:
deleteLocalizationTextin interfaceRealmProvider
-
getLocalizationTextsById
public String getLocalizationTextsById(RealmModel realm, String locale, String key)
- Specified by:
getLocalizationTextsByIdin interfaceRealmProvider
-
-