Asynchronously create EmbeddedCacheManager when JDBC_PING2 not required
Closes #34313 Signed-off-by: Ryan Emerson <remerson@redhat.com>
This commit is contained in:
parent
4e540fa2a7
commit
ba51140a25
1 changed files with 44 additions and 14 deletions
|
@ -28,6 +28,7 @@ import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
import java.util.function.Function;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
@ -52,6 +53,7 @@ import org.infinispan.configuration.global.ShutdownHookBehavior;
|
||||||
import org.infinispan.configuration.parsing.ConfigurationBuilderHolder;
|
import org.infinispan.configuration.parsing.ConfigurationBuilderHolder;
|
||||||
import org.infinispan.configuration.parsing.ParserRegistry;
|
import org.infinispan.configuration.parsing.ParserRegistry;
|
||||||
import org.infinispan.manager.DefaultCacheManager;
|
import org.infinispan.manager.DefaultCacheManager;
|
||||||
|
import org.infinispan.manager.EmbeddedCacheManager;
|
||||||
import org.infinispan.metrics.config.MicrometerMeterRegisterConfigurationBuilder;
|
import org.infinispan.metrics.config.MicrometerMeterRegisterConfigurationBuilder;
|
||||||
import org.infinispan.persistence.remote.configuration.ExhaustedAction;
|
import org.infinispan.persistence.remote.configuration.ExhaustedAction;
|
||||||
import org.infinispan.persistence.remote.configuration.RemoteStoreConfigurationBuilder;
|
import org.infinispan.persistence.remote.configuration.RemoteStoreConfigurationBuilder;
|
||||||
|
@ -110,12 +112,21 @@ public class CacheManagerFactory {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(CacheManagerFactory.class);
|
private static final Logger logger = Logger.getLogger(CacheManagerFactory.class);
|
||||||
|
|
||||||
|
private final CompletableFuture<EmbeddedCacheManager> cacheManagerFuture;
|
||||||
private final CompletableFuture<RemoteCacheManager> remoteCacheManagerFuture;
|
private final CompletableFuture<RemoteCacheManager> remoteCacheManagerFuture;
|
||||||
private final String config;
|
private final Function<EntityManager, EmbeddedCacheManager> jdbcCacheManagerFunction;
|
||||||
private volatile DefaultCacheManager cacheManager;
|
private volatile EmbeddedCacheManager cacheManager;
|
||||||
|
|
||||||
public CacheManagerFactory(String config) {
|
public CacheManagerFactory(String config) {
|
||||||
this.config = config;
|
ConfigurationBuilderHolder builder = new ParserRegistry().parse(config);
|
||||||
|
if (!isJdbcPingRequired(builder)) {
|
||||||
|
cacheManagerFuture = CompletableFuture.supplyAsync(() -> startEmbeddedCacheManager(builder, null));
|
||||||
|
jdbcCacheManagerFunction = null;
|
||||||
|
} else {
|
||||||
|
cacheManagerFuture = null;
|
||||||
|
jdbcCacheManagerFunction = em -> startEmbeddedCacheManager(builder, em);
|
||||||
|
}
|
||||||
|
|
||||||
if (InfinispanUtils.isRemoteInfinispan()) {
|
if (InfinispanUtils.isRemoteInfinispan()) {
|
||||||
logger.debug("Remote Cache feature is enabled");
|
logger.debug("Remote Cache feature is enabled");
|
||||||
this.remoteCacheManagerFuture = CompletableFuture.supplyAsync(this::startRemoteCacheManager);
|
this.remoteCacheManagerFuture = CompletableFuture.supplyAsync(this::startRemoteCacheManager);
|
||||||
|
@ -125,11 +136,32 @@ public class CacheManagerFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DefaultCacheManager getOrCreateEmbeddedCacheManager(KeycloakSession keycloakSession) {
|
private static boolean isJdbcPingRequired(ConfigurationBuilderHolder builder) {
|
||||||
|
if (InfinispanUtils.isRemoteInfinispan())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var transportConfig = builder.getGlobalConfigurationBuilder().transport();
|
||||||
|
if (transportConfig.getTransport() == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
String transportStack = Configuration.getRawValue("kc.cache-stack");
|
||||||
|
if (transportStack != null && !isJdbcPingStack(transportStack))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var stackXmlAttribute = transportConfig.defaultTransport().attributes().attribute(STACK);
|
||||||
|
return !stackXmlAttribute.isModified() || isJdbcPingStack(stackXmlAttribute.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
public EmbeddedCacheManager getOrCreateEmbeddedCacheManager(KeycloakSession keycloakSession) {
|
||||||
|
if (cacheManagerFuture != null)
|
||||||
|
return join(cacheManagerFuture);
|
||||||
|
|
||||||
if (cacheManager == null) {
|
if (cacheManager == null) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (cacheManager == null)
|
if (cacheManager == null) {
|
||||||
cacheManager = startEmbeddedCacheManager(keycloakSession);
|
EntityManager em = keycloakSession.getProvider(JpaConnectionProvider.class).getEntityManager();
|
||||||
|
cacheManager = jdbcCacheManagerFunction.apply(em);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return cacheManager;
|
return cacheManager;
|
||||||
|
@ -286,9 +318,8 @@ public class CacheManagerFactory {
|
||||||
admin.reindexCache(cacheName);
|
admin.reindexCache(cacheName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DefaultCacheManager startEmbeddedCacheManager(KeycloakSession keycloakSession) {
|
private EmbeddedCacheManager startEmbeddedCacheManager(ConfigurationBuilderHolder builder, EntityManager em) {
|
||||||
logger.info("Starting Infinispan embedded cache manager");
|
logger.info("Starting Infinispan embedded cache manager");
|
||||||
ConfigurationBuilderHolder builder = new ParserRegistry().parse(config);
|
|
||||||
|
|
||||||
// We must disable the Infinispan default ShutdownHook as we manage the EmbeddedCacheManager lifecycle explicitly
|
// We must disable the Infinispan default ShutdownHook as we manage the EmbeddedCacheManager lifecycle explicitly
|
||||||
// with #shutdown and multiple calls to EmbeddedCacheManager#stop can lead to Exceptions being thrown
|
// with #shutdown and multiple calls to EmbeddedCacheManager#stop can lead to Exceptions being thrown
|
||||||
|
@ -322,7 +353,7 @@ public class CacheManagerFactory {
|
||||||
} else {
|
} else {
|
||||||
// embedded mode!
|
// embedded mode!
|
||||||
if (builder.getNamedConfigurationBuilders().entrySet().stream().anyMatch(c -> c.getValue().clustering().cacheMode().isClustered())) {
|
if (builder.getNamedConfigurationBuilders().entrySet().stream().anyMatch(c -> c.getValue().clustering().cacheMode().isClustered())) {
|
||||||
configureTransportStack(builder, keycloakSession);
|
configureTransportStack(builder, em);
|
||||||
configureRemoteStores(builder);
|
configureRemoteStores(builder);
|
||||||
}
|
}
|
||||||
configureCacheMaxCount(builder, CachingOptions.CLUSTERED_MAX_COUNT_CACHES);
|
configureCacheMaxCount(builder, CachingOptions.CLUSTERED_MAX_COUNT_CACHES);
|
||||||
|
@ -368,7 +399,7 @@ public class CacheManagerFactory {
|
||||||
return Integer.getInteger("kc.cache-ispn-start-timeout", 120);
|
return Integer.getInteger("kc.cache-ispn-start-timeout", 120);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void configureTransportStack(ConfigurationBuilderHolder builder, KeycloakSession keycloakSession) {
|
private static void configureTransportStack(ConfigurationBuilderHolder builder, EntityManager em) {
|
||||||
var transportConfig = builder.getGlobalConfigurationBuilder().transport();
|
var transportConfig = builder.getGlobalConfigurationBuilder().transport();
|
||||||
if (Configuration.isTrue(CachingOptions.CACHE_EMBEDDED_MTLS_ENABLED_PROPERTY)) {
|
if (Configuration.isTrue(CachingOptions.CACHE_EMBEDDED_MTLS_ENABLED_PROPERTY)) {
|
||||||
validateTlsAvailable(transportConfig.build());
|
validateTlsAvailable(transportConfig.build());
|
||||||
|
@ -405,7 +436,6 @@ public class CacheManagerFactory {
|
||||||
stackXmlAttribute.isModified() ? stackXmlAttribute.get() : "jdbc-ping-udp";
|
stackXmlAttribute.isModified() ? stackXmlAttribute.get() : "jdbc-ping-udp";
|
||||||
var udp = stackName.endsWith("udp");
|
var udp = stackName.endsWith("udp");
|
||||||
|
|
||||||
EntityManager em = keycloakSession.getProvider(JpaConnectionProvider.class).getEntityManager();
|
|
||||||
var tableName = JpaUtils.getTableNameForNativeQuery("JGROUPS_PING", em);
|
var tableName = JpaUtils.getTableNameForNativeQuery("JGROUPS_PING", em);
|
||||||
var attributes = Map.of(
|
var attributes = Map.of(
|
||||||
// Leave initialize_sql blank as table is already created by Keycloak
|
// Leave initialize_sql blank as table is already created by Keycloak
|
||||||
|
@ -429,16 +459,16 @@ public class CacheManagerFactory {
|
||||||
transportConfig.defaultTransport().stack(stackName);
|
transportConfig.defaultTransport().stack(stackName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void warnDeprecatedCloudStack(String stackName) {
|
private static void warnDeprecatedCloudStack(String stackName) {
|
||||||
switch (stackName) {
|
switch (stackName) {
|
||||||
case "azure":
|
case "azure":
|
||||||
case "ec2":
|
case "ec2":
|
||||||
case "google":
|
case "google":
|
||||||
logger.warnf("Stack '%s' is deprecated. We recommend to use 'jdbc-ping' instead", stackName);
|
Logger.getLogger(CacheManagerFactory.class).warnf("Stack '%s' is deprecated. We recommend to use 'jdbc-ping' instead", stackName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isJdbcPingStack(String stackName) {
|
private static boolean isJdbcPingStack(String stackName) {
|
||||||
return "jdbc-ping".equals(stackName) || "jdbc-ping-udp".equals(stackName);
|
return "jdbc-ping".equals(stackName) || "jdbc-ping-udp".equals(stackName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue