diff --git a/distribution/demo-dist/src/main/xslt/standalone.xsl b/distribution/demo-dist/src/main/xslt/standalone.xsl
index 2b67a54715..94dd49c554 100755
--- a/distribution/demo-dist/src/main/xslt/standalone.xsl
+++ b/distribution/demo-dist/src/main/xslt/standalone.xsl
@@ -89,6 +89,7 @@
+
diff --git a/distribution/server-overlay/cli/keycloak-install-ha.cli b/distribution/server-overlay/cli/keycloak-install-ha.cli
index c120a44a62..e0ad848848 100644
--- a/distribution/server-overlay/cli/keycloak-install-ha.cli
+++ b/distribution/server-overlay/cli/keycloak-install-ha.cli
@@ -7,5 +7,8 @@ embed-server --server-config=standalone-ha.xml
/subsystem=infinispan/cache-container=keycloak/distributed-cache=sessions:add(mode="SYNC",owners="1")
/subsystem=infinispan/cache-container=keycloak/distributed-cache=offlineSessions:add(mode="SYNC",owners="1")
/subsystem=infinispan/cache-container=keycloak/distributed-cache=loginFailures:add(mode="SYNC",owners="1")
+/subsystem=infinispan/cache-container=keycloak/replicated-cache=work:add(mode="SYNC")
+/subsystem=infinispan/cache-container=keycloak/local-cache=realmVersions:add()
+/subsystem=infinispan/cache-container=keycloak/local-cache=realmVersions/transaction=TRANSACTION:add(mode=BATCH,locking=PESSIMISTIC)
/extension=org.keycloak.keycloak-server-subsystem/:add(module=org.keycloak.keycloak-server-subsystem)
/subsystem=keycloak-server:add(web-context=auth)
\ No newline at end of file
diff --git a/distribution/server-overlay/cli/keycloak-install.cli b/distribution/server-overlay/cli/keycloak-install.cli
index f068ace6d0..ce08e0a411 100644
--- a/distribution/server-overlay/cli/keycloak-install.cli
+++ b/distribution/server-overlay/cli/keycloak-install.cli
@@ -6,5 +6,8 @@ embed-server --server-config=standalone.xml
/subsystem=infinispan/cache-container=keycloak/local-cache=sessions:add()
/subsystem=infinispan/cache-container=keycloak/local-cache=offlineSessions:add()
/subsystem=infinispan/cache-container=keycloak/local-cache=loginFailures:add()
+/subsystem=infinispan/cache-container=keycloak/local-cache=work:add()
+/subsystem=infinispan/cache-container=keycloak/local-cache=realmVersions:add()
+/subsystem=infinispan/cache-container=keycloak/local-cache=realmVersions/transaction=TRANSACTION:add(mode=BATCH,locking=PESSIMISTIC)
/extension=org.keycloak.keycloak-server-subsystem/:add(module=org.keycloak.keycloak-server-subsystem)
/subsystem=keycloak-server:add(web-context=auth)
\ No newline at end of file
diff --git a/model/infinispan/src/main/java/org/keycloak/cluster/infinispan/InfinispanClusterProvider.java b/model/infinispan/src/main/java/org/keycloak/cluster/infinispan/InfinispanClusterProvider.java
index 9986dadadc..62f1adc8a0 100644
--- a/model/infinispan/src/main/java/org/keycloak/cluster/infinispan/InfinispanClusterProvider.java
+++ b/model/infinispan/src/main/java/org/keycloak/cluster/infinispan/InfinispanClusterProvider.java
@@ -34,7 +34,6 @@ import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
import org.keycloak.models.KeycloakSession;
/**
- * Various utils related to clustering
*
* @author Marek Posolda
*/
@@ -67,7 +66,7 @@ public class InfinispanClusterProvider implements ClusterProvider {
existingClusterStartTime = (Integer) cache.putIfAbsent(InfinispanClusterProvider.CLUSTER_STARTUP_TIME_KEY, serverStartTime);
if (existingClusterStartTime == null) {
- logger.infof("Initialized cluster startup time to %s", Time.toDate(serverStartTime).toString());
+ logger.debugf("Initialized cluster startup time to %s", Time.toDate(serverStartTime).toString());
return serverStartTime;
} else {
return existingClusterStartTime;
@@ -140,19 +139,26 @@ public class InfinispanClusterProvider implements ClusterProvider {
int thatTime = existingLock.getTimestamp();
int currentTime = Time.currentTime();
if (thatTime + taskTimeoutInSeconds < currentTime) {
- logger.infof("Task %s outdated when in progress by node %s. Will try to replace task with our node %s", cacheKey, existingLock.getNode(), myLock.getNode());
+ if (logger.isTraceEnabled()) {
+ logger.tracef("Task %s outdated when in progress by node %s. Will try to replace task with our node %s", cacheKey, existingLock.getNode(), myLock.getNode());
+ }
boolean replaced = cache.replace(cacheKey, existingLock, myLock);
- // TODO: trace
if (!replaced) {
- logger.infof("Failed to replace the task %s. Other thread replaced in the meantime. Ignoring task.", cacheKey);
+ if (logger.isTraceEnabled()) {
+ logger.tracef("Failed to replace the task %s. Other thread replaced in the meantime. Ignoring task.", cacheKey);
+ }
}
return replaced;
} else {
- logger.infof("Task %s in progress already by node %s. Ignoring task.", cacheKey, existingLock.getNode());
+ if (logger.isTraceEnabled()) {
+ logger.tracef("Task %s in progress already by node %s. Ignoring task.", cacheKey, existingLock.getNode());
+ }
return false;
}
} else {
- logger.infof("Successfully acquired lock for task %s. Our node is %s", cacheKey, myLock.getNode());
+ if (logger.isTraceEnabled()) {
+ logger.tracef("Successfully acquired lock for task %s. Our node is %s", cacheKey, myLock.getNode());
+ }
return true;
}
}
@@ -166,7 +172,9 @@ public class InfinispanClusterProvider implements ClusterProvider {
cache.getAdvancedCache()
.withFlags(Flag.IGNORE_RETURN_VALUES, Flag.FORCE_SYNCHRONOUS)
.remove(cacheKey);
- logger.infof("Task %s removed from the cache", cacheKey);
+ if (logger.isTraceEnabled()) {
+ logger.tracef("Task %s removed from the cache", cacheKey);
+ }
return;
} catch (RuntimeException e) {
ComponentStatus status = cache.getStatus();
diff --git a/model/infinispan/src/main/java/org/keycloak/cluster/infinispan/InfinispanClusterProviderFactory.java b/model/infinispan/src/main/java/org/keycloak/cluster/infinispan/InfinispanClusterProviderFactory.java
index 48adfe167f..dcff3d6e68 100644
--- a/model/infinispan/src/main/java/org/keycloak/cluster/infinispan/InfinispanClusterProviderFactory.java
+++ b/model/infinispan/src/main/java/org/keycloak/cluster/infinispan/InfinispanClusterProviderFactory.java
@@ -119,7 +119,7 @@ public class InfinispanClusterProviderFactory implements ClusterProviderFactory
return;
}
- logger.infof("Nodes %s removed from cluster. Removing tasks locked by this nodes", removedNodesAddresses.toString());
+ logger.debugf("Nodes %s removed from cluster. Removing tasks locked by this nodes", removedNodesAddresses.toString());
Cache cache = cacheManager.getCache(InfinispanConnectionProvider.WORK_CACHE_NAME);
@@ -146,7 +146,9 @@ public class InfinispanClusterProviderFactory implements ClusterProviderFactory
while (toRemove.hasNext()) {
String rem = toRemove.next();
- logger.infof("Removing task %s due it's node left cluster", rem);
+ if (logger.isTraceEnabled()) {
+ logger.tracef("Removing task %s due it's node left cluster", rem);
+ }
cache.remove(rem);
}
}
diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/initializer/InfinispanUserSessionInitializer.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/initializer/InfinispanUserSessionInitializer.java
index 8dd9575b2b..09bb4fc1e5 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/initializer/InfinispanUserSessionInitializer.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/initializer/InfinispanUserSessionInitializer.java
@@ -40,7 +40,7 @@ import org.keycloak.models.utils.KeycloakModelUtils;
* Startup initialization for reading persistent userSessions/clientSessions to be filled into infinispan/memory . In cluster,
* the initialization is distributed among all cluster nodes, so the startup time is even faster
*
- * TODO: Move to clusterService. Implementation is already pretty generic and doesn't contain any "userSession" specific stuff. All logic is in the SessionLoader implementation
+ * TODO: Move to clusterService. Implementation is already pretty generic and doesn't contain any "userSession" specific stuff. All sessions-specific logic is in the SessionLoader implementation
*
* @author Marek Posolda
*/
diff --git a/server-spi/src/main/java/org/keycloak/cluster/ClusterListener.java b/server-spi/src/main/java/org/keycloak/cluster/ClusterListener.java
index b29848cd14..41c65c03d5 100644
--- a/server-spi/src/main/java/org/keycloak/cluster/ClusterListener.java
+++ b/server-spi/src/main/java/org/keycloak/cluster/ClusterListener.java
@@ -17,8 +17,6 @@
package org.keycloak.cluster;
-import java.io.Serializable;
-
/**
* Task to be executed on all cluster nodes once it's notified.
*
diff --git a/server-spi/src/main/java/org/keycloak/cluster/ClusterProvider.java b/server-spi/src/main/java/org/keycloak/cluster/ClusterProvider.java
index 70b64a1f1a..498782baf4 100644
--- a/server-spi/src/main/java/org/keycloak/cluster/ClusterProvider.java
+++ b/server-spi/src/main/java/org/keycloak/cluster/ClusterProvider.java
@@ -23,12 +23,14 @@ import java.util.concurrent.Callable;
import org.keycloak.provider.Provider;
/**
+ * Various utils related to clustering and concurrent tasks on cluster nodes
+ *
* @author Marek Posolda
*/
public interface ClusterProvider extends Provider {
/**
- * Will use startup time of this server in non-cluster environment. Otherwise the value is same for all cluster nodes
+ * Same value for all cluster nodes. It will use startup time of this server in non-cluster environment.
*/
int getClusterStartupTime();
diff --git a/services/src/main/java/org/keycloak/services/managers/UsersSyncManager.java b/services/src/main/java/org/keycloak/services/managers/UsersSyncManager.java
index 2177d041c9..3f85a87546 100755
--- a/services/src/main/java/org/keycloak/services/managers/UsersSyncManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/UsersSyncManager.java
@@ -106,7 +106,7 @@ public class UsersSyncManager {
});
if (holder.result == null || !holder.result.isExecuted()) {
- logger.infof("syncAllUsers for federation provider %s was ignored as it's already in progress", fedProvider.getDisplayName());
+ logger.debugf("syncAllUsers for federation provider %s was ignored as it's already in progress", fedProvider.getDisplayName());
return UserFederationSyncResult.ignored();
} else {
return holder.result.getResult();
@@ -145,7 +145,7 @@ public class UsersSyncManager {
});
if (holder.result == null || !holder.result.isExecuted()) {
- logger.infof("syncChangedUsers for federation provider %s was ignored as it's already in progress", fedProvider.getDisplayName());
+ logger.debugf("syncChangedUsers for federation provider %s was ignored as it's already in progress", fedProvider.getDisplayName());
return UserFederationSyncResult.ignored();
} else {
return holder.result.getResult();
@@ -162,7 +162,7 @@ public class UsersSyncManager {
// Executed once it receives notification that some UserFederationProvider was created or updated
protected void refreshPeriodicSyncForProvider(final KeycloakSessionFactory sessionFactory, TimerProvider timer, final UserFederationProviderModel fedProvider, final String realmId) {
- logger.infof("Going to refresh periodic sync for provider '%s' . Full sync period: %d , changed users sync period: %d",
+ logger.debugf("Going to refresh periodic sync for provider '%s' . Full sync period: %d , changed users sync period: %d",
fedProvider.getDisplayName(), fedProvider.getFullSyncPeriod(), fedProvider.getChangedSyncPeriod());
if (fedProvider.getFullSyncPeriod() > 0) {
@@ -176,7 +176,7 @@ public class UsersSyncManager {
if (shouldPerformSync) {
syncAllUsers(sessionFactory, realmId, fedProvider);
} else {
- logger.infof("Ignored periodic full sync with federation provider %s due small time since last sync", fedProvider.getDisplayName());
+ logger.debugf("Ignored periodic full sync with federation provider %s due small time since last sync", fedProvider.getDisplayName());
}
} catch (Throwable t) {
logger.errorDuringFullUserSync(t);
@@ -199,7 +199,7 @@ public class UsersSyncManager {
if (shouldPerformSync) {
syncChangedUsers(sessionFactory, realmId, fedProvider);
} else {
- logger.infof("Ignored periodic changed-users sync with federation provider %s due small time since last sync", fedProvider.getDisplayName());
+ logger.debugf("Ignored periodic changed-users sync with federation provider %s due small time since last sync", fedProvider.getDisplayName());
}
} catch (Throwable t) {
logger.errorDuringChangedUserSync(t);
@@ -227,7 +227,7 @@ public class UsersSyncManager {
// Executed once it receives notification that some UserFederationProvider was removed
protected void removePeriodicSyncForProvider(TimerProvider timer, UserFederationProviderModel fedProvider) {
- logger.infof("Removing periodic sync for provider %s", fedProvider.getDisplayName());
+ logger.debugf("Removing periodic sync for provider %s", fedProvider.getDisplayName());
timer.cancelTask(fedProvider.getId() + "-FULL");
timer.cancelTask(fedProvider.getId() + "-CHANGED");
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionInitializerTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionInitializerTest.java
index d224b3ecdc..15dd9dc132 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionInitializerTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionInitializerTest.java
@@ -100,7 +100,7 @@ public class UserSessionInitializerTest {
// Clear ispn cache to ensure initializerState is removed as well
InfinispanConnectionProvider infinispan = session.getProvider(InfinispanConnectionProvider.class);
- infinispan.getCache(InfinispanConnectionProvider.OFFLINE_SESSION_CACHE_NAME).clear();
+ infinispan.getCache(InfinispanConnectionProvider.WORK_CACHE_NAME).clear();
resetSession();
diff --git a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakServerDeploymentProcessor.java b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakServerDeploymentProcessor.java
index 1d2230c9fe..8b4840a324 100755
--- a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakServerDeploymentProcessor.java
+++ b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakServerDeploymentProcessor.java
@@ -62,6 +62,7 @@ public class KeycloakServerDeploymentProcessor implements DeploymentUnitProcesso
st.addDependency(cacheContainerService.append("sessions"));
st.addDependency(cacheContainerService.append("offlineSessions"));
st.addDependency(cacheContainerService.append("loginFailures"));
+ st.addDependency(cacheContainerService.append("work"));
st.addDependency(cacheContainerService.append("realmVersions"));
}
}
diff --git a/wildfly/server-subsystem/src/main/resources/subsystem-templates/keycloak-infinispan.xml b/wildfly/server-subsystem/src/main/resources/subsystem-templates/keycloak-infinispan.xml
index 74fbae372e..79f741a832 100755
--- a/wildfly/server-subsystem/src/main/resources/subsystem-templates/keycloak-infinispan.xml
+++ b/wildfly/server-subsystem/src/main/resources/subsystem-templates/keycloak-infinispan.xml
@@ -30,6 +30,7 @@
+
@@ -90,6 +91,7 @@
+