Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
dreamstar-enterprises authored Sep 7, 2024
1 parent 0b57d4b commit 1253daf
Showing 1 changed file with 74 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.data.domain.Range
import org.springframework.data.redis.connection.Limit
import org.springframework.data.redis.connection.ReactiveRedisConnection
import org.springframework.data.redis.connection.ReturnType
import org.springframework.data.redis.core.ReactiveRedisOperations
import org.springframework.data.redis.core.script.RedisScript
import org.springframework.scheduling.annotation.EnableScheduling
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.session.config.ReactiveSessionRepositoryCustomizer
Expand Down Expand Up @@ -63,11 +66,16 @@ internal class SessionEvicter(
springSessionProperties: SpringSessionProperties,
) {

private val logger = LoggerFactory.getLogger(SessionEvicter::class.java)

private val redisKeyLocation = springSessionProperties.redis?.expiredSessionsNamespace
?: "spring:session:sessions:expirations"

companion object {
private const val duration : Long = 120
private const val LOCK_KEY = "session-cleanup-lock"
private val LOCK_EXPIRY: Duration = Duration.ofSeconds(duration)
private val logger = LoggerFactory.getLogger(SessionEvicter::class.java)
}

data class CleanupContext(
val now: Instant,
val pastFiveDays: Instant,
Expand All @@ -76,8 +84,70 @@ internal class SessionEvicter(
)

// run every 120 seconds
@Scheduled(fixedRate = 120, timeUnit = TimeUnit.SECONDS)
fun cleanup(): Mono<Void> {
@Scheduled(fixedRate = duration, timeUnit = TimeUnit.SECONDS)
fun cleanup() {
val lockValue = UUID.randomUUID().toString()

acquireLock(lockValue)
.flatMap { acquired ->
if (acquired) {
// Lock acquired, perform the cleanup task
performCleanup()
// release lock 10s before duration time
.then(Mono.delay(Duration.ofSeconds(duration - 10)))
.then(releaseLock(lockValue))
.onErrorResume { e ->
// Handle errors here
logger.error("Error during cleanup or lock release", e)
Mono.empty()
}
} else {
// Lock not acquired, skip cleanup
Mono.empty()
}
}
.onErrorResume { e ->
// Handle errors here
logger.error("Error during lock acquisition or cleanup", e)
Mono.empty()
}
.subscribe()
}

private fun acquireLock(lockValue: String): Mono<Boolean> {
val script = """
return redis.call('set', KEYS[1], ARGV[1], 'NX', 'EX', ARGV[2])
"""
val redisScript = RedisScript.of(script, String::class.java)
return redisOperations.execute(
redisScript,
listOf(LOCK_KEY),
listOf(lockValue, LOCK_EXPIRY.seconds.toString())
)
.next() // Converts Flux<String> to Mono<String>
.map { result -> result == "OK" }
}

private fun releaseLock(lockValue: String): Mono<Boolean> {
val script = """
if redis.call('get', KEYS[1]) == ARGV[1] then
return redis.call('del', KEYS[1])
else
return 0
end
"""
val redisScript = RedisScript.of(script, Long::class.java)
return redisOperations.execute(
redisScript,
listOf(LOCK_KEY),
listOf(lockValue)
)
.next() // Converts Flux<Long> to Mono<Long>
.map { result -> result == 1L }
}

// clean up sessions from expirations
private fun performCleanup(): Mono<Void> {
return Mono.fromCallable {
val now = Instant.now()
val pastFiveDays = now.minus(Duration.ofDays(5))
Expand Down

0 comments on commit 1253daf

Please sign in to comment.