Search in sources :

Example 1 with SessionEntity

use of org.keycloak.models.sessions.infinispan.entities.SessionEntity in project keycloak by keycloak.

the class RemoteCacheSessionListener method replaceRemoteEntityInCache.

protected void replaceRemoteEntityInCache(K key, long eventVersion) {
    // TODO can be optimized and remoteSession sent in the event itself?
    AtomicBoolean replaced = new AtomicBoolean(false);
    int replaceRetries = 0;
    int sleepInterval = 25;
    do {
        replaceRetries++;
        SessionEntityWrapper<V> localEntityWrapper = cache.get(key);
        VersionedValue<SessionEntityWrapper<V>> remoteSessionVersioned = remoteCache.getWithMetadata(key);
        // Probably already removed
        if (remoteSessionVersioned == null || remoteSessionVersioned.getValue() == null) {
            logger.debugf("Entity '%s' not present in remoteCache. Ignoring replace", key);
            return;
        }
        if (remoteSessionVersioned.getVersion() < eventVersion) {
            try {
                logger.debugf("Got replace remote entity event prematurely for entity '%s', will try again. Event version: %d, got: %d", key, eventVersion, remoteSessionVersioned == null ? -1 : remoteSessionVersioned.getVersion());
                // using exponential backoff
                Thread.sleep(new Random().nextInt(sleepInterval));
                continue;
            } catch (InterruptedException ex) {
                continue;
            } finally {
                sleepInterval = sleepInterval << 1;
            }
        }
        SessionEntity remoteSession = remoteSessionVersioned.getValue().getEntity();
        logger.debugf("Read session entity from the remote cache: %s . replaceRetries=%d", remoteSession, replaceRetries);
        SessionEntityWrapper<V> sessionWrapper = remoteSession.mergeRemoteEntityWithLocalEntity(localEntityWrapper);
        KeycloakModelUtils.runJobInTransaction(sessionFactory, (session -> {
            RealmModel realm = session.realms().getRealm(sessionWrapper.getEntity().getRealmId());
            long lifespanMs = lifespanMsLoader.apply(realm, sessionWrapper.getEntity());
            long maxIdleTimeMs = maxIdleTimeMsLoader.apply(realm, sessionWrapper.getEntity());
            // We received event from remoteCache, so we won't update it back
            replaced.set(cache.getAdvancedCache().withFlags(Flag.SKIP_CACHE_STORE, Flag.SKIP_CACHE_LOAD, Flag.IGNORE_RETURN_VALUES).replace(key, localEntityWrapper, sessionWrapper, lifespanMs, TimeUnit.MILLISECONDS, maxIdleTimeMs, TimeUnit.MILLISECONDS));
        }));
        if (!replaced.get()) {
            logger.debugf("Did not succeed in merging sessions, will try again: %s", remoteSession);
        }
    } while (replaceRetries < MAXIMUM_REPLACE_RETRIES && !replaced.get());
}
Also used : KeycloakModelUtils(org.keycloak.models.utils.KeycloakModelUtils) Logger(org.jboss.logging.Logger) BiFunction(java.util.function.BiFunction) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ClientEvent(org.infinispan.client.hotrod.event.ClientEvent) Random(java.util.Random) Cache(org.infinispan.Cache) RemoteCache(org.infinispan.client.hotrod.RemoteCache) ClientCacheEntryCreated(org.infinispan.client.hotrod.annotation.ClientCacheEntryCreated) ExecutorsProvider(org.keycloak.executors.ExecutorsProvider) TopologyInfo(org.keycloak.connections.infinispan.TopologyInfo) SessionEntity(org.keycloak.models.sessions.infinispan.entities.SessionEntity) ClientCacheEntryCreatedEvent(org.infinispan.client.hotrod.event.ClientCacheEntryCreatedEvent) InfinispanUtil(org.keycloak.connections.infinispan.InfinispanUtil) ExecutorService(java.util.concurrent.ExecutorService) RealmModel(org.keycloak.models.RealmModel) ClientListener(org.infinispan.client.hotrod.annotation.ClientListener) KeycloakSession(org.keycloak.models.KeycloakSession) ClientCacheEntryRemoved(org.infinispan.client.hotrod.annotation.ClientCacheEntryRemoved) SessionEntityWrapper(org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper) TimeUnit(java.util.concurrent.TimeUnit) VersionedValue(org.infinispan.client.hotrod.VersionedValue) ClientCacheEntryModified(org.infinispan.client.hotrod.annotation.ClientCacheEntryModified) Flag(org.infinispan.context.Flag) KeycloakSessionFactory(org.keycloak.models.KeycloakSessionFactory) ClientCacheEntryModifiedEvent(org.infinispan.client.hotrod.event.ClientCacheEntryModifiedEvent) ClientCacheEntryRemovedEvent(org.infinispan.client.hotrod.event.ClientCacheEntryRemovedEvent) RealmModel(org.keycloak.models.RealmModel) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Random(java.util.Random) SessionEntity(org.keycloak.models.sessions.infinispan.entities.SessionEntity) SessionEntityWrapper(org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper)

Aggregations

Random (java.util.Random)1 ExecutorService (java.util.concurrent.ExecutorService)1 TimeUnit (java.util.concurrent.TimeUnit)1 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)1 BiFunction (java.util.function.BiFunction)1 Cache (org.infinispan.Cache)1 RemoteCache (org.infinispan.client.hotrod.RemoteCache)1 VersionedValue (org.infinispan.client.hotrod.VersionedValue)1 ClientCacheEntryCreated (org.infinispan.client.hotrod.annotation.ClientCacheEntryCreated)1 ClientCacheEntryModified (org.infinispan.client.hotrod.annotation.ClientCacheEntryModified)1 ClientCacheEntryRemoved (org.infinispan.client.hotrod.annotation.ClientCacheEntryRemoved)1 ClientListener (org.infinispan.client.hotrod.annotation.ClientListener)1 ClientCacheEntryCreatedEvent (org.infinispan.client.hotrod.event.ClientCacheEntryCreatedEvent)1 ClientCacheEntryModifiedEvent (org.infinispan.client.hotrod.event.ClientCacheEntryModifiedEvent)1 ClientCacheEntryRemovedEvent (org.infinispan.client.hotrod.event.ClientCacheEntryRemovedEvent)1 ClientEvent (org.infinispan.client.hotrod.event.ClientEvent)1 Flag (org.infinispan.context.Flag)1 Logger (org.jboss.logging.Logger)1 InfinispanUtil (org.keycloak.connections.infinispan.InfinispanUtil)1 TopologyInfo (org.keycloak.connections.infinispan.TopologyInfo)1