Avoid n+1 SQL selects to load sessions

Closes #32273

Signed-off-by: Alexander Schwartz <aschwart@redhat.com>
This commit is contained in:
Alexander Schwartz 2024-08-20 16:03:41 +02:00 committed by Alexander Schwartz
parent 293333056f
commit a7964a588b
2 changed files with 21 additions and 19 deletions

View file

@ -223,7 +223,7 @@ public class PersistentUserSessionProvider implements UserSessionProvider, Sessi
if (userSession.isOffline()) { if (userSession.isOffline()) {
// If this is an offline session, and the referred online session doesn't exist anymore, don't register the client session in the transaction. // If this is an offline session, and the referred online session doesn't exist anymore, don't register the client session in the transaction.
// Instead keep it transient and it will be added to the offline session only afterward. This is expected by SessionTimeoutsTest.testOfflineUserClientIdleTimeoutSmallerThanSessionOneRefresh. // Instead keep it transient and it will be added to the offline session only afterward. This is expected by SessionTimeoutsTest.testOfflineUserClientIdleTimeoutSmallerThanSessionOneRefresh.
if (sessionTx.get(realm, userSession.getId(), false) == null) { if (sessionTx.get(realm, userSession.getId(), userSession, false) == null) {
return adapter; return adapter;
} }
} }
@ -279,23 +279,23 @@ public class PersistentUserSessionProvider implements UserSessionProvider, Sessi
@Override @Override
public UserSessionModel getUserSession(RealmModel realm, String id) { public UserSessionModel getUserSession(RealmModel realm, String id) {
return getUserSession(realm, id, false); return getUserSession(realm, id, null, false);
} }
private UserSessionAdapter getUserSession(RealmModel realm, String id, boolean offline) { private UserSessionAdapter getUserSession(RealmModel realm, String id, UserSessionModel userSession, boolean offline) {
SessionEntityWrapper<UserSessionEntity> entityWrapper = sessionTx.get(realm, id, offline); SessionEntityWrapper<UserSessionEntity> entityWrapper = sessionTx.get(realm, id, userSession, offline);
return entityWrapper != null ? wrap(realm, entityWrapper.getEntity(), offline) : null; return entityWrapper != null ? wrap(realm, entityWrapper.getEntity(), offline) : null;
} }
private UserSessionEntity getUserSessionEntity(RealmModel realm, String id, boolean offline) { private UserSessionEntity getUserSessionEntity(RealmModel realm, String id, boolean offline) {
SessionEntityWrapper<UserSessionEntity> entityWrapper = sessionTx.get(realm, id, offline); SessionEntityWrapper<UserSessionEntity> entityWrapper = sessionTx.get(realm, id, null, offline);
return entityWrapper != null ? entityWrapper.getEntity() : null; return entityWrapper != null ? entityWrapper.getEntity() : null;
} }
private Stream<UserSessionModel> getUserSessionsFromPersistenceProviderStream(RealmModel realm, UserModel user) { private Stream<UserSessionModel> getUserSessionsFromPersistenceProviderStream(RealmModel realm, UserModel user) {
UserSessionPersisterProvider persister = session.getProvider(UserSessionPersisterProvider.class); UserSessionPersisterProvider persister = session.getProvider(UserSessionPersisterProvider.class);
return persister.loadUserSessionsStream(realm, user, true, 0, null) return persister.loadUserSessionsStream(realm, user, true, 0, null)
.map(persistentUserSession -> (UserSessionModel) getUserSession(realm, persistentUserSession.getId(), true)) .map(persistentUserSession -> (UserSessionModel) getUserSession(realm, persistentUserSession.getId(), persistentUserSession, true))
.filter(Objects::nonNull); .filter(Objects::nonNull);
} }
@ -318,7 +318,7 @@ public class PersistentUserSessionProvider implements UserSessionProvider, Sessi
if (user != null) { if (user != null) {
return persister.loadUserSessionsStream(realm, user, offline, 0, null) return persister.loadUserSessionsStream(realm, user, offline, 0, null)
.filter(predicate.toModelPredicate()) .filter(predicate.toModelPredicate())
.map(s -> (UserSessionModel) getUserSession(realm, s.getId(), offline)) .map(s -> (UserSessionModel) getUserSession(realm, s.getId(), s, offline))
.filter(Objects::nonNull); .filter(Objects::nonNull);
} else { } else {
return Stream.empty(); return Stream.empty();
@ -337,7 +337,7 @@ public class PersistentUserSessionProvider implements UserSessionProvider, Sessi
return userModel != null ? return userModel != null ?
persister.loadUserSessionsStream(realm, userModel, offline, 0, null) persister.loadUserSessionsStream(realm, userModel, offline, 0, null)
.filter(predicate.toModelPredicate()) .filter(predicate.toModelPredicate())
.map(s -> (UserSessionModel) getUserSession(realm, s.getId(), offline)) .map(s -> (UserSessionModel) getUserSession(realm, s.getId(), s, offline))
.filter(Objects::nonNull) : .filter(Objects::nonNull) :
Stream.empty(); Stream.empty();
} }
@ -346,7 +346,7 @@ public class PersistentUserSessionProvider implements UserSessionProvider, Sessi
ClientModel client = session.clients().getClientById(realm, predicate.getClient()); ClientModel client = session.clients().getClientById(realm, predicate.getClient());
return persister.loadUserSessionsStream(realm, client, offline, 0, null) return persister.loadUserSessionsStream(realm, client, offline, 0, null)
.filter(predicate.toModelPredicate()) .filter(predicate.toModelPredicate())
.map(s -> (UserSessionModel) getUserSession(realm, s.getId(), offline)) .map(s -> (UserSessionModel) getUserSession(realm, s.getId(), s, offline))
.filter(Objects::nonNull); .filter(Objects::nonNull);
} }
@ -354,7 +354,7 @@ public class PersistentUserSessionProvider implements UserSessionProvider, Sessi
// we haven't yet migrated the old offline entries, so they don't have a brokerSessionId yet // we haven't yet migrated the old offline entries, so they don't have a brokerSessionId yet
return Stream.of(persister.loadUserSessionsStreamByBrokerSessionId(realm, predicate.getBrokerSessionId(), false)) return Stream.of(persister.loadUserSessionsStreamByBrokerSessionId(realm, predicate.getBrokerSessionId(), false))
.filter(predicate.toModelPredicate()) .filter(predicate.toModelPredicate())
.map(s -> (UserSessionModel) getUserSession(realm, s.getId(), false)) .map(s -> (UserSessionModel) getUserSession(realm, s.getId(), s, false))
.filter(Objects::nonNull); .filter(Objects::nonNull);
} }
@ -412,7 +412,7 @@ public class PersistentUserSessionProvider implements UserSessionProvider, Sessi
@Override @Override
public UserSessionModel getUserSessionWithPredicate(RealmModel realm, String id, boolean offline, Predicate<UserSessionModel> predicate) { public UserSessionModel getUserSessionWithPredicate(RealmModel realm, String id, boolean offline, Predicate<UserSessionModel> predicate) {
UserSessionModel userSession = getUserSession(realm, id, offline); UserSessionModel userSession = getUserSession(realm, id, null, offline);
if (userSession == null) { if (userSession == null) {
return null; return null;
} }
@ -680,7 +680,7 @@ public class PersistentUserSessionProvider implements UserSessionProvider, Sessi
@Override @Override
public UserSessionAdapter getOfflineUserSession(RealmModel realm, String userSessionId) { public UserSessionAdapter getOfflineUserSession(RealmModel realm, String userSessionId) {
return getUserSession(realm, userSessionId, true); return getUserSession(realm, userSessionId, null, true);
} }
@Override @Override

View file

@ -52,7 +52,7 @@ public class UserSessionPersistentChangelogBasedTransaction extends PersistentSe
super(session, USER_SESSION_CACHE_NAME, cache, offlineCache, remoteCacheInvoker, lifespanMsLoader, maxIdleTimeMsLoader, offlineLifespanMsLoader, offlineMaxIdleTimeMsLoader, batchingQueue, serializerOnline, serializerOffline); super(session, USER_SESSION_CACHE_NAME, cache, offlineCache, remoteCacheInvoker, lifespanMsLoader, maxIdleTimeMsLoader, offlineLifespanMsLoader, offlineMaxIdleTimeMsLoader, batchingQueue, serializerOnline, serializerOffline);
} }
public SessionEntityWrapper<UserSessionEntity> get(RealmModel realm, String key, boolean offline) { public SessionEntityWrapper<UserSessionEntity> get(RealmModel realm, String key, UserSessionModel userSession, boolean offline) {
SessionUpdatesList<UserSessionEntity> myUpdates = getUpdates(offline).get(key); SessionUpdatesList<UserSessionEntity> myUpdates = getUpdates(offline).get(key);
if (myUpdates == null) { if (myUpdates == null) {
SessionEntityWrapper<UserSessionEntity> wrappedEntity = null; SessionEntityWrapper<UserSessionEntity> wrappedEntity = null;
@ -63,7 +63,7 @@ public class UserSessionPersistentChangelogBasedTransaction extends PersistentSe
if (wrappedEntity == null) { if (wrappedEntity == null) {
LOG.debugf("user-session not found in cache for sessionId=%s offline=%s, loading from persister", key, offline); LOG.debugf("user-session not found in cache for sessionId=%s offline=%s, loading from persister", key, offline);
wrappedEntity = getSessionEntityFromPersister(realm, key, offline); wrappedEntity = getSessionEntityFromPersister(realm, key, userSession, offline);
} else { } else {
LOG.debugf("user-session found in cache for sessionId=%s offline=%s %s", key, offline, wrappedEntity.getEntity().getLastSessionRefresh()); LOG.debugf("user-session found in cache for sessionId=%s offline=%s %s", key, offline, wrappedEntity.getEntity().getLastSessionRefresh());
} }
@ -96,15 +96,17 @@ public class UserSessionPersistentChangelogBasedTransaction extends PersistentSe
} }
} }
private SessionEntityWrapper<UserSessionEntity> getSessionEntityFromPersister(RealmModel realm, String key, boolean offline) { private SessionEntityWrapper<UserSessionEntity> getSessionEntityFromPersister(RealmModel realm, String key, UserSessionModel userSession, boolean offline) {
UserSessionPersisterProvider persister = kcSession.getProvider(UserSessionPersisterProvider.class); if (userSession == null) {
UserSessionModel persistentUserSession = persister.loadUserSession(realm, key, offline); UserSessionPersisterProvider persister = kcSession.getProvider(UserSessionPersisterProvider.class);
userSession = persister.loadUserSession(realm, key, offline);
}
if (persistentUserSession == null) { if (userSession == null) {
return null; return null;
} }
return importUserSession(persistentUserSession); return importUserSession(userSession);
} }
private SessionEntityWrapper<UserSessionEntity> importUserSession(UserSessionModel persistentUserSession) { private SessionEntityWrapper<UserSessionEntity> importUserSession(UserSessionModel persistentUserSession) {