Skip to content

Touch expires key in SortedSetRedisSessionExpirationStore - #3870

Open
lsh1215 wants to merge 1 commit into
spring-projects:4.0.xfrom
lsh1215:fix/gh-3468-sortedset-expires-key
Open

Touch expires key in SortedSetRedisSessionExpirationStore#3870
lsh1215 wants to merge 1 commit into
spring-projects:4.0.xfrom
lsh1215:fix/gh-3468-sortedset-expires-key

Conversation

@lsh1215

@lsh1215 lsh1215 commented Jul 24, 2026

Copy link
Copy Markdown

SortedSetRedisSessionExpirationStore#cleanupExpiredSessions touches the session key (<namespace>:sessions:<id>) instead of the expires shadow key (<namespace>:sessions:expires:<id>).

RedisIndexedSessionRepository#onMessage only handles keyspace events whose key starts with the sessions:expires: prefix. Because the store touches the session key, expiration does not produce an event that matches that prefix, so SessionDeletedEvent and SessionExpiredEvent are not published for sessions tracked by this store. The principal index cleanup and the removal from the expiration sorted set run from that same onMessage handler, so they do not happen either.

This affects RedisIndexedSessionRepository when it is configured with SortedSetRedisSessionExpirationStore. MinuteBasedRedisSessionExpirationStore and the reactive SortedSetReactiveRedisSessionExpirationStore both touch the expires key and are not affected.

Change

cleanupExpiredSessions now touches <namespace>:sessions:expires:<id>, which matches the prefix that onMessage listens on and is consistent with the other two stores. The existing private helper was renamed from getSessionKey to getExpiredKey to reflect the key it builds and to match the naming used in RedisIndexedSessionRepository and ReactiveRedisIndexedSessionRepository.

Testing

  • Updated SortedSetRedisSessionExpirationStoreTests#cleanupExpiredSessionsThenTouchExpiredSessions to assert that the expires key is touched. It fails before the change and passes after.
  • ./gradlew :spring-session-data-redis:test passes.
  • ./gradlew :spring-session-data-redis:integrationTest --tests "*SortedSetRedisSessionExpirationStoreITests" passes.
  • checkstyle and Spring Java Format checks pass for the changed files.

Closes gh-3468

cc @rwinch

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jul 24, 2026
@lsh1215
lsh1215 changed the base branch from 3.5.x to 4.0.x August 11, 2026 20:35
cleanupExpiredSessions touched the session key (<namespace>:sessions:<id>)
instead of the expires shadow key (<namespace>:sessions:expires:<id>).
RedisIndexedSessionRepository#onMessage only reacts to key events whose key
starts with the "sessions:expires:" prefix, so touching the session key never
triggered a SessionDeletedEvent/SessionExpiredEvent for sessions tracked by
this store.

Touch the expires key instead, consistent with
MinuteBasedRedisSessionExpirationStore and the reactive
SortedSetReactiveRedisSessionExpirationStore.

Closes spring-projectsgh-3468

Signed-off-by: sanghun <[email protected]>
@lsh1215
lsh1215 force-pushed the fix/gh-3468-sortedset-expires-key branch from 12d174b to e7cb94f Compare August 11, 2026 20:35
@lsh1215

lsh1215 commented Aug 11, 2026

Copy link
Copy Markdown
Author

@rwinch flagging this as @marcusdacoregio suggested on #3468.

I've retargeted this from 3.5.x to 4.0.x — 3.5.x left OSS support on Jun 30, so my original base was wrong. Rebased cleanly onto 4.0.x; the change itself is unchanged (one commit, two files), and the bug is present on main too.

SortedSetRedisSessionExpirationStore#cleanupExpiredSessions touches the session key instead of the sessions:expires: shadow key, so expiration never produces a keyspace event matching the prefix RedisIndexedSessionRepository#onMessage listens for — no SessionExpiredEvent/SessionDeletedEvent, and the principal-index cleanup that runs from the same handler doesn't happen either.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status: waiting-for-triage An issue we've not yet triaged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants