From ba495d1ab19ac2e8813414d953383ce0f4e9ae86 Mon Sep 17 00:00:00 2001 From: Pedro Ruivo Date: Wed, 17 Dec 2025 06:40:49 +0000 Subject: [PATCH] Remote Infinispan should return count per client only for the current realm (#44948) Closes #44577 Signed-off-by: Pedro Ruivo <1492066+pruivo@users.noreply.github.com> Co-authored-by: Pedro Ruivo <1492066+pruivo@users.noreply.github.com> --- .../sessions/infinispan/query/ClientSessionQueries.java | 7 ++++--- .../infinispan/remote/RemoteUserSessionProvider.java | 2 +- .../model/infinispan/InfinispanIckleQueryTest.java | 6 +++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/query/ClientSessionQueries.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/query/ClientSessionQueries.java index 6e9af6e047f..b799a51b362 100644 --- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/query/ClientSessionQueries.java +++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/query/ClientSessionQueries.java @@ -35,7 +35,7 @@ public final class ClientSessionQueries { public static final String CLIENT_SESSION = Marshalling.protoEntity(RemoteAuthenticatedClientSessionEntity.class); private static final String FETCH_USER_SESSION_ID = "SELECT e.userSessionId FROM %s as e WHERE e.realmId = :realmId && e.clientId = :clientId ORDER BY e.userSessionId".formatted(CLIENT_SESSION); - private static final String PER_CLIENT_COUNT = "SELECT e.clientId, count(e.clientId) FROM %s as e GROUP BY e.clientId ORDER BY e.clientId".formatted(CLIENT_SESSION); + private static final String PER_CLIENT_COUNT = "SELECT e.clientId, count(e.clientId) FROM %s as e WHERE e.realmId = :realmId GROUP BY e.clientId ORDER BY e.clientId".formatted(CLIENT_SESSION); private static final String CLIENT_SESSION_COUNT = "SELECT count(e) FROM %s as e WHERE e.realmId = :realmId && e.clientId = :clientId".formatted(CLIENT_SESSION); private static final String FROM_USER_SESSION = "FROM %s as e WHERE e.userSessionId = :userSessionId ORDER BY e.clientId".formatted(CLIENT_SESSION); private static final String IDS_FROM_USER_SESSION = "SELECT e.clientId FROM %s as e WHERE e.userSessionId = :userSessionId ORDER BY e.clientId".formatted(CLIENT_SESSION); @@ -52,8 +52,9 @@ public final class ClientSessionQueries { /** * Returns a projection with the client ID and its number of active client sessions. */ - public static Query activeClientCount(RemoteCache cache) { - return cache.query(PER_CLIENT_COUNT); + public static Query activeClientCount(RemoteCache cache, String realmId) { + return cache.query(PER_CLIENT_COUNT) + .setParameter("realmId", realmId); } /** diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/remote/RemoteUserSessionProvider.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/remote/RemoteUserSessionProvider.java index 24f946145d2..84ae02f9401 100644 --- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/remote/RemoteUserSessionProvider.java +++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/remote/RemoteUserSessionProvider.java @@ -168,7 +168,7 @@ public class RemoteUserSessionProvider implements UserSessionProvider { @Override public Map getActiveClientSessionStats(RealmModel realm, boolean offline) { - var query = ClientSessionQueries.activeClientCount(getClientSessionTransaction(offline).getCache()); + var query = ClientSessionQueries.activeClientCount(getClientSessionTransaction(offline).getCache(), realm.getId()); return QueryHelper.streamAll(query, batchSize, QueryHelper.PROJECTION_TO_STRING_LONG_ENTRY) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); } diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/infinispan/InfinispanIckleQueryTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/infinispan/InfinispanIckleQueryTest.java index 21995cebada..a8d7d23dd22 100644 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/infinispan/InfinispanIckleQueryTest.java +++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/infinispan/InfinispanIckleQueryTest.java @@ -459,9 +459,9 @@ public class InfinispanIckleQueryTest extends KeycloakModelTest { expectedResults = CLIENTS.stream().map(s -> new ClientSessionKey(userSession, s)).map(Objects::toString).collect(Collectors.toSet()); assertQuery(query2, objects -> objects.createCacheKey().toString(), expectedResults); - // each client has user-session * realms active client sessions - query = ClientSessionQueries.activeClientCount(cache); - expectedResults = CLIENTS.stream().map(s -> String.format("%s-%s", s, USER_SESSIONS.size() * REALMS.size())).collect(Collectors.toSet()); + // each client has user-session active client sessions + query = ClientSessionQueries.activeClientCount(cache, realm); + expectedResults = CLIENTS.stream().map(s -> String.format("%s-%s", s, USER_SESSIONS.size())).collect(Collectors.toSet()); assertQuery(query, objects -> String.format("%s-%s", objects[0], objects[1]), expectedResults); }