Description
Before reporting an issue
- I have read and understood the above terms for submitting issues, and I understand that my issue may be closed without action if I do not follow them.
Area
infinispan
Describe the bug
If the offline userSession does not exist in the cache, then under certain conditions, this process will delete the userSession and the clientSession from the database : InfinispanUserSessionProvider.java#L295
Version
22.0.5
Regression
- The issue is a regression
Expected behavior
userSession offline and clientSession offline not deleted from the database
Actual behavior
userSession offline and clientSession offline deleted from the database
How to Reproduce?
Modify the max-count attribute of the offlineSessions cache. Set it to 1, for example, to facilitate reproduction :
<distributed-cache name="offlineSessions" owners="2">
<expiration lifespan="as_you_want"/>
<memory max-count="1"/>
</distributed-cache>
To reproduce the issue, you need to use breakpoints: place the first breakpoint here and the second one there.
The goal is to have two userSessions that will mutually remove each other from the cache, and in the end, the first userSession will be deleted from the database.
1 - Generate two offline token for two different users
2 - Enable the breakpoints and refresh the first offline token using a call with grant_type = refresh_token. (At the first breakpoint, check that userSessionEntityFromCache
is null. If it is not, skip the breakpoints and start again with the second offline token). From now on, we will refer to this token as Token A.
3 - On the thread of Token A, proceed to the second breakpoint. Since the offline userSession was not in the cache, this step will store it in the cache, and as a result, the other session will no longer be in the cache.
4 - Now refresh the other offline token using a call with grant_type = refresh_token. We will refer to this token as Token B. And skip all breakpoint for this token B.
5 - Now, the userSession of Token B is the one present in the cache. Complete the last breakpoint on the thread of Token A, and you will observe that its userSession is deleted from the database
Anything else?
If you don't see any side effects, we could put this in a critical section:
private UserSessionEntity importUserSession(RealmModel realm, boolean offline, UserSessionModel persistentUserSession) {
String sessionId = persistentUserSession.getId();
log.debugf("Attempting to import user-session for sessionId=%s offline=%s", sessionId, offline);
session.sessions().importUserSessions(Collections.singleton(persistentUserSession), offline);
log.debugf("user-session imported, trying another lookup for sessionId=%s offline=%s", sessionId, offline);
UserSessionEntity ispnUserSessionEntity = getUserSessionEntity(realm, sessionId, offline);
if (ispnUserSessionEntity != null) {
log.debugf("user-session found after import for sessionId=%s offline=%s", sessionId, offline);
return ispnUserSessionEntity;
}
log.debugf("user-session could not be found after import for sessionId=%s offline=%s", sessionId, offline);
return null;
}