keycloak-memoizeit

javadoc

2/19/2016 8:08:45 PM

Details

diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/StreamCacheRealmProvider.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/StreamCacheRealmProvider.java
index d21599c..0a50575 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/StreamCacheRealmProvider.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/StreamCacheRealmProvider.java
@@ -49,6 +49,50 @@ import java.util.Set;
 
 
 /**
+ * - 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.
+ * - At prepare phase of the transaction, a local lock on the revision cache will be obtained for each object marked for invalidation
+ * we sort the list of these keys to order local acquisition and avoid deadlocks.
+ * - 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 clientListInvalidations 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.
+ *
+ * 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