This commit is contained in:
Bill Burke 2016-02-19 17:08:45 -05:00
parent 2e64d01251
commit 1511f7088f

View file

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