Infinispan 15.0.3.Final
Closes #29068 Signed-off-by: Pedro Ruivo <pruivo@redhat.com>
This commit is contained in:
parent
8ff1ae0c08
commit
cbce548e71
32 changed files with 170 additions and 303 deletions
|
@ -92,16 +92,12 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.infinispan</groupId>
|
<groupId>org.infinispan</groupId>
|
||||||
<artifactId>infinispan-core-jakarta</artifactId>
|
<artifactId>infinispan-core</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.infinispan</groupId>
|
<groupId>org.infinispan</groupId>
|
||||||
<artifactId>infinispan-cachestore-remote</artifactId>
|
<artifactId>infinispan-cachestore-remote</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.infinispan</groupId>
|
|
||||||
<artifactId>infinispan-client-hotrod-jakarta</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
|
|
|
@ -88,11 +88,6 @@
|
||||||
<groupId>org.infinispan</groupId>
|
<groupId>org.infinispan</groupId>
|
||||||
<artifactId>infinispan-cachestore-remote</artifactId>
|
<artifactId>infinispan-cachestore-remote</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<!-- adding it explictly, as Keycloak's parent excludes it to have full control over Jakarta EE vs. Java EE -->
|
|
||||||
<groupId>org.infinispan</groupId>
|
|
||||||
<artifactId>infinispan-client-hotrod</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
|
|
|
@ -16,6 +16,14 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.adapters.saml.elytron.infinispan;
|
package org.keycloak.adapters.saml.elytron.infinispan;
|
||||||
|
|
||||||
|
import org.infinispan.Cache;
|
||||||
|
import org.infinispan.configuration.cache.CacheMode;
|
||||||
|
import org.infinispan.configuration.cache.Configuration;
|
||||||
|
import org.infinispan.factories.ComponentRegistry;
|
||||||
|
import org.infinispan.manager.EmbeddedCacheManager;
|
||||||
|
import org.infinispan.persistence.manager.PersistenceManager;
|
||||||
|
import org.infinispan.persistence.remote.RemoteStore;
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.adapters.saml.AdapterConstants;
|
import org.keycloak.adapters.saml.AdapterConstants;
|
||||||
import org.keycloak.adapters.spi.SessionIdMapper;
|
import org.keycloak.adapters.spi.SessionIdMapper;
|
||||||
import org.keycloak.adapters.spi.SessionIdMapperUpdater;
|
import org.keycloak.adapters.spi.SessionIdMapperUpdater;
|
||||||
|
@ -23,14 +31,6 @@ import org.keycloak.adapters.spi.SessionIdMapperUpdater;
|
||||||
import javax.naming.InitialContext;
|
import javax.naming.InitialContext;
|
||||||
import javax.naming.NamingException;
|
import javax.naming.NamingException;
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
import org.infinispan.Cache;
|
|
||||||
import org.infinispan.configuration.cache.CacheMode;
|
|
||||||
import org.infinispan.configuration.cache.Configuration;
|
|
||||||
import org.infinispan.manager.EmbeddedCacheManager;
|
|
||||||
import org.infinispan.persistence.manager.PersistenceManager;
|
|
||||||
import org.infinispan.persistence.remote.RemoteStore;
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -94,21 +94,19 @@ public class InfinispanSessionCacheIdMapperUpdater {
|
||||||
}
|
}
|
||||||
|
|
||||||
Cache<String, String[]> ssoCache = cacheManager.getCache(cacheName, true);
|
Cache<String, String[]> ssoCache = cacheManager.getCache(cacheName, true);
|
||||||
final SsoSessionCacheListener listener = new SsoSessionCacheListener(ssoCache, mapper);
|
SsoSessionCacheListener listener = new SsoSessionCacheListener(ssoCache, mapper);
|
||||||
ssoCache.addListener(listener);
|
ssoCache.addListener(listener);
|
||||||
|
|
||||||
addSsoCacheCrossDcListener(ssoCache, listener);
|
addSsoCacheCrossDcListener(ssoCache, listener);
|
||||||
|
|
||||||
LOG.debugv("Added distributed SSO session cache, lookup={0}, cache name={1}", cacheContainerLookup, cacheName);
|
LOG.debugv("Added distributed SSO session cache, lookup={0}, cache name={1}", cacheContainerLookup, cacheName);
|
||||||
|
|
||||||
SsoCacheSessionIdMapperUpdater updater = new SsoCacheSessionIdMapperUpdater(ssoCache, previousIdMapperUpdater) {
|
return new SsoCacheSessionIdMapperUpdater(ssoCache, previousIdMapperUpdater) {
|
||||||
@Override
|
@Override
|
||||||
public void close() throws Exception {
|
public void close() {
|
||||||
ssoCache.stop();
|
ssoCache.stop();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return updater;
|
|
||||||
} catch (NamingException ex) {
|
} catch (NamingException ex) {
|
||||||
LOG.warnv("Failed to obtain distributed session cache container, lookup={0}", cacheContainerLookup);
|
LOG.warnv("Failed to obtain distributed session cache container, lookup={0}", cacheContainerLookup);
|
||||||
return previousIdMapperUpdater;
|
return previousIdMapperUpdater;
|
||||||
|
@ -137,7 +135,7 @@ public class InfinispanSessionCacheIdMapperUpdater {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Set<RemoteStore> stores = getRemoteStores(ssoCache);
|
Set<RemoteStore> stores = getRemoteStores(ssoCache);
|
||||||
if (stores == null || stores.isEmpty()) {
|
if (stores == null || stores.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -149,7 +147,7 @@ public class InfinispanSessionCacheIdMapperUpdater {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Set<RemoteStore> getRemoteStores(Cache ispnCache) {
|
public static Set<RemoteStore> getRemoteStores(Cache<?, ?> ispnCache) {
|
||||||
return ispnCache.getAdvancedCache().getComponentRegistry().getComponent(PersistenceManager.class).getStores(RemoteStore.class);
|
return ComponentRegistry.componentOf(ispnCache, PersistenceManager.class).getStores(RemoteStore.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -224,7 +224,7 @@ spec:
|
||||||
expose:
|
expose:
|
||||||
type: Route
|
type: Route
|
||||||
configMapName: "cluster-config"
|
configMapName: "cluster-config"
|
||||||
image: quay.io/infinispan/server:14.0.27.Final
|
image: quay.io/infinispan/server:15.0.3.Final
|
||||||
configListener:
|
configListener:
|
||||||
enabled: false
|
enabled: false
|
||||||
container:
|
container:
|
||||||
|
|
|
@ -363,7 +363,7 @@ spec:
|
||||||
expose:
|
expose:
|
||||||
type: Route
|
type: Route
|
||||||
configMapName: "cluster-config"
|
configMapName: "cluster-config"
|
||||||
image: quay.io/infinispan/server:14.0.27.Final
|
image: quay.io/infinispan/server:15.0.3.Final
|
||||||
configListener:
|
configListener:
|
||||||
enabled: false
|
enabled: false
|
||||||
container:
|
container:
|
||||||
|
|
|
@ -363,7 +363,7 @@ spec:
|
||||||
expose:
|
expose:
|
||||||
type: Route
|
type: Route
|
||||||
configMapName: "cluster-config"
|
configMapName: "cluster-config"
|
||||||
image: quay.io/infinispan/server:14.0.27.Final
|
image: quay.io/infinispan/server:15.0.3.Final
|
||||||
configListener:
|
configListener:
|
||||||
enabled: false
|
enabled: false
|
||||||
container:
|
container:
|
||||||
|
|
|
@ -59,11 +59,7 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.infinispan</groupId>
|
<groupId>org.infinispan</groupId>
|
||||||
<artifactId>infinispan-core-jakarta</artifactId>
|
<artifactId>infinispan-core</artifactId>
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.infinispan</groupId>
|
|
||||||
<artifactId>infinispan-client-hotrod-jakarta</artifactId>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.infinispan</groupId>
|
<groupId>org.infinispan</groupId>
|
||||||
|
|
|
@ -20,13 +20,11 @@ package org.keycloak.cluster.infinispan;
|
||||||
import org.infinispan.Cache;
|
import org.infinispan.Cache;
|
||||||
import org.infinispan.client.hotrod.exceptions.HotRodClientException;
|
import org.infinispan.client.hotrod.exceptions.HotRodClientException;
|
||||||
import org.infinispan.lifecycle.ComponentStatus;
|
import org.infinispan.lifecycle.ComponentStatus;
|
||||||
import org.infinispan.manager.EmbeddedCacheManager;
|
|
||||||
import org.infinispan.notifications.Listener;
|
import org.infinispan.notifications.Listener;
|
||||||
import org.infinispan.notifications.cachemanagerlistener.annotation.ViewChanged;
|
import org.infinispan.notifications.cachemanagerlistener.annotation.ViewChanged;
|
||||||
import org.infinispan.notifications.cachemanagerlistener.event.ViewChangedEvent;
|
import org.infinispan.notifications.cachemanagerlistener.event.ViewChangedEvent;
|
||||||
import org.infinispan.persistence.remote.RemoteStore;
|
import org.infinispan.persistence.remote.RemoteStore;
|
||||||
import org.infinispan.remoting.transport.Address;
|
import org.infinispan.remoting.transport.Address;
|
||||||
import org.infinispan.remoting.transport.Transport;
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.Config;
|
import org.keycloak.Config;
|
||||||
import org.keycloak.cluster.ClusterProvider;
|
import org.keycloak.cluster.ClusterProvider;
|
||||||
|
@ -35,10 +33,10 @@ import org.keycloak.common.util.Retry;
|
||||||
import org.keycloak.common.util.Time;
|
import org.keycloak.common.util.Time;
|
||||||
import org.keycloak.connections.infinispan.DefaultInfinispanConnectionProviderFactory;
|
import org.keycloak.connections.infinispan.DefaultInfinispanConnectionProviderFactory;
|
||||||
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
|
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
|
||||||
|
import org.keycloak.connections.infinispan.InfinispanUtil;
|
||||||
import org.keycloak.connections.infinispan.TopologyInfo;
|
import org.keycloak.connections.infinispan.TopologyInfo;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
import org.keycloak.connections.infinispan.InfinispanUtil;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
@ -47,7 +45,6 @@ import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -72,7 +69,7 @@ public class InfinispanClusterProviderFactory implements ClusterProviderFactory
|
||||||
// Just to extract notifications related stuff to separate class
|
// Just to extract notifications related stuff to separate class
|
||||||
private InfinispanNotificationsManager notificationsManager;
|
private InfinispanNotificationsManager notificationsManager;
|
||||||
|
|
||||||
private ExecutorService localExecutor = Executors.newCachedThreadPool(r -> {
|
private final ExecutorService localExecutor = Executors.newCachedThreadPool(r -> {
|
||||||
Thread thread = Executors.defaultThreadFactory().newThread(r);
|
Thread thread = Executors.defaultThreadFactory().newThread(r);
|
||||||
thread.setName(this.getClass().getName() + "-" + thread.getName());
|
thread.setName(this.getClass().getName() + "-" + thread.getName());
|
||||||
return thread;
|
return thread;
|
||||||
|
@ -140,7 +137,7 @@ public class InfinispanClusterProviderFactory implements ClusterProviderFactory
|
||||||
static <V extends Serializable> V putIfAbsentWithRetries(CrossDCAwareCacheFactory crossDCAwareCacheFactory, String key, V value, int taskTimeoutInSeconds) {
|
static <V extends Serializable> V putIfAbsentWithRetries(CrossDCAwareCacheFactory crossDCAwareCacheFactory, String key, V value, int taskTimeoutInSeconds) {
|
||||||
AtomicReference<V> resultRef = new AtomicReference<>();
|
AtomicReference<V> resultRef = new AtomicReference<>();
|
||||||
|
|
||||||
Retry.executeWithBackoff((int iteration) -> {
|
Retry.executeWithBackoff(iteration -> {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
V result;
|
V result;
|
||||||
|
@ -196,17 +193,14 @@ public class InfinispanClusterProviderFactory implements ClusterProviderFactory
|
||||||
|
|
||||||
@ViewChanged
|
@ViewChanged
|
||||||
public void viewChanged(ViewChangedEvent event) {
|
public void viewChanged(ViewChangedEvent event) {
|
||||||
final Set<String> removedNodesAddresses = convertAddresses(event.getOldMembers());
|
Set<String> removedNodesAddresses = convertAddresses(event.getOldMembers());
|
||||||
final Set<String> newAddresses = convertAddresses(event.getNewMembers());
|
Set<String> newAddresses = convertAddresses(event.getNewMembers());
|
||||||
|
|
||||||
// Use separate thread to avoid potential deadlock
|
// Use separate thread to avoid potential deadlock
|
||||||
localExecutor.execute(() -> {
|
localExecutor.execute(() -> {
|
||||||
try {
|
try {
|
||||||
EmbeddedCacheManager cacheManager = workCache.getCacheManager();
|
|
||||||
Transport transport = cacheManager.getTransport();
|
|
||||||
|
|
||||||
// Coordinator makes sure that entries for outdated nodes are cleaned up
|
// Coordinator makes sure that entries for outdated nodes are cleaned up
|
||||||
if (transport != null && transport.isCoordinator()) {
|
if (workCache.getCacheManager().isCoordinator()) {
|
||||||
|
|
||||||
removedNodesAddresses.removeAll(newAddresses);
|
removedNodesAddresses.removeAll(newAddresses);
|
||||||
|
|
||||||
|
@ -230,14 +224,7 @@ public class InfinispanClusterProviderFactory implements ClusterProviderFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<String> convertAddresses(Collection<Address> addresses) {
|
private Set<String> convertAddresses(Collection<Address> addresses) {
|
||||||
return addresses.stream().map(new Function<Address, String>() {
|
return addresses.stream().map(Object::toString).collect(Collectors.toSet());
|
||||||
|
|
||||||
@Override
|
|
||||||
public String apply(Address address) {
|
|
||||||
return address.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}).collect(Collectors.toSet());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
package org.keycloak.connections.infinispan;
|
package org.keycloak.connections.infinispan;
|
||||||
|
|
||||||
import org.infinispan.Cache;
|
import org.infinispan.Cache;
|
||||||
|
import org.infinispan.factories.ComponentRegistry;
|
||||||
import org.infinispan.persistence.manager.PersistenceManager;
|
import org.infinispan.persistence.manager.PersistenceManager;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.health.LoadBalancerCheckProvider;
|
import org.keycloak.health.LoadBalancerCheckProvider;
|
||||||
|
@ -60,9 +61,7 @@ public class InfinispanMultiSiteLoadBalancerCheckProvider implements LoadBalance
|
||||||
return true; // no need to check other caches
|
return true; // no need to check other caches
|
||||||
}
|
}
|
||||||
|
|
||||||
PersistenceManager persistenceManager = cache.getAdvancedCache()
|
var persistenceManager = ComponentRegistry.componentOf(cache, PersistenceManager.class);
|
||||||
.getComponentRegistry()
|
|
||||||
.getComponent(PersistenceManager.class);
|
|
||||||
|
|
||||||
if (persistenceManager != null && !persistenceManager.isAvailable()) {
|
if (persistenceManager != null && !persistenceManager.isAvailable()) {
|
||||||
LOG.debugf("PersistenceManager for cache '%s' is down.", cacheName);
|
LOG.debugf("PersistenceManager for cache '%s' is down.", cacheName);
|
||||||
|
|
|
@ -17,11 +17,6 @@
|
||||||
|
|
||||||
package org.keycloak.connections.infinispan;
|
package org.keycloak.connections.infinispan;
|
||||||
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
|
|
||||||
import org.infinispan.Cache;
|
import org.infinispan.Cache;
|
||||||
import org.infinispan.client.hotrod.ProtocolVersion;
|
import org.infinispan.client.hotrod.ProtocolVersion;
|
||||||
import org.infinispan.client.hotrod.RemoteCache;
|
import org.infinispan.client.hotrod.RemoteCache;
|
||||||
|
@ -34,7 +29,7 @@ import org.infinispan.configuration.cache.ConfigurationBuilder;
|
||||||
import org.infinispan.configuration.global.GlobalConfigurationBuilder;
|
import org.infinispan.configuration.global.GlobalConfigurationBuilder;
|
||||||
import org.infinispan.configuration.global.TransportConfigurationBuilder;
|
import org.infinispan.configuration.global.TransportConfigurationBuilder;
|
||||||
import org.infinispan.eviction.EvictionStrategy;
|
import org.infinispan.eviction.EvictionStrategy;
|
||||||
import org.infinispan.eviction.EvictionType;
|
import org.infinispan.factories.ComponentRegistry;
|
||||||
import org.infinispan.factories.GlobalComponentRegistry;
|
import org.infinispan.factories.GlobalComponentRegistry;
|
||||||
import org.infinispan.factories.impl.BasicComponentRegistry;
|
import org.infinispan.factories.impl.BasicComponentRegistry;
|
||||||
import org.infinispan.factories.impl.ComponentRef;
|
import org.infinispan.factories.impl.ComponentRef;
|
||||||
|
@ -48,6 +43,11 @@ import org.jgroups.JChannel;
|
||||||
import org.keycloak.common.util.Time;
|
import org.keycloak.common.util.Time;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
|
@ -58,12 +58,12 @@ public class InfinispanUtil {
|
||||||
public static final int MAXIMUM_REPLACE_RETRIES = 25;
|
public static final int MAXIMUM_REPLACE_RETRIES = 25;
|
||||||
|
|
||||||
// See if we have RemoteStore (external JDG) configured for cross-Data-Center scenario
|
// See if we have RemoteStore (external JDG) configured for cross-Data-Center scenario
|
||||||
public static Set<RemoteStore> getRemoteStores(Cache ispnCache) {
|
public static Set<RemoteStore> getRemoteStores(Cache<?, ?> ispnCache) {
|
||||||
return ispnCache.getAdvancedCache().getComponentRegistry().getComponent(PersistenceManager.class).getStores(RemoteStore.class);
|
return ComponentRegistry.componentOf(ispnCache, PersistenceManager.class).getStores(RemoteStore.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static RemoteCache getRemoteCache(Cache ispnCache) {
|
public static RemoteCache getRemoteCache(Cache<?, ?> ispnCache) {
|
||||||
Set<RemoteStore> remoteStores = getRemoteStores(ispnCache);
|
Set<RemoteStore> remoteStores = getRemoteStores(ispnCache);
|
||||||
if (remoteStores.isEmpty()) {
|
if (remoteStores.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -88,10 +88,9 @@ public class InfinispanUtil {
|
||||||
* @param lifespanOrigMs
|
* @param lifespanOrigMs
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static long toHotrodTimeMs(BasicCache ispnCache, long lifespanOrigMs) {
|
public static long toHotrodTimeMs(BasicCache<?, ?> ispnCache, long lifespanOrigMs) {
|
||||||
if (ispnCache instanceof RemoteCache && lifespanOrigMs > 2592000000L) {
|
if (ispnCache instanceof RemoteCache<?, ?> remoteCache && lifespanOrigMs > 2592000000L) {
|
||||||
RemoteCache remoteCache = (RemoteCache) ispnCache;
|
ProtocolVersion protocolVersion = remoteCache.getRemoteCacheContainer().getConfiguration().version();
|
||||||
ProtocolVersion protocolVersion = remoteCache.getRemoteCacheManager().getConfiguration().version();
|
|
||||||
if (ProtocolVersion.PROTOCOL_VERSION_30.compareTo(protocolVersion) > 0) {
|
if (ProtocolVersion.PROTOCOL_VERSION_30.compareTo(protocolVersion) > 0) {
|
||||||
return Time.currentTimeMillis() + lifespanOrigMs;
|
return Time.currentTimeMillis() + lifespanOrigMs;
|
||||||
}
|
}
|
||||||
|
@ -103,7 +102,7 @@ public class InfinispanUtil {
|
||||||
private static final Object CHANNEL_INIT_SYNCHRONIZER = new Object();
|
private static final Object CHANNEL_INIT_SYNCHRONIZER = new Object();
|
||||||
|
|
||||||
public static void configureTransport(GlobalConfigurationBuilder gcb, String nodeName, String siteName, String jgroupsUdpMcastAddr,
|
public static void configureTransport(GlobalConfigurationBuilder gcb, String nodeName, String siteName, String jgroupsUdpMcastAddr,
|
||||||
String jgroupsConfigPath) {
|
String jgroupsConfigPath) {
|
||||||
if (nodeName == null) {
|
if (nodeName == null) {
|
||||||
gcb.transport().defaultTransport();
|
gcb.transport().defaultTransport();
|
||||||
} else {
|
} else {
|
||||||
|
@ -166,9 +165,8 @@ public class InfinispanUtil {
|
||||||
ConfigurationBuilder cb = createCacheConfigurationBuilder();
|
ConfigurationBuilder cb = createCacheConfigurationBuilder();
|
||||||
|
|
||||||
cb.memory()
|
cb.memory()
|
||||||
.evictionStrategy(EvictionStrategy.NONE)
|
.whenFull(EvictionStrategy.MANUAL)
|
||||||
.evictionType(EvictionType.COUNT)
|
.maxCount(InfinispanConnectionProvider.ACTION_TOKEN_CACHE_DEFAULT_MAX);
|
||||||
.size(InfinispanConnectionProvider.ACTION_TOKEN_CACHE_DEFAULT_MAX);
|
|
||||||
cb.expiration()
|
cb.expiration()
|
||||||
.maxIdle(InfinispanConnectionProvider.ACTION_TOKEN_MAX_IDLE_SECONDS, TimeUnit.SECONDS)
|
.maxIdle(InfinispanConnectionProvider.ACTION_TOKEN_MAX_IDLE_SECONDS, TimeUnit.SECONDS)
|
||||||
.wakeUpInterval(InfinispanConnectionProvider.ACTION_TOKEN_WAKE_UP_INTERVAL_SECONDS, TimeUnit.SECONDS);
|
.wakeUpInterval(InfinispanConnectionProvider.ACTION_TOKEN_WAKE_UP_INTERVAL_SECONDS, TimeUnit.SECONDS);
|
||||||
|
@ -209,7 +207,7 @@ public class InfinispanUtil {
|
||||||
* @return the original component that was replaced
|
* @return the original component that was replaced
|
||||||
*/
|
*/
|
||||||
private static <T> T replaceComponent(EmbeddedCacheManager cacheMgr, Class<T> componentType, T replacementComponent, boolean rewire) {
|
private static <T> T replaceComponent(EmbeddedCacheManager cacheMgr, Class<T> componentType, T replacementComponent, boolean rewire) {
|
||||||
GlobalComponentRegistry cr = cacheMgr.getGlobalComponentRegistry();
|
GlobalComponentRegistry cr = GlobalComponentRegistry.of(cacheMgr);
|
||||||
BasicComponentRegistry bcr = cr.getComponent(BasicComponentRegistry.class);
|
BasicComponentRegistry bcr = cr.getComponent(BasicComponentRegistry.class);
|
||||||
ComponentRef<T> old = bcr.getComponent(componentType);
|
ComponentRef<T> old = bcr.getComponent(componentType);
|
||||||
bcr.replaceComponent(componentType.getName(), replacementComponent, true);
|
bcr.replaceComponent(componentType.getName(), replacementComponent, true);
|
||||||
|
|
|
@ -17,12 +17,9 @@
|
||||||
|
|
||||||
package org.keycloak.connections.infinispan;
|
package org.keycloak.connections.infinispan;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.security.SecureRandom;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import org.infinispan.Cache;
|
import org.infinispan.Cache;
|
||||||
import org.infinispan.distribution.DistributionManager;
|
import org.infinispan.distribution.DistributionManager;
|
||||||
|
import org.infinispan.factories.GlobalComponentRegistry;
|
||||||
import org.infinispan.manager.EmbeddedCacheManager;
|
import org.infinispan.manager.EmbeddedCacheManager;
|
||||||
import org.infinispan.remoting.transport.Address;
|
import org.infinispan.remoting.transport.Address;
|
||||||
import org.infinispan.remoting.transport.LocalModeAddress;
|
import org.infinispan.remoting.transport.LocalModeAddress;
|
||||||
|
@ -30,12 +27,14 @@ import org.infinispan.remoting.transport.Transport;
|
||||||
import org.infinispan.remoting.transport.jgroups.JGroupsAddress;
|
import org.infinispan.remoting.transport.jgroups.JGroupsAddress;
|
||||||
import org.infinispan.remoting.transport.jgroups.JGroupsTransport;
|
import org.infinispan.remoting.transport.jgroups.JGroupsTransport;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jgroups.Event;
|
|
||||||
import org.jgroups.JChannel;
|
|
||||||
import org.jgroups.stack.IpAddress;
|
import org.jgroups.stack.IpAddress;
|
||||||
import org.jgroups.util.NameCache;
|
import org.jgroups.util.NameCache;
|
||||||
import org.keycloak.Config;
|
import org.keycloak.Config;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
|
@ -66,9 +65,9 @@ public class TopologyInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!embedded) {
|
if (!embedded) {
|
||||||
Transport transport = cacheManager.getTransport();
|
var addr = cacheManager.getAddress();
|
||||||
if (transport != null) {
|
if (addr != null) {
|
||||||
nodeName = transport.getAddress().toString();
|
nodeName = addr.toString();
|
||||||
siteName = cacheManager.getCacheManagerConfiguration().transport().siteId();
|
siteName = cacheManager.getCacheManagerConfiguration().transport().siteId();
|
||||||
if (siteName == null) {
|
if (siteName == null) {
|
||||||
siteName = config.get("siteName");
|
siteName = config.get("siteName");
|
||||||
|
@ -133,7 +132,7 @@ public class TopologyInfo {
|
||||||
/**
|
/**
|
||||||
* True if I am primary owner of the key in case of distributed caches. In case of local caches, always return true
|
* True if I am primary owner of the key in case of distributed caches. In case of local caches, always return true
|
||||||
*/
|
*/
|
||||||
public boolean amIOwner(Cache cache, Object key) {
|
public boolean amIOwner(Cache<?, ?> cache, Object key) {
|
||||||
Address myAddress = cache.getCacheManager().getAddress();
|
Address myAddress = cache.getCacheManager().getAddress();
|
||||||
Address objectOwnerAddress = getOwnerAddress(cache, key);
|
Address objectOwnerAddress = getOwnerAddress(cache, key);
|
||||||
|
|
||||||
|
@ -145,7 +144,7 @@ public class TopologyInfo {
|
||||||
/**
|
/**
|
||||||
* Get route to be used as the identifier for sticky session. Return null if I am not able to find the appropriate route (or in case of local mode)
|
* Get route to be used as the identifier for sticky session. Return null if I am not able to find the appropriate route (or in case of local mode)
|
||||||
*/
|
*/
|
||||||
public String getRouteName(Cache cache, Object key) {
|
public String getRouteName(Cache<?, ?> cache, Object key) {
|
||||||
if (cache.getCacheConfiguration().clustering().cacheMode().isClustered() && isGeneratedNodeName) {
|
if (cache.getCacheConfiguration().clustering().cacheMode().isClustered() && isGeneratedNodeName) {
|
||||||
logger.warn("Clustered configuration used, but node name is not properly set. Make sure to start server with jboss.node.name property identifying cluster node");
|
logger.warn("Clustered configuration used, but node name is not properly set. Make sure to start server with jboss.node.name property identifying cluster node");
|
||||||
}
|
}
|
||||||
|
@ -168,11 +167,11 @@ public class TopologyInfo {
|
||||||
// If no logical name exists, create one using physical address
|
// If no logical name exists, create one using physical address
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
|
|
||||||
Transport transport = cache.getCacheManager().getTransport();
|
var transport = GlobalComponentRegistry.componentOf(cache.getCacheManager(), Transport.class);
|
||||||
JChannel jgroupsChannel = ((JGroupsTransport) transport).getChannel();
|
var channel = ((JGroupsTransport) transport).getChannel();
|
||||||
|
var ipAddress = (IpAddress) channel.getProtocolStack().getTransport().localPhysicalAddress();
|
||||||
IpAddress ipAddress = (IpAddress) jgroupsChannel.down(new Event(Event.GET_PHYSICAL_ADDRESS, jgroupsAddress));
|
// Physical address might be null if node is no longer a member of the cluster.
|
||||||
// Physical address might be null if node is no longer a member of the cluster
|
// This seems broken, it is returning the IP/PORT for JGroups!?
|
||||||
InetSocketAddress socketAddress = (ipAddress != null) ? new InetSocketAddress(ipAddress.getIpAddress(), ipAddress.getPort()) : new InetSocketAddress(0);
|
InetSocketAddress socketAddress = (ipAddress != null) ? new InetSocketAddress(ipAddress.getIpAddress(), ipAddress.getPort()) : new InetSocketAddress(0);
|
||||||
name = String.format("%s:%s", socketAddress.getHostString(), socketAddress.getPort());
|
name = String.format("%s:%s", socketAddress.getHostString(), socketAddress.getPort());
|
||||||
|
|
||||||
|
@ -183,21 +182,16 @@ public class TopologyInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private Address getOwnerAddress(Cache cache, Object key) {
|
private Address getOwnerAddress(Cache<?, ?> cache, Object key) {
|
||||||
DistributionManager dist = cache.getAdvancedCache().getDistributionManager();
|
DistributionManager dist = cache.getAdvancedCache().getDistributionManager();
|
||||||
Address address = (dist != null) && !cache.getCacheConfiguration().clustering().cacheMode().isScattered() ?
|
return dist == null ? cache.getCacheManager().getAddress() : dist.getCacheTopology().getDistribution(key).primary();
|
||||||
dist.getCacheTopology().getDistribution(key).primary() :
|
|
||||||
cache.getCacheManager().getAddress();
|
|
||||||
|
|
||||||
return address;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// See org.wildfly.clustering.server.group.CacheGroup
|
// See org.wildfly.clustering.server.group.CacheGroup
|
||||||
private static org.jgroups.Address toJGroupsAddress(Address address) {
|
private static org.jgroups.Address toJGroupsAddress(Address address) {
|
||||||
if ((address == null) || (address == LocalModeAddress.INSTANCE)) return null;
|
if ((address == null) || (address == LocalModeAddress.INSTANCE)) return null;
|
||||||
if (address instanceof JGroupsAddress) {
|
if (address instanceof JGroupsAddress jgroupsAddress) {
|
||||||
JGroupsAddress jgroupsAddress = (JGroupsAddress) address;
|
|
||||||
return jgroupsAddress.getJGroupsAddress();
|
return jgroupsAddress.getJGroupsAddress();
|
||||||
}
|
}
|
||||||
throw new IllegalArgumentException(address.toString());
|
throw new IllegalArgumentException(address.toString());
|
||||||
|
|
|
@ -202,11 +202,8 @@ public class InfinispanUserLoginFailureProviderFactory implements UserLoginFailu
|
||||||
InfinispanCacheInitializer initializer = new InfinispanCacheInitializer(sessionFactory, workCache,
|
InfinispanCacheInitializer initializer = new InfinispanCacheInitializer(sessionFactory, workCache,
|
||||||
new RemoteCacheSessionsLoader(cacheName, sessionsPerSegment), "remoteCacheLoad::" + cacheName, maxErrors,
|
new RemoteCacheSessionsLoader(cacheName, sessionsPerSegment), "remoteCacheLoad::" + cacheName, maxErrors,
|
||||||
getStalledTimeoutInSeconds(defaultStateTransferTimeout));
|
getStalledTimeoutInSeconds(defaultStateTransferTimeout));
|
||||||
|
|
||||||
initializer.initCache();
|
|
||||||
initializer.loadSessions();
|
initializer.loadSessions();
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
log.debugf("Pre-loading login failures from remote cache '%s' finished", cacheName);
|
log.debugf("Pre-loading login failures from remote cache '%s' finished", cacheName);
|
||||||
|
|
|
@ -399,11 +399,8 @@ public class InfinispanUserSessionProviderFactory implements UserSessionProvider
|
||||||
InfinispanCacheInitializer initializer = new InfinispanCacheInitializer(sessionFactory, workCache,
|
InfinispanCacheInitializer initializer = new InfinispanCacheInitializer(sessionFactory, workCache,
|
||||||
new RemoteCacheSessionsLoader(cacheName, sessionsPerSegment), "remoteCacheLoad::" + cacheName, maxErrors,
|
new RemoteCacheSessionsLoader(cacheName, sessionsPerSegment), "remoteCacheLoad::" + cacheName, maxErrors,
|
||||||
getStalledTimeoutInSeconds(defaultStateTransferTimeout));
|
getStalledTimeoutInSeconds(defaultStateTransferTimeout));
|
||||||
|
|
||||||
initializer.initCache();
|
|
||||||
initializer.loadSessions();
|
initializer.loadSessions();
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
log.debugf("Pre-loading sessions from remote cache '%s' finished", cacheName);
|
log.debugf("Pre-loading sessions from remote cache '%s' finished", cacheName);
|
||||||
|
|
|
@ -17,15 +17,14 @@
|
||||||
|
|
||||||
package org.keycloak.models.sessions.infinispan.initializer;
|
package org.keycloak.models.sessions.infinispan.initializer;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
import org.infinispan.Cache;
|
import org.infinispan.Cache;
|
||||||
import org.infinispan.context.Flag;
|
import org.infinispan.context.Flag;
|
||||||
import org.infinispan.lifecycle.ComponentStatus;
|
import org.infinispan.lifecycle.ComponentStatus;
|
||||||
import org.infinispan.remoting.transport.Transport;
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
|
@ -74,21 +73,15 @@ public abstract class BaseCacheInitializer extends CacheInitializer {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected void saveStateToCache(final InitializerState state) {
|
protected void saveStateToCache(InitializerState state) {
|
||||||
|
|
||||||
// 3 attempts to send the message (it may fail if some node fails in the meantime)
|
// 3 attempts to send the message (it may fail if some node fails in the meantime)
|
||||||
retry(3, new Runnable() {
|
retry(3, () -> {
|
||||||
|
// Save this synchronously to ensure all nodes read correct state
|
||||||
@Override
|
// We ignore cacheStore for now, so that in Cross-DC scenario (with RemoteStore enabled) is the remoteStore ignored.
|
||||||
public void run() {
|
BaseCacheInitializer.this.workCache.getAdvancedCache().
|
||||||
|
withFlags(Flag.IGNORE_RETURN_VALUES, Flag.FORCE_SYNCHRONOUS, Flag.SKIP_CACHE_STORE, Flag.SKIP_CACHE_LOAD)
|
||||||
// Save this synchronously to ensure all nodes read correct state
|
.put(stateKey, state);
|
||||||
// We ignore cacheStore for now, so that in Cross-DC scenario (with RemoteStore enabled) is the remoteStore ignored.
|
|
||||||
BaseCacheInitializer.this.workCache.getAdvancedCache().
|
|
||||||
withFlags(Flag.IGNORE_RETURN_VALUES, Flag.FORCE_SYNCHRONOUS, Flag.SKIP_CACHE_STORE, Flag.SKIP_CACHE_LOAD)
|
|
||||||
.put(stateKey, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
package org.keycloak.models.sessions.infinispan.initializer;
|
package org.keycloak.models.sessions.infinispan.initializer;
|
||||||
|
|
||||||
import org.infinispan.Cache;
|
import org.infinispan.Cache;
|
||||||
import org.infinispan.factories.ComponentRegistry;
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
|
@ -26,9 +25,9 @@ import org.keycloak.models.KeycloakSessionTask;
|
||||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Startup initialization for reading persistent userSessions to be filled into infinispan/memory.
|
* Startup initialization for reading persistent userSessions to be filled into infinispan/memory.
|
||||||
|
@ -53,18 +52,6 @@ public class InfinispanCacheInitializer extends BaseCacheInitializer {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void initCache() {
|
|
||||||
// due to lazy initialization, this might be called from multiple threads simultaneously, therefore, synchronize
|
|
||||||
synchronized (workCache) {
|
|
||||||
final ComponentRegistry cr = this.workCache.getAdvancedCache().getComponentRegistry();
|
|
||||||
// first check if already set, as Infinispan would otherwise throw a RuntimeException
|
|
||||||
if (cr.getComponent(KeycloakSessionFactory.class) != sessionFactory) {
|
|
||||||
cr.registerComponent(sessionFactory, KeycloakSessionFactory.class);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Just coordinator will run this
|
// Just coordinator will run this
|
||||||
@Override
|
@Override
|
||||||
protected void startLoading() {
|
protected void startLoading() {
|
||||||
|
@ -102,7 +89,7 @@ public class InfinispanCacheInitializer extends BaseCacheInitializer {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void startLoadingImpl(InitializerState state, SessionLoader.LoaderContext loaderCtx) {
|
protected void startLoadingImpl(InitializerState state, SessionLoader.LoaderContext loaderCtx) {
|
||||||
int errors = 0;
|
final int errors = 0;
|
||||||
int segmentToLoad = 0;
|
int segmentToLoad = 0;
|
||||||
|
|
||||||
int distributedWorkersCount = 1;
|
int distributedWorkersCount = 1;
|
||||||
|
@ -117,7 +104,7 @@ public class InfinispanCacheInitializer extends BaseCacheInitializer {
|
||||||
log.trace("unfinished segments for this iteration: " + segments);
|
log.trace("unfinished segments for this iteration: " + segments);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Queue<SessionLoader.WorkerResult> results = new ConcurrentLinkedQueue<>();
|
Queue<SessionLoader.WorkerResult> results = new ConcurrentLinkedQueue<>();
|
||||||
|
|
||||||
for (Integer segment : segments) {
|
for (Integer segment : segments) {
|
||||||
SessionLoader.WorkerContext workerCtx = sessionLoader.computeWorkerContext(segment);
|
SessionLoader.WorkerContext workerCtx = sessionLoader.computeWorkerContext(segment);
|
||||||
|
|
|
@ -17,11 +17,6 @@
|
||||||
|
|
||||||
package org.keycloak.cluster.infinispan;
|
package org.keycloak.cluster.infinispan;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Random;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
import org.infinispan.Cache;
|
import org.infinispan.Cache;
|
||||||
import org.infinispan.client.hotrod.Flag;
|
import org.infinispan.client.hotrod.Flag;
|
||||||
import org.infinispan.client.hotrod.RemoteCache;
|
import org.infinispan.client.hotrod.RemoteCache;
|
||||||
|
@ -31,12 +26,17 @@ import org.infinispan.client.hotrod.annotation.ClientListener;
|
||||||
import org.infinispan.client.hotrod.event.ClientCacheEntryCreatedEvent;
|
import org.infinispan.client.hotrod.event.ClientCacheEntryCreatedEvent;
|
||||||
import org.infinispan.client.hotrod.event.ClientCacheEntryModifiedEvent;
|
import org.infinispan.client.hotrod.event.ClientCacheEntryModifiedEvent;
|
||||||
import org.infinispan.client.hotrod.exceptions.HotRodClientException;
|
import org.infinispan.client.hotrod.exceptions.HotRodClientException;
|
||||||
|
import org.infinispan.factories.ComponentRegistry;
|
||||||
import org.infinispan.manager.EmbeddedCacheManager;
|
import org.infinispan.manager.EmbeddedCacheManager;
|
||||||
import org.infinispan.persistence.manager.PersistenceManager;
|
import org.infinispan.persistence.manager.PersistenceManager;
|
||||||
import org.infinispan.persistence.remote.RemoteStore;
|
import org.infinispan.persistence.remote.RemoteStore;
|
||||||
import org.infinispan.persistence.remote.configuration.RemoteStoreConfigurationBuilder;
|
import org.infinispan.persistence.remote.configuration.RemoteStoreConfigurationBuilder;
|
||||||
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
|
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test concurrency for remoteStore (backed by HotRod RemoteCaches) against external JDG. Especially tests "putIfAbsent" contract.
|
* Test concurrency for remoteStore (backed by HotRod RemoteCaches) against external JDG. Especially tests "putIfAbsent" contract.
|
||||||
*
|
*
|
||||||
|
@ -46,11 +46,7 @@ import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
|
||||||
*/
|
*/
|
||||||
public class ConcurrencyJDGCachePutTest {
|
public class ConcurrencyJDGCachePutTest {
|
||||||
|
|
||||||
private static Map<String, EntryInfo> state = new HashMap<>();
|
private static final Map<String, EntryInfo> state = new HashMap<>();
|
||||||
|
|
||||||
private RemoteCache remoteCache1;
|
|
||||||
private RemoteCache remoteCache2;
|
|
||||||
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
// Init map somehow
|
// Init map somehow
|
||||||
|
@ -105,7 +101,8 @@ public class ConcurrencyJDGCachePutTest {
|
||||||
|
|
||||||
System.out.println("Retrieved cache: " + threadId);
|
System.out.println("Retrieved cache: " + threadId);
|
||||||
|
|
||||||
RemoteStore remoteStore = cache.getAdvancedCache().getComponentRegistry().getComponent(PersistenceManager.class).getStores(RemoteStore.class).iterator().next();
|
RemoteStore<?, ?> remoteStore = ComponentRegistry.componentOf(cache, PersistenceManager.class)
|
||||||
|
.getStores(RemoteStore.class).iterator().next();
|
||||||
HotRodListener listener = new HotRodListener();
|
HotRodListener listener = new HotRodListener();
|
||||||
remoteStore.getRemoteCache().addClientListener(listener);
|
remoteStore.getRemoteCache().addClientListener(listener);
|
||||||
|
|
||||||
|
@ -119,14 +116,14 @@ public class ConcurrencyJDGCachePutTest {
|
||||||
//private AtomicInteger listenerCount = new AtomicInteger(0);
|
//private AtomicInteger listenerCount = new AtomicInteger(0);
|
||||||
|
|
||||||
@ClientCacheEntryCreated
|
@ClientCacheEntryCreated
|
||||||
public void created(ClientCacheEntryCreatedEvent event) {
|
public void created(ClientCacheEntryCreatedEvent<String> event) {
|
||||||
String cacheKey = (String) event.getKey();
|
String cacheKey = event.getKey();
|
||||||
state.get(cacheKey).successfulListenerWrites.incrementAndGet();
|
state.get(cacheKey).successfulListenerWrites.incrementAndGet();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ClientCacheEntryModified
|
@ClientCacheEntryModified
|
||||||
public void updated(ClientCacheEntryModifiedEvent event) {
|
public void updated(ClientCacheEntryModifiedEvent<String> event) {
|
||||||
String cacheKey = (String) event.getKey();
|
String cacheKey = event.getKey();
|
||||||
state.get(cacheKey).successfulListenerWrites.incrementAndGet();
|
state.get(cacheKey).successfulListenerWrites.incrementAndGet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,7 +168,10 @@ public class ConcurrencyJDGCachePutTest {
|
||||||
//Integer existingClusterStartTime = (Integer) cache.putIfAbsent(cacheKey, startupTime);
|
//Integer existingClusterStartTime = (Integer) cache.putIfAbsent(cacheKey, startupTime);
|
||||||
|
|
||||||
// Concurrency works fine with this
|
// Concurrency works fine with this
|
||||||
RemoteCache remoteCache = cache.getAdvancedCache().getComponentRegistry().getComponent(PersistenceManager.class).getStores(RemoteStore.class).iterator().next().getRemoteCache();
|
RemoteCache remoteCache = ComponentRegistry.componentOf(cache, PersistenceManager.class)
|
||||||
|
.getStores(RemoteStore.class)
|
||||||
|
.iterator().next()
|
||||||
|
.getRemoteCache();
|
||||||
|
|
||||||
Integer existingClusterStartTime = null;
|
Integer existingClusterStartTime = null;
|
||||||
for (int i=0 ; i<10 ; i++) {
|
for (int i=0 ; i<10 ; i++) {
|
||||||
|
|
|
@ -17,12 +17,6 @@
|
||||||
|
|
||||||
package org.keycloak.cluster.infinispan;
|
package org.keycloak.cluster.infinispan;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
import org.infinispan.Cache;
|
import org.infinispan.Cache;
|
||||||
import org.infinispan.client.hotrod.RemoteCache;
|
import org.infinispan.client.hotrod.RemoteCache;
|
||||||
import org.infinispan.client.hotrod.VersionedValue;
|
import org.infinispan.client.hotrod.VersionedValue;
|
||||||
|
@ -31,6 +25,7 @@ import org.infinispan.client.hotrod.annotation.ClientCacheEntryModified;
|
||||||
import org.infinispan.client.hotrod.annotation.ClientListener;
|
import org.infinispan.client.hotrod.annotation.ClientListener;
|
||||||
import org.infinispan.client.hotrod.event.ClientCacheEntryCreatedEvent;
|
import org.infinispan.client.hotrod.event.ClientCacheEntryCreatedEvent;
|
||||||
import org.infinispan.client.hotrod.event.ClientCacheEntryModifiedEvent;
|
import org.infinispan.client.hotrod.event.ClientCacheEntryModifiedEvent;
|
||||||
|
import org.infinispan.factories.ComponentRegistry;
|
||||||
import org.infinispan.manager.EmbeddedCacheManager;
|
import org.infinispan.manager.EmbeddedCacheManager;
|
||||||
import org.infinispan.persistence.manager.PersistenceManager;
|
import org.infinispan.persistence.manager.PersistenceManager;
|
||||||
import org.infinispan.persistence.remote.RemoteStore;
|
import org.infinispan.persistence.remote.RemoteStore;
|
||||||
|
@ -39,6 +34,12 @@ import org.junit.Assert;
|
||||||
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
|
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
|
||||||
import org.keycloak.connections.infinispan.InfinispanUtil;
|
import org.keycloak.connections.infinispan.InfinispanUtil;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that hotrod ClientListeners are correctly executed as expected
|
* Test that hotrod ClientListeners are correctly executed as expected
|
||||||
*
|
*
|
||||||
|
@ -68,11 +69,11 @@ import org.keycloak.connections.infinispan.InfinispanUtil;
|
||||||
public class ConcurrencyJDGRemoteCacheClientListenersTest {
|
public class ConcurrencyJDGRemoteCacheClientListenersTest {
|
||||||
|
|
||||||
// Helper map to track if listeners were executed
|
// Helper map to track if listeners were executed
|
||||||
private static Map<String, EntryInfo> state = new HashMap<>();
|
private static final Map<String, EntryInfo> state = new HashMap<>();
|
||||||
|
|
||||||
private static AtomicInteger totalListenerCalls = new AtomicInteger(0);
|
private static final AtomicInteger totalListenerCalls = new AtomicInteger(0);
|
||||||
|
|
||||||
private static AtomicInteger totalErrors = new AtomicInteger(0);
|
private static final AtomicInteger totalErrors = new AtomicInteger(0);
|
||||||
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
@ -134,7 +135,8 @@ public class ConcurrencyJDGRemoteCacheClientListenersTest {
|
||||||
|
|
||||||
System.out.println("Retrieved cache: " + threadId);
|
System.out.println("Retrieved cache: " + threadId);
|
||||||
|
|
||||||
RemoteStore remoteStore = cache.getAdvancedCache().getComponentRegistry().getComponent(PersistenceManager.class).getStores(RemoteStore.class).iterator().next();
|
RemoteStore<?, ?> remoteStore = ComponentRegistry.componentOf(cache, PersistenceManager.class)
|
||||||
|
.getStores(RemoteStore.class).iterator().next();
|
||||||
HotRodListener listener = new HotRodListener(cache, threadId);
|
HotRodListener listener = new HotRodListener(cache, threadId);
|
||||||
remoteStore.getRemoteCache().addClientListener(listener);
|
remoteStore.getRemoteCache().addClientListener(listener);
|
||||||
|
|
||||||
|
@ -147,7 +149,7 @@ public class ConcurrencyJDGRemoteCacheClientListenersTest {
|
||||||
|
|
||||||
private final RemoteCache<String, Integer> remoteCache;
|
private final RemoteCache<String, Integer> remoteCache;
|
||||||
private final int threadId;
|
private final int threadId;
|
||||||
private Executor executor;
|
private final Executor executor;
|
||||||
|
|
||||||
public HotRodListener(Cache<String, Integer> cache, int threadId) {
|
public HotRodListener(Cache<String, Integer> cache, int threadId) {
|
||||||
this.remoteCache = InfinispanUtil.getRemoteCache(cache);
|
this.remoteCache = InfinispanUtil.getRemoteCache(cache);
|
||||||
|
@ -158,26 +160,15 @@ public class ConcurrencyJDGRemoteCacheClientListenersTest {
|
||||||
//private AtomicInteger listenerCount = new AtomicInteger(0);
|
//private AtomicInteger listenerCount = new AtomicInteger(0);
|
||||||
|
|
||||||
@ClientCacheEntryCreated
|
@ClientCacheEntryCreated
|
||||||
public void created(ClientCacheEntryCreatedEvent event) {
|
public void created(ClientCacheEntryCreatedEvent<String> event) {
|
||||||
String cacheKey = (String) event.getKey();
|
executor.execute(() -> event(event.getKey(), event.getVersion(), true));
|
||||||
|
|
||||||
executor.execute(() -> {
|
|
||||||
|
|
||||||
event(cacheKey, event.getVersion(), true);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ClientCacheEntryModified
|
@ClientCacheEntryModified
|
||||||
public void updated(ClientCacheEntryModifiedEvent event) {
|
public void updated(ClientCacheEntryModifiedEvent<String> event) {
|
||||||
String cacheKey = (String) event.getKey();
|
executor.execute(() -> event(event.getKey(), event.getVersion(), false));
|
||||||
executor.execute(() -> {
|
|
||||||
|
|
||||||
event(cacheKey, event.getVersion(), false);
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,19 +17,11 @@
|
||||||
|
|
||||||
package org.keycloak.keys.infinispan;
|
package org.keycloak.keys.infinispan;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.FutureTask;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
import org.infinispan.Cache;
|
import org.infinispan.Cache;
|
||||||
import org.infinispan.configuration.cache.Configuration;
|
import org.infinispan.configuration.cache.Configuration;
|
||||||
import org.infinispan.configuration.cache.ConfigurationBuilder;
|
import org.infinispan.configuration.cache.ConfigurationBuilder;
|
||||||
import org.infinispan.configuration.global.GlobalConfigurationBuilder;
|
import org.infinispan.configuration.global.GlobalConfigurationBuilder;
|
||||||
import org.infinispan.eviction.EvictionStrategy;
|
import org.infinispan.eviction.EvictionStrategy;
|
||||||
import org.infinispan.eviction.EvictionType;
|
|
||||||
import org.infinispan.manager.DefaultCacheManager;
|
import org.infinispan.manager.DefaultCacheManager;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
@ -40,12 +32,19 @@ import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
|
||||||
import org.keycloak.crypto.PublicKeysWrapper;
|
import org.keycloak.crypto.PublicKeysWrapper;
|
||||||
import org.keycloak.keys.PublicKeyLoader;
|
import org.keycloak.keys.PublicKeyLoader;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.FutureTask;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
public class InfinispanKeyStorageProviderTest {
|
public class InfinispanKeyStorageProviderTest {
|
||||||
|
|
||||||
private Map<String, AtomicInteger> counters = new ConcurrentHashMap<>();
|
private final Map<String, AtomicInteger> counters = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
Cache<String, PublicKeysEntry> keys = getKeysCache();
|
Cache<String, PublicKeysEntry> keys = getKeysCache();
|
||||||
Map<String, FutureTask<PublicKeysEntry>> tasksInProgress = new ConcurrentHashMap<>();
|
Map<String, FutureTask<PublicKeysEntry>> tasksInProgress = new ConcurrentHashMap<>();
|
||||||
|
@ -157,14 +156,13 @@ public class InfinispanKeyStorageProviderTest {
|
||||||
protected Cache<String, PublicKeysEntry> getKeysCache() {
|
protected Cache<String, PublicKeysEntry> getKeysCache() {
|
||||||
GlobalConfigurationBuilder gcb = new GlobalConfigurationBuilder();
|
GlobalConfigurationBuilder gcb = new GlobalConfigurationBuilder();
|
||||||
gcb.jmx().domain(InfinispanConnectionProvider.JMX_DOMAIN).enable();
|
gcb.jmx().domain(InfinispanConnectionProvider.JMX_DOMAIN).enable();
|
||||||
final DefaultCacheManager cacheManager = new DefaultCacheManager(gcb.build());
|
DefaultCacheManager cacheManager = new DefaultCacheManager(gcb.build());
|
||||||
|
|
||||||
ConfigurationBuilder cb = new ConfigurationBuilder();
|
ConfigurationBuilder cb = new ConfigurationBuilder();
|
||||||
cb.memory()
|
cb.memory()
|
||||||
.evictionStrategy(EvictionStrategy.REMOVE)
|
.whenFull(EvictionStrategy.REMOVE)
|
||||||
.evictionType(EvictionType.COUNT)
|
.maxCount(InfinispanConnectionProvider.KEYS_CACHE_DEFAULT_MAX);
|
||||||
.size(InfinispanConnectionProvider.KEYS_CACHE_DEFAULT_MAX);
|
cb.statistics().enabled(true);
|
||||||
cb.jmxStatistics().enabled(true);
|
|
||||||
Configuration cfg = cb.build();
|
Configuration cfg = cb.build();
|
||||||
cacheManager.defineConfiguration(InfinispanConnectionProvider.KEYS_CACHE_NAME, cfg);
|
cacheManager.defineConfiguration(InfinispanConnectionProvider.KEYS_CACHE_NAME, cfg);
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,8 @@
|
||||||
|
|
||||||
<infinispan
|
<infinispan
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="urn:infinispan:config:14.0 http://www.infinispan.org/schemas/infinispan-config-14.0.xsd"
|
xsi:schemaLocation="urn:infinispan:config:15.0 http://www.infinispan.org/schemas/infinispan-config-15.0.xsd"
|
||||||
xmlns="urn:infinispan:config:14.0">
|
xmlns="urn:infinispan:config:15.0">
|
||||||
|
|
||||||
<cache-container name="keycloak">
|
<cache-container name="keycloak">
|
||||||
<transport lock-timeout="60000"/>
|
<transport lock-timeout="60000"/>
|
||||||
|
|
38
pom.xml
38
pom.xml
|
@ -93,7 +93,7 @@
|
||||||
<h2.version>2.2.224</h2.version>
|
<h2.version>2.2.224</h2.version>
|
||||||
<hibernate-orm.plugin.version>6.2.13.Final</hibernate-orm.plugin.version>
|
<hibernate-orm.plugin.version>6.2.13.Final</hibernate-orm.plugin.version>
|
||||||
<hibernate.c3p0.version>6.2.13.Final</hibernate.c3p0.version>
|
<hibernate.c3p0.version>6.2.13.Final</hibernate.c3p0.version>
|
||||||
<infinispan.version>14.0.27.Final</infinispan.version>
|
<infinispan.version>15.0.3.Final</infinispan.version>
|
||||||
|
|
||||||
<!--JAKARTA-->
|
<!--JAKARTA-->
|
||||||
<jakarta.mail.version>2.1.1</jakarta.mail.version>
|
<jakarta.mail.version>2.1.1</jakarta.mail.version>
|
||||||
|
@ -311,42 +311,6 @@
|
||||||
<type>pom</type>
|
<type>pom</type>
|
||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.infinispan</groupId>
|
|
||||||
<artifactId>infinispan-jboss-marshalling</artifactId>
|
|
||||||
<version>${infinispan.version}</version>
|
|
||||||
<exclusions>
|
|
||||||
<!-- this conflicts with infinispan-*-jakarta -->
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.infinispan</groupId>
|
|
||||||
<artifactId>infinispan-core</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.infinispan</groupId>
|
|
||||||
<artifactId>infinispan-commons</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.infinispan</groupId>
|
|
||||||
<artifactId>infinispan-cachestore-remote</artifactId>
|
|
||||||
<version>${infinispan.version}</version>
|
|
||||||
<exclusions>
|
|
||||||
<!-- this conflicts with infinispan-*-jakarta -->
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.infinispan</groupId>
|
|
||||||
<artifactId>infinispan-core</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.infinispan</groupId>
|
|
||||||
<artifactId>infinispan-commons</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.infinispan</groupId>
|
|
||||||
<artifactId>infinispan-client-hotrod</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.quarkus.platform</groupId>
|
<groupId>io.quarkus.platform</groupId>
|
||||||
<artifactId>quarkus-bom</artifactId>
|
<artifactId>quarkus-bom</artifactId>
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.infinispan</groupId>
|
<groupId>org.infinispan</groupId>
|
||||||
<artifactId>infinispan-commons-jakarta</artifactId>
|
<artifactId>infinispan-commons</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
|
@ -457,19 +457,9 @@
|
||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.infinispan</groupId>
|
|
||||||
<artifactId>infinispan-client-hotrod-jakarta</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.infinispan</groupId>
|
<groupId>org.infinispan</groupId>
|
||||||
<artifactId>infinispan-cachestore-remote</artifactId>
|
<artifactId>infinispan-cachestore-remote</artifactId>
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>*</groupId>
|
|
||||||
<artifactId>*</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.ua-parser</groupId>
|
<groupId>com.github.ua-parser</groupId>
|
||||||
|
@ -558,11 +548,11 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.infinispan</groupId>
|
<groupId>org.infinispan</groupId>
|
||||||
<artifactId>infinispan-commons-jakarta</artifactId>
|
<artifactId>infinispan-commons</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.infinispan</groupId>
|
<groupId>org.infinispan</groupId>
|
||||||
<artifactId>infinispan-core-jakarta</artifactId>
|
<artifactId>infinispan-core</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.infinispan</groupId>
|
<groupId>org.infinispan</groupId>
|
||||||
|
|
|
@ -18,8 +18,8 @@
|
||||||
|
|
||||||
<infinispan
|
<infinispan
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="urn:infinispan:config:14.0 http://www.infinispan.org/schemas/infinispan-config-14.0.xsd"
|
xsi:schemaLocation="urn:infinispan:config:15.0 http://www.infinispan.org/schemas/infinispan-config-15.0.xsd"
|
||||||
xmlns="urn:infinispan:config:14.0">
|
xmlns="urn:infinispan:config:15.0">
|
||||||
|
|
||||||
<cache-container name="keycloak">
|
<cache-container name="keycloak">
|
||||||
<transport lock-timeout="60000"/>
|
<transport lock-timeout="60000"/>
|
||||||
|
|
|
@ -18,8 +18,8 @@
|
||||||
|
|
||||||
<infinispan
|
<infinispan
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="urn:infinispan:config:14.0 http://www.infinispan.org/schemas/infinispan-config-14.0.xsd"
|
xsi:schemaLocation="urn:infinispan:config:15.0 http://www.infinispan.org/schemas/infinispan-config-15.0.xsd"
|
||||||
xmlns="urn:infinispan:config:14.0">
|
xmlns="urn:infinispan:config:15.0">
|
||||||
|
|
||||||
<cache-container name="keycloak">
|
<cache-container name="keycloak">
|
||||||
<local-cache name="default">
|
<local-cache name="default">
|
||||||
|
|
|
@ -21,9 +21,9 @@
|
||||||
<!--tag::keycloak-ispn-configmap[] -->
|
<!--tag::keycloak-ispn-configmap[] -->
|
||||||
<infinispan
|
<infinispan
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="urn:infinispan:config:14.0 https://www.infinispan.org/schemas/infinispan-config-14.0.xsd
|
xsi:schemaLocation="urn:infinispan:config:15.0 https://www.infinispan.org/schemas/infinispan-config-15.0.xsd
|
||||||
urn:infinispan:config:store:remote:14.0 https://www.infinispan.org/schemas/infinispan-cachestore-remote-config-14.0.xsd"
|
urn:infinispan:config:store:remote:15.0 https://www.infinispan.org/schemas/infinispan-cachestore-remote-config-15.0.xsd"
|
||||||
xmlns="urn:infinispan:config:14.0">
|
xmlns="urn:infinispan:config:15.0">
|
||||||
<!--end::keycloak-ispn-configmap[] -->
|
<!--end::keycloak-ispn-configmap[] -->
|
||||||
|
|
||||||
<!-- the statistics="true" attribute is not part of the original KC config and was added by Keycloak Benchmark -->
|
<!-- the statistics="true" attribute is not part of the original KC config and was added by Keycloak Benchmark -->
|
||||||
|
@ -47,8 +47,8 @@
|
||||||
<!--tag::keycloak-ispn-remotestore[] -->
|
<!--tag::keycloak-ispn-remotestore[] -->
|
||||||
<distributed-cache name="sessions" owners="2" statistics="true">
|
<distributed-cache name="sessions" owners="2" statistics="true">
|
||||||
<expiration lifespan="-1"/>
|
<expiration lifespan="-1"/>
|
||||||
<persistence passivation="false"> <!--1-->
|
<persistence passivation="false" availability-interval="500"> <!--1-->
|
||||||
<remote-store xmlns="urn:infinispan:config:store:remote:14.0"
|
<remote-store xmlns="urn:infinispan:config:store:remote:15.0"
|
||||||
cache="sessions"
|
cache="sessions"
|
||||||
raw-values="true"
|
raw-values="true"
|
||||||
shared="true"
|
shared="true"
|
||||||
|
@ -71,8 +71,8 @@
|
||||||
<!--end::keycloak-ispn-remotestore[] -->
|
<!--end::keycloak-ispn-remotestore[] -->
|
||||||
<distributed-cache name="authenticationSessions" owners="2" statistics="true">
|
<distributed-cache name="authenticationSessions" owners="2" statistics="true">
|
||||||
<expiration lifespan="-1"/>
|
<expiration lifespan="-1"/>
|
||||||
<persistence passivation="false">
|
<persistence passivation="false" availability-interval="500">
|
||||||
<remote-store xmlns="urn:infinispan:config:store:remote:14.0"
|
<remote-store xmlns="urn:infinispan:config:store:remote:15.0"
|
||||||
cache="authenticationSessions"
|
cache="authenticationSessions"
|
||||||
raw-values="true"
|
raw-values="true"
|
||||||
shared="true"
|
shared="true"
|
||||||
|
@ -94,8 +94,8 @@
|
||||||
</distributed-cache>
|
</distributed-cache>
|
||||||
<distributed-cache name="offlineSessions" owners="2" statistics="true">
|
<distributed-cache name="offlineSessions" owners="2" statistics="true">
|
||||||
<expiration lifespan="-1"/>
|
<expiration lifespan="-1"/>
|
||||||
<persistence passivation="false">
|
<persistence passivation="false" availability-interval="500">
|
||||||
<remote-store xmlns="urn:infinispan:config:store:remote:14.0"
|
<remote-store xmlns="urn:infinispan:config:store:remote:15.0"
|
||||||
cache="offlineSessions"
|
cache="offlineSessions"
|
||||||
raw-values="true"
|
raw-values="true"
|
||||||
shared="true"
|
shared="true"
|
||||||
|
@ -117,8 +117,8 @@
|
||||||
</distributed-cache>
|
</distributed-cache>
|
||||||
<distributed-cache name="clientSessions" owners="2" statistics="true">
|
<distributed-cache name="clientSessions" owners="2" statistics="true">
|
||||||
<expiration lifespan="-1"/>
|
<expiration lifespan="-1"/>
|
||||||
<persistence passivation="false">
|
<persistence passivation="false" availability-interval="500">
|
||||||
<remote-store xmlns="urn:infinispan:config:store:remote:14.0"
|
<remote-store xmlns="urn:infinispan:config:store:remote:15.0"
|
||||||
cache="clientSessions"
|
cache="clientSessions"
|
||||||
raw-values="true"
|
raw-values="true"
|
||||||
shared="true"
|
shared="true"
|
||||||
|
@ -140,8 +140,8 @@
|
||||||
</distributed-cache>
|
</distributed-cache>
|
||||||
<distributed-cache name="offlineClientSessions" owners="2" statistics="true">
|
<distributed-cache name="offlineClientSessions" owners="2" statistics="true">
|
||||||
<expiration lifespan="-1"/>
|
<expiration lifespan="-1"/>
|
||||||
<persistence passivation="false">
|
<persistence passivation="false" availability-interval="500">
|
||||||
<remote-store xmlns="urn:infinispan:config:store:remote:14.0"
|
<remote-store xmlns="urn:infinispan:config:store:remote:15.0"
|
||||||
cache="offlineClientSessions"
|
cache="offlineClientSessions"
|
||||||
raw-values="true"
|
raw-values="true"
|
||||||
shared="true"
|
shared="true"
|
||||||
|
@ -163,8 +163,8 @@
|
||||||
</distributed-cache>
|
</distributed-cache>
|
||||||
<distributed-cache name="loginFailures" owners="2" statistics="true">
|
<distributed-cache name="loginFailures" owners="2" statistics="true">
|
||||||
<expiration lifespan="-1"/>
|
<expiration lifespan="-1"/>
|
||||||
<persistence passivation="false">
|
<persistence passivation="false" availability-interval="500">
|
||||||
<remote-store xmlns="urn:infinispan:config:store:remote:14.0"
|
<remote-store xmlns="urn:infinispan:config:store:remote:15.0"
|
||||||
cache="loginFailures"
|
cache="loginFailures"
|
||||||
raw-values="true"
|
raw-values="true"
|
||||||
shared="true"
|
shared="true"
|
||||||
|
@ -193,8 +193,8 @@
|
||||||
</local-cache>
|
</local-cache>
|
||||||
<replicated-cache name="work" statistics="true">
|
<replicated-cache name="work" statistics="true">
|
||||||
<expiration lifespan="-1"/>
|
<expiration lifespan="-1"/>
|
||||||
<persistence passivation="false">
|
<persistence passivation="false" availability-interval="500">
|
||||||
<remote-store xmlns="urn:infinispan:config:store:remote:14.0"
|
<remote-store xmlns="urn:infinispan:config:store:remote:15.0"
|
||||||
cache="work"
|
cache="work"
|
||||||
raw-values="true"
|
raw-values="true"
|
||||||
shared="true"
|
shared="true"
|
||||||
|
@ -229,8 +229,8 @@
|
||||||
</encoding>
|
</encoding>
|
||||||
<expiration max-idle="-1" lifespan="-1" interval="300000"/>
|
<expiration max-idle="-1" lifespan="-1" interval="300000"/>
|
||||||
<memory max-count="-1"/>
|
<memory max-count="-1"/>
|
||||||
<persistence passivation="false">
|
<persistence passivation="false" availability-interval="500">
|
||||||
<remote-store xmlns="urn:infinispan:config:store:remote:14.0"
|
<remote-store xmlns="urn:infinispan:config:store:remote:15.0"
|
||||||
cache="actionTokens"
|
cache="actionTokens"
|
||||||
raw-values="true"
|
raw-values="true"
|
||||||
shared="true"
|
shared="true"
|
||||||
|
|
|
@ -86,21 +86,11 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.infinispan</groupId>
|
<groupId>org.infinispan</groupId>
|
||||||
<artifactId>infinispan-core-jakarta</artifactId>
|
<artifactId>infinispan-core</artifactId>
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.infinispan</groupId>
|
|
||||||
<artifactId>infinispan-client-hotrod-jakarta</artifactId>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.infinispan</groupId>
|
<groupId>org.infinispan</groupId>
|
||||||
<artifactId>infinispan-tasks-api</artifactId>
|
<artifactId>infinispan-tasks-api</artifactId>
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.infinispan</groupId>
|
|
||||||
<artifactId>infinispan-core</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
|
@ -48,14 +48,14 @@ public class InfinispanTimeServiceTask implements ServerTask<String> {
|
||||||
@Override
|
@Override
|
||||||
public String call() {
|
public String call() {
|
||||||
EmbeddedCacheManager cacheManager = context.getCacheManager();
|
EmbeddedCacheManager cacheManager = context.getCacheManager();
|
||||||
Map<String, Object> params = new HashMap();
|
Map<String, Object> params = new HashMap<>();
|
||||||
if (this.context.getParameters().isPresent())
|
if (this.context.getParameters().isPresent())
|
||||||
params = this.context.getParameters().get();
|
params = this.context.getParameters().get();
|
||||||
if (params.containsKey("timeService")) {
|
if (params.containsKey("timeService")) {
|
||||||
offset = (int) params.get("timeService");
|
offset = (int) params.get("timeService");
|
||||||
|
|
||||||
// rewire the Time service
|
// rewire the Time service
|
||||||
GlobalComponentRegistry cr = cacheManager.getGlobalComponentRegistry();
|
GlobalComponentRegistry cr = GlobalComponentRegistry.of(cacheManager);
|
||||||
BasicComponentRegistry bcr = cr.getComponent(BasicComponentRegistry.class);
|
BasicComponentRegistry bcr = cr.getComponent(BasicComponentRegistry.class);
|
||||||
bcr.replaceComponent(TimeService.class.getName(), KEYCLOAK_TIME_SERVICE, true);
|
bcr.replaceComponent(TimeService.class.getName(), KEYCLOAK_TIME_SERVICE, true);
|
||||||
cr.rewire();
|
cr.rewire();
|
||||||
|
|
|
@ -17,29 +17,28 @@
|
||||||
|
|
||||||
package org.keycloak.testsuite.rest.resource;
|
package org.keycloak.testsuite.rest.resource;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import jakarta.ws.rs.Consumes;
|
import jakarta.ws.rs.Consumes;
|
||||||
import jakarta.ws.rs.GET;
|
import jakarta.ws.rs.GET;
|
||||||
import jakarta.ws.rs.POST;
|
import jakarta.ws.rs.POST;
|
||||||
import jakarta.ws.rs.Path;
|
import jakarta.ws.rs.Path;
|
||||||
import jakarta.ws.rs.PathParam;
|
import jakarta.ws.rs.PathParam;
|
||||||
import jakarta.ws.rs.Produces;
|
import jakarta.ws.rs.Produces;
|
||||||
|
|
||||||
import org.infinispan.Cache;
|
import org.infinispan.Cache;
|
||||||
import org.infinispan.client.hotrod.RemoteCache;
|
import org.infinispan.client.hotrod.RemoteCache;
|
||||||
|
import org.infinispan.stream.CacheCollectors;
|
||||||
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
|
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
|
||||||
|
import org.keycloak.connections.infinispan.InfinispanUtil;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper;
|
import org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper;
|
||||||
import org.keycloak.models.sessions.infinispan.entities.UserSessionEntity;
|
import org.keycloak.models.sessions.infinispan.entities.UserSessionEntity;
|
||||||
import org.keycloak.connections.infinispan.InfinispanUtil;
|
|
||||||
import org.keycloak.utils.MediaType;
|
import org.keycloak.utils.MediaType;
|
||||||
import org.infinispan.stream.CacheCollectors;
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
@ -114,12 +113,10 @@ public class TestCacheResource {
|
||||||
@Path("/remote-cache-stats")
|
@Path("/remote-cache-stats")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public Map<String, String> getRemoteCacheStats() {
|
public Map<String, String> getRemoteCacheStats() {
|
||||||
RemoteCache remoteCache = InfinispanUtil.getRemoteCache(cache);
|
var remoteCache = InfinispanUtil.getRemoteCache(cache);
|
||||||
if (remoteCache == null) {
|
return remoteCache == null ?
|
||||||
return new HashMap<>();
|
Collections.emptyMap() :
|
||||||
} else {
|
remoteCache.serverStatistics().getStatsMap();
|
||||||
return remoteCache.stats().getStatsMap();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -127,11 +124,11 @@ public class TestCacheResource {
|
||||||
@Path("/remote-cache-last-session-refresh/{user-session-id}")
|
@Path("/remote-cache-last-session-refresh/{user-session-id}")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public int getRemoteCacheLastSessionRefresh(@PathParam("user-session-id") String userSessionId) {
|
public int getRemoteCacheLastSessionRefresh(@PathParam("user-session-id") String userSessionId) {
|
||||||
RemoteCache remoteCache = InfinispanUtil.getRemoteCache(cache);
|
RemoteCache<String, SessionEntityWrapper<UserSessionEntity>> remoteCache = InfinispanUtil.getRemoteCache(cache);
|
||||||
if (remoteCache == null) {
|
if (remoteCache == null) {
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
SessionEntityWrapper<UserSessionEntity> userSession = (SessionEntityWrapper<UserSessionEntity>) remoteCache.get(userSessionId);
|
SessionEntityWrapper<UserSessionEntity> userSession = remoteCache.get(userSessionId);
|
||||||
if (userSession == null) {
|
if (userSession == null) {
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -151,7 +151,7 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.infinispan</groupId>
|
<groupId>org.infinispan</groupId>
|
||||||
<artifactId>infinispan-server-hotrod-jakarta</artifactId>
|
<artifactId>infinispan-server-hotrod</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
|
|
|
@ -1819,7 +1819,7 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.infinispan</groupId>
|
<groupId>org.infinispan</groupId>
|
||||||
<artifactId>infinispan-core-jakarta</artifactId>
|
<artifactId>infinispan-core</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
|
@ -104,7 +104,7 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.infinispan</groupId>
|
<groupId>org.infinispan</groupId>
|
||||||
<artifactId>infinispan-core-jakarta</artifactId>
|
<artifactId>infinispan-core</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.postgresql</groupId>
|
<groupId>org.postgresql</groupId>
|
||||||
|
|
|
@ -227,7 +227,7 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.infinispan</groupId>
|
<groupId>org.infinispan</groupId>
|
||||||
<artifactId>infinispan-core-jakarta</artifactId>
|
<artifactId>infinispan-core</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.infinispan</groupId>
|
<groupId>org.infinispan</groupId>
|
||||||
|
|
Loading…
Reference in a new issue