diff --git a/model/infinispan/src/main/java/org/keycloak/infinispan/compatibility/CachingEmbeddedMetadataProvider.java b/model/infinispan/src/main/java/org/keycloak/infinispan/compatibility/CachingEmbeddedMetadataProvider.java index 74f7438362c..67b2c52c030 100644 --- a/model/infinispan/src/main/java/org/keycloak/infinispan/compatibility/CachingEmbeddedMetadataProvider.java +++ b/model/infinispan/src/main/java/org/keycloak/infinispan/compatibility/CachingEmbeddedMetadataProvider.java @@ -4,20 +4,28 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Arrays; import java.util.Base64; +import java.util.HashMap; import java.util.Map; +import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Stream; import org.keycloak.Config; +import org.keycloak.common.Profile; import org.keycloak.compatibility.AbstractCompatibilityMetadataProvider; import org.keycloak.crypto.JavaAlgorithm; import org.keycloak.infinispan.util.InfinispanUtils; import org.keycloak.jose.jws.crypto.HashUtils; +import org.keycloak.spi.infinispan.impl.embedded.CacheConfigurator; import org.infinispan.commons.util.Version; +import org.infinispan.configuration.cache.HashConfiguration; +import static org.keycloak.connections.infinispan.InfinispanConnectionProvider.CLUSTERED_CACHE_NUM_OWNERS; +import static org.keycloak.connections.infinispan.InfinispanConnectionProvider.USER_AND_CLIENT_SESSION_CACHES; import static org.keycloak.spi.infinispan.CacheEmbeddedConfigProviderSpi.SPI_NAME; import static org.keycloak.spi.infinispan.impl.embedded.DefaultCacheEmbeddedConfigProviderFactory.CONFIG; import static org.keycloak.spi.infinispan.impl.embedded.DefaultCacheEmbeddedConfigProviderFactory.PROVIDER_ID; @@ -38,17 +46,34 @@ public class CachingEmbeddedMetadataProvider extends AbstractCompatibilityMetada @Override public Map customMeta() { - return Map.of( - "version", majorMinorOf(Version.getVersion()), - "jgroupsVersion", majorMinorOf(org.jgroups.Version.printVersion()), - CONFIG, sha256Of(Paths.get(config.get(CONFIG))) - ); + var meta = new HashMap(8); + var defaultNumOwners = HashConfiguration.NUM_OWNERS.getDefaultValue(); + Arrays.stream(CLUSTERED_CACHE_NUM_OWNERS) + .map(CacheConfigurator::numOwnerConfigKey) + .forEach(configKey -> addInt(meta, configKey, defaultNumOwners)); + if (Profile.isFeatureEnabled(Profile.Feature.PERSISTENT_USER_SESSIONS)) { + // persistent user sessions always force num_owners=1. + // the spi option is ignored + Arrays.stream(USER_AND_CLIENT_SESSION_CACHES) + .map(CacheConfigurator::numOwnerConfigKey) + .forEach(meta::remove); + } + meta.put("version", majorMinorOf(Version.getVersion())); + meta.put("jgroupsVersion", majorMinorOf(org.jgroups.Version.printVersion())); + meta.put(CONFIG, sha256Of(Paths.get(config.get(CONFIG)))); + return meta; } @Override public Stream configKeys() { return Stream.of(STACK); } + private void addInt(Map meta, String configKey, int defaultValue) { + Optional.ofNullable(config.getInt(configKey, defaultValue)) + .map(String::valueOf) + .ifPresent(value -> meta.put(configKey, value)); + } + public static String sha256Of(Path filePath) { try { var hash = HashUtils.hash(JavaAlgorithm.SHA256, Files.readAllBytes(filePath)); diff --git a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/UpdateCommandDistTest.java b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/UpdateCommandDistTest.java index 768025e5d5c..37cca7707aa 100644 --- a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/UpdateCommandDistTest.java +++ b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/UpdateCommandDistTest.java @@ -338,6 +338,9 @@ public class UpdateCommandDistTest { m.put("version", majorMinorOf(org.infinispan.commons.util.Version.getVersion())); m.put("jgroupsVersion", majorMinorOf(org.jgroups.Version.printVersion())); m.put(CONFIG, CONFIG_FILE_NOT_FOUND); + m.put("actionTokensOwners", "2"); + m.put("loginFailuresOwners", "2"); + m.put("authenticationSessionsOwners", "2"); return m; } }