Wasn't sure if this was a bug, or an issue my side, hence positing here: https://stackoverflow.com/questions/78894596/spring-session-webflux-redis-session-clean-up-evicter-not-working
Describe the bug I've followed the main documentation guidance with the following code, for cleaning sessions using Spring Session
@Configuration
@EnableScheduling
internal class RedisCleanUpConfig {
/**
* No specific configuration or action should be taken regarding Redis keyspace notifications.
*/
@Bean
fun configureReactiveRedisAction(): ConfigureReactiveRedisAction {
return ConfigureReactiveRedisAction.NO_OP
}
/**
* Disables the default clean up task
*/
@Bean
fun reactiveSessionRepositoryCustomizer(): ReactiveSessionRepositoryCustomizer<ReactiveRedisIndexedSessionRepository> {
return ReactiveSessionRepositoryCustomizer { sessionRepository: ReactiveRedisIndexedSessionRepository ->
sessionRepository.disableCleanupTask()
}
}
}
/**
* For cleanup operations (i.e. removing expired session from a ZSet (Sorted Sets) in Redis)
* Spring's scheduling mechanism will automatically call the cleanup method according to the schedule
* defined by the @Scheduled annotation.
*/
@Component
internal class SessionEvicter(
private val redisOperations: ReactiveRedisOperations<String, String>,
springSessionProperties: SpringSessionProperties,
) {
private val logger = LoggerFactory.getLogger(SessionEvicter::class.java)
private val redisKeyLocation = springSessionProperties.redis?.expiredSessionsNameSpace
?: "spring:session:sessions:expirations"
// run every 120 seconds
@Scheduled(fixedRate = 120, timeUnit = TimeUnit.SECONDS)
fun cleanup(): Mono<Void> {
val now = Instant.now()
val pastFiveMinutes = now.minus(Duration.ofMinutes(5))
val range = Range.closed(
(pastFiveMinutes.toEpochMilli()).toDouble(),
(now.toEpochMilli()).toDouble()
)
val limit = Limit.limit().count(500)
// get the ZSet (Sorted Set) operations
val zSetOps = redisOperations.opsForZSet()
return zSetOps.reverseRangeByScore(redisKeyLocation, range, limit)
.collectList()
.flatMap { sessionIdsList ->
if (sessionIdsList.isNotEmpty()) {
logger.info("Found ${sessionIdsList.size} sessions to remove.")
val removal = zSetOps.remove(
redisKeyLocation,
*sessionIdsList.toTypedArray()
)
removal
} else {
logger.info("No sessions found to remove.")
Mono.empty()
}
}
.doOnSuccess {
logger.info("Cleanup operation completed.")
}
.doOnError { e ->
logger.error("Error during cleanup operation: ${e.message}")
}
.then()
}
}
For some reason the sessions don't really get deleted. The sorted set just keeps building up. Is that by design.
I do get a message from Netty server about whether sessions were found to delete or not, very 120s. It always says none were found.
Any ideas where I am maybe wrong?
The specific class file can be found here: https://github.com/dreamstar-enterprises/docs/blob/master/Spring%20BFF/bff/auth/sessions/RedisSessionCleanUpConfig.kt
The full repo can be found here: https://github.com/dreamstar-enterprises/docs/tree/master/Spring%20BFF/bff
44 sessions - none have been deleted?
Comment From: philwebb
Thanks for getting in touch, but it feels like this is a question that would be better suited to Stack Overflow. As mentioned in the guidelines for contributing, we prefer to use GitHub issues only for bugs and enhancements. Feel free to update this issue with a link to the re-posted question (so that other people can find it) or add some more details if you feel this is a genuine bug.
Comment From: dreamstar-enterprises
Hmmm. ok thanks Phil. It does look like a bug to me : ( I'll post it on stack overflow.
Comment From: philwebb
If it is a bug, it's unlikely to be in Spring Boot itself. We're involved with configuring libraries like Spring Session, but the low level features they provide are handled directly in those projects.