org.keycloak.models.cache.infinispan

## Class CacheManager

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

- Direct Known Subclasses:
    RealmCacheManager, StoreFactoryCacheManager, UserCacheManager

      public abstract class CacheManager
      extends Object

  Some notes on how this works: This implementation manages optimistic locking and version checks itself. The reason is Infinispan just does behave the way we need it to. Not saying Infinispan is bad, just that we have specific caching requirements! This is an invalidation cache implementation and requires to caches: Cache 1 is an Invalidation Cache Cache 2 is a local-only revision number cache. Each node in the cluster maintains its own revision number cache for each entry in the main invalidation cache. This revision cache holds the version counter for each cached entity. Cache listeners do not receive a @CacheEntryInvalidated event if that node does not have an entry for that item. So, consider the following. 1. Node 1 gets current counter for user. There currently isn't one as this user isn't cached. 2. Node 1 reads user from DB 3. Node 2 updates user 4. Node 2 calls cache.remove(user). This does not result in an invalidation listener event to node 1! 5. node 1 checks version counter, checks pass. Stale entry is cached. The issue is that Node 1 doesn't have an entry for the user, so it never receives an invalidation listener event from Node 2 thus it can't bump the version. So, when node 1 goes to cache the user it is stale as the version number was never bumped. So how is this issue fixed? here is pseudo code: 1. Node 1 calls cacheManager.getCurrentRevision() to get the current local version counter of that User 2. Node 1 getCurrentRevision() pulls current counter for that user 3. Node 1 getCurrentRevision() adds a "invalidation.key.userid" to invalidation cache. Its just a marker. nothing else 4. Node 2 update user 5. Node 2 does a cache.remove(user) cache.remove(invalidation.key.userid) 6. Node 1 receives invalidation event for invalidation.key.userid. Bumps the version counter for that user 7. node 1 version check fails, it doesn't cache the user
  Version:
    $Revision: 1 $
  Author:
    Bill Burke

- - ### Field Summary

    Fields
    Modifier and Type | Field and Description
    --- | ---
    `protected org.infinispan.Cache<String,Revisioned>` | `cache`
    `protected UpdateCounter` | `counter`
    `protected org.infinispan.Cache<String,Long>` | `revisions`

  - ### Constructor Summary

    Constructors
    Constructor and Description
    `CacheManager(org.infinispan.Cache<String,Revisioned> cache, org.infinispan.Cache<String,Long> revisions)`

  - ### Method Summary

    All Methods Instance Methods Abstract Methods Concrete Methods
    Modifier and Type | Method and Description
    --- | ---
    `void` | `addInvalidations(Predicate<Map.Entry<String,Revisioned>> predicate, Set<String> invalidations)`
    `protected abstract void` | `addInvalidationsFromEvent(InvalidationEvent event, Set<String> invalidations)`
    `void` | `addRevisioned(Revisioned object, long startupRevision)`
    `void` | `addRevisioned(Revisioned object, long startupRevision, long lifespan)`
    `protected void` | `bumpVersion(String id)`
    `void` | `clear()`
    `void` | `endRevisionBatch()`
    `<T extends Revisioned> T` | `get(String id, Class<T> type)`
    `org.infinispan.Cache<String,Revisioned>` | `getCache()`
    `long` | `getCurrentCounter()`
    `Long` | `getCurrentRevision(String id)`
    `protected abstract org.jboss.logging.Logger` | `getLogger()`
    `Object` | `invalidateObject(String id)`
    `void` | `invalidationEventReceived(InvalidationEvent event)`
    `void` | `sendInvalidationEvents(KeycloakSession session, Collection<InvalidationEvent> invalidationEvents, String eventKey)`

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

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

- - ### Field Detail

    - #### revisions

          protected final org.infinispan.Cache<String,Long> revisions

    - #### cache

          protected final org.infinispan.Cache<String,Revisioned> cache

    - #### counter

          protected final UpdateCounter counter

  - ### Constructor Detail

    - #### CacheManager

          public CacheManager(org.infinispan.Cache<String,Revisioned> cache,
                              org.infinispan.Cache<String,Long> revisions)

  - ### Method Detail

    - #### getLogger

          protected abstract org.jboss.logging.Logger getLogger()

    - #### getCache

          public org.infinispan.Cache<String,Revisioned> getCache()

    - #### getCurrentCounter

          public long getCurrentCounter()

    - #### getCurrentRevision

          public Long getCurrentRevision(String id)

    - #### endRevisionBatch

          public void endRevisionBatch()

    - #### get

          public <T extends Revisioned> T get(String id,
                                              Class<T> type)

    - #### invalidateObject

          public Object invalidateObject(String id)

    - #### bumpVersion

          protected void bumpVersion(String id)

    - #### addRevisioned

          public void addRevisioned(Revisioned object,
                                    long startupRevision)

    - #### addRevisioned

          public void addRevisioned(Revisioned object,
                                    long startupRevision,
                                    long lifespan)

    - #### clear

          public void clear()

    - #### addInvalidations

          public void addInvalidations(Predicate<Map.Entry<String,Revisioned>> predicate,
                                       Set<String> invalidations)

    - #### sendInvalidationEvents

          public void sendInvalidationEvents(KeycloakSession session,
                                             Collection<InvalidationEvent> invalidationEvents,
                                             String eventKey)

    - #### invalidationEventReceived

          public void invalidationEventReceived(InvalidationEvent event)

    - #### addInvalidationsFromEvent

          protected abstract void addInvalidationsFromEvent(InvalidationEvent event,
                                                            Set<String> invalidations)

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