org.keycloak.models.cache.infinispan

## Class RealmCacheSession

- java.lang.Object
- - org.keycloak.models.cache.infinispan.RealmCacheSession

- All Implemented Interfaces:
    CacheRealmProvider, RealmProvider, Provider

      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 and Description
    --- | ---
    `protected RealmCacheManager` | `cache`
    `protected boolean` | `clearAll`
    `protected RealmProvider` | `delegate`
    `protected Set<String>` | `invalidations`
    `protected Set<String>` | `listInvalidations`
    `protected static org.jboss.logging.Logger` | `logger`
    `protected Map<String,ClientAdapter>` | `managedApplications`
    `protected Map<String,ClientTemplateAdapter>` | `managedClientTemplates`
    `protected Map<String,GroupAdapter>` | `managedGroups`
    `protected Map<String,RealmAdapter>` | `managedRealms`
    `protected Map<String,RoleAdapter>` | `managedRoles`
    `static String` | `REALM_CLIENTS_QUERY_SUFFIX`
    `static String` | `ROLE_BY_NAME_QUERY_SUFFIX`
    `static String` | `ROLES_QUERY_SUFFIX`
    `protected KeycloakSession` | `session`
    `protected boolean` | `setRollbackOnly`
    `protected long` | `startupRevision`
    `protected boolean` | `transactionActive`

  - ### Constructor Summary

    Constructors
    Constructor and Description
    `RealmCacheSession(RealmCacheManager cache, KeycloakSession session)`

  - ### Method Summary

    All Methods Instance Methods Concrete Methods
    Modifier and Type | Method and Description
    --- | ---
    `ClientModel` | `addClient(RealmModel realm, String clientId)`
    `ClientModel` | `addClient(RealmModel realm, String id, String clientId)`
    `RoleModel` | `addClientRole(RealmModel realm, ClientModel client, String name)`
    `RoleModel` | `addClientRole(RealmModel realm, ClientModel client, String id, String name)`
    `RoleModel` | `addRealmRole(RealmModel realm, String name)`
    `RoleModel` | `addRealmRole(RealmModel realm, String id, String name)`
    `void` | `addTopLevelGroup(RealmModel realm, GroupModel subGroup)`
    `void` | `clear()`
    `void` | `close()`
    `GroupModel` | `createGroup(RealmModel realm, String name)`
    `GroupModel` | `createGroup(RealmModel realm, String id, String name)`
    `RealmModel` | `createRealm(String name)`
    `RealmModel` | `createRealm(String id, String name)`
    `ClientModel` | `getClientByClientId(String clientId, RealmModel realm)`
    `String` | `getClientByClientIdCacheKey(String clientId, RealmModel realm)`
    `ClientModel` | `getClientById(String id, RealmModel realm)`
    `RoleModel` | `getClientRole(RealmModel realm, ClientModel client, String name)`
    `Set<RoleModel>` | `getClientRoles(RealmModel realm, ClientModel client)`
    `List<ClientModel>` | `getClients(RealmModel realm)`
    `ClientTemplateModel` | `getClientTemplateById(String id, RealmModel realm)`
    `RealmProvider` | `getDelegate()`
    `GroupModel` | `getGroupById(String id, RealmModel realm)`
    `List<GroupModel>` | `getGroups(RealmModel realm)`
    `MigrationModel` | `getMigrationModel()`
    `RealmModel` | `getRealm(String id)`
    `RealmModel` | `getRealmByName(String name)`
    `String` | `getRealmByNameCacheKey(String name)`
    `RoleModel` | `getRealmRole(RealmModel realm, String name)`
    `Set<RoleModel>` | `getRealmRoles(RealmModel realm)`
    `List<RealmModel>` | `getRealms()`
    `RoleModel` | `getRoleById(String id, RealmModel realm)`
    `long` | `getStartupRevision()`
    `List<GroupModel>` | `getTopLevelGroups(RealmModel realm)`
    `GroupModel` | `groupAdded(RealmModel realm, GroupModel group)`
    `protected void` | `invalidateClient(RealmModel realm, ClientModel client)`
    `boolean` | `isInvalid(String id)`
    `void` | `moveGroup(RealmModel realm, GroupModel group, GroupModel toParent)`
    `void` | `registerClientInvalidation(String id)`
    `void` | `registerClientTemplateInvalidation(String id)`
    `void` | `registerGroupInvalidation(String id)`
    `void` | `registerRealmInvalidation(String id)`
    `void` | `registerRoleInvalidation(String id)`
    `boolean` | `removeClient(String id, RealmModel realm)`
    `boolean` | `removeGroup(RealmModel realm, GroupModel group)`
    `boolean` | `removeRealm(String id)`
    `boolean` | `removeRole(RealmModel realm, RoleModel role)`
    `protected void` | `runInvalidations()`

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### 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

    - #### ROLE_BY_NAME_QUERY_SUFFIX

          public static final String ROLE_BY_NAME_QUERY_SUFFIX

      See Also:
        Constant Field Values

    - #### cache

          protected RealmCacheManager cache

    - #### session

          protected KeycloakSession session

    - #### delegate

          protected RealmProvider delegate

    - #### transactionActive

          protected boolean transactionActive

    - #### setRollbackOnly

          protected boolean setRollbackOnly

    - #### managedRealms

          protected Map<String,RealmAdapter> managedRealms

    - #### managedApplications

          protected Map<String,ClientAdapter> managedApplications

    - #### managedClientTemplates

          protected Map<String,ClientTemplateAdapter> managedClientTemplates

    - #### managedRoles

          protected Map<String,RoleAdapter> managedRoles

    - #### managedGroups

          protected Map<String,GroupAdapter> managedGroups

    - #### listInvalidations

          protected Set<String> listInvalidations

    - #### invalidations

          protected Set<String> invalidations

    - #### 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:
        `clear` in interface `CacheRealmProvider`

    - #### getMigrationModel

          public MigrationModel getMigrationModel()

      Specified by:
        `getMigrationModel` in interface `RealmProvider`

    - #### getDelegate

          public RealmProvider getDelegate()

      Specified by:
        `getDelegate` in interface `CacheRealmProvider`

    - #### registerRealmInvalidation

          public void registerRealmInvalidation(String id)

      Specified by:
        `registerRealmInvalidation` in interface `CacheRealmProvider`

    - #### registerClientInvalidation

          public void registerClientInvalidation(String id)

      Specified by:
        `registerClientInvalidation` in interface `CacheRealmProvider`

    - #### registerClientTemplateInvalidation

          public void registerClientTemplateInvalidation(String id)

      Specified by:
        `registerClientTemplateInvalidation` in interface `CacheRealmProvider`

    - #### registerRoleInvalidation

          public void registerRoleInvalidation(String id)

      Specified by:
        `registerRoleInvalidation` in interface `CacheRealmProvider`

    - #### registerGroupInvalidation

          public void registerGroupInvalidation(String id)

      Specified by:
        `registerGroupInvalidation` in interface `CacheRealmProvider`

    - #### runInvalidations

          protected void runInvalidations()

    - #### createRealm

          public RealmModel createRealm(String name)

      Specified by:
        `createRealm` in interface `RealmProvider`

    - #### createRealm

          public RealmModel createRealm(String id,
                                        String name)

      Specified by:
        `createRealm` in interface `RealmProvider`

    - #### getRealm

          public RealmModel getRealm(String id)

      Specified by:
        `getRealm` in interface `RealmProvider`

    - #### getRealmByName

          public RealmModel getRealmByName(String name)

      Specified by:
        `getRealmByName` in interface `RealmProvider`

    - #### getRealmByNameCacheKey

          public String getRealmByNameCacheKey(String name)

    - #### getRealms

          public List<RealmModel> getRealms()

      Specified by:
        `getRealms` in interface `RealmProvider`

    - #### removeRealm

          public boolean removeRealm(String id)

      Specified by:
        `removeRealm` in interface `RealmProvider`

    - #### invalidateClient

          protected void invalidateClient(RealmModel realm,
                                          ClientModel client)

    - #### addClient

          public ClientModel addClient(RealmModel realm,
                                       String clientId)

      Specified by:
        `addClient` in interface `RealmProvider`

    - #### addClient

          public ClientModel addClient(RealmModel realm,
                                       String id,
                                       String clientId)

      Specified by:
        `addClient` in interface `RealmProvider`

    - #### getClients

          public List<ClientModel> getClients(RealmModel realm)

      Specified by:
        `getClients` in interface `RealmProvider`

    - #### removeClient

          public boolean removeClient(String id,
                                      RealmModel realm)

      Specified by:
        `removeClient` in interface `RealmProvider`

    - #### close

          public void close()

      Specified by:
        `close` in interface `RealmProvider`
      Specified by:
        `close` in interface `Provider`

    - #### addRealmRole

          public RoleModel addRealmRole(RealmModel realm,
                                        String name)

      Specified by:
        `addRealmRole` in interface `RealmProvider`

    - #### addRealmRole

          public RoleModel addRealmRole(RealmModel realm,
                                        String id,
                                        String name)

      Specified by:
        `addRealmRole` in interface `RealmProvider`

    - #### getRealmRoles

          public Set<RoleModel> getRealmRoles(RealmModel realm)

      Specified by:
        `getRealmRoles` in interface `RealmProvider`

    - #### getClientRoles

          public Set<RoleModel> getClientRoles(RealmModel realm,
                                               ClientModel client)

      Specified by:
        `getClientRoles` in interface `RealmProvider`

    - #### addClientRole

          public RoleModel addClientRole(RealmModel realm,
                                         ClientModel client,
                                         String name)

      Specified by:
        `addClientRole` in interface `RealmProvider`

    - #### addClientRole

          public RoleModel addClientRole(RealmModel realm,
                                         ClientModel client,
                                         String id,
                                         String name)

      Specified by:
        `addClientRole` in interface `RealmProvider`

    - #### getRealmRole

          public RoleModel getRealmRole(RealmModel realm,
                                        String name)

      Specified by:
        `getRealmRole` in interface `RealmProvider`

    - #### getClientRole

          public RoleModel getClientRole(RealmModel realm,
                                         ClientModel client,
                                         String name)

      Specified by:
        `getClientRole` in interface `RealmProvider`

    - #### removeRole

          public boolean removeRole(RealmModel realm,
                                    RoleModel role)

      Specified by:
        `removeRole` in interface `RealmProvider`

    - #### getRoleById

          public RoleModel getRoleById(String id,
                                       RealmModel realm)

      Specified by:
        `getRoleById` in interface `RealmProvider`

    - #### getGroupById

          public GroupModel getGroupById(String id,
                                         RealmModel realm)

      Specified by:
        `getGroupById` in interface `RealmProvider`

    - #### moveGroup

          public void moveGroup(RealmModel realm,
                                GroupModel group,
                                GroupModel toParent)

      Specified by:
        `moveGroup` in interface `RealmProvider`

    - #### getGroups

          public List<GroupModel> getGroups(RealmModel realm)

      Specified by:
        `getGroups` in interface `RealmProvider`

    - #### getTopLevelGroups

          public List<GroupModel> getTopLevelGroups(RealmModel realm)

      Specified by:
        `getTopLevelGroups` in interface `RealmProvider`

    - #### removeGroup

          public boolean removeGroup(RealmModel realm,
                                     GroupModel group)

      Specified by:
        `removeGroup` in interface `RealmProvider`

    - #### createGroup

          public GroupModel createGroup(RealmModel realm,
                                        String name)

      Specified by:
        `createGroup` in interface `RealmProvider`

    - #### groupAdded

          public GroupModel groupAdded(RealmModel realm,
                                       GroupModel group)

    - #### createGroup

          public GroupModel createGroup(RealmModel realm,
                                        String id,
                                        String name)

      Specified by:
        `createGroup` in interface `RealmProvider`

    - #### addTopLevelGroup

          public void addTopLevelGroup(RealmModel realm,
                                       GroupModel subGroup)

      Specified by:
        `addTopLevelGroup` in interface `RealmProvider`

    - #### getClientById

          public ClientModel getClientById(String id,
                                           RealmModel realm)

      Specified by:
        `getClientById` in interface `RealmProvider`

    - #### getClientByClientId

          public ClientModel getClientByClientId(String clientId,
                                                 RealmModel realm)

      Specified by:
        `getClientByClientId` in interface `RealmProvider`

    - #### getClientByClientIdCacheKey

          public String getClientByClientIdCacheKey(String clientId,
                                                    RealmModel realm)

    - #### getClientTemplateById

          public ClientTemplateModel getClientTemplateById(String id,
                                                           RealmModel realm)

      Specified by:
        `getClientTemplateById` in interface `RealmProvider`

Copyright © 2016 JBoss by Red Hat. All rights reserved.