com.himadieiev.redpulsar.lettuce.locks.backends.LettuceLocksBackend.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of redpulsar-lettuce Show documentation
Show all versions of redpulsar-lettuce Show documentation
RedPulsar Distributed locks and utilities for Redis with Lettuce client
The newest version!
package com.himadieiev.redpulsar.lettuce.locks.backends
import com.himadieiev.redpulsar.core.common.CLEAN_UP_EXPIRED_SEMAPHORE_LOCKS_SCRIPT_PATH
import com.himadieiev.redpulsar.core.common.REMOVE_LOCK_SCRIPT_PATH
import com.himadieiev.redpulsar.core.common.SET_SEMAPHORE_LOCK_SCRIPT_PATH
import com.himadieiev.redpulsar.core.common.loadScript
import com.himadieiev.redpulsar.core.locks.abstracts.backends.LocksBackend
import com.himadieiev.redpulsar.core.utils.failsafe
import com.himadieiev.redpulsar.lettuce.abstracts.LettuceUnified
import io.lettuce.core.ScriptOutputType
import io.lettuce.core.SetArgs
import java.time.Duration
/**
* An implementation of [LocksBackend] that uses Redis as a storage.
*/
internal class LettuceLocksBackend(private val redis: LettuceUnified) : LocksBackend() {
override fun setLock(
resourceName: String,
clientId: String,
ttl: Duration,
): String? {
val args = SetArgs().nx().px(ttl.toMillis())
return failsafe(null) {
redis.sync { sync -> sync.set(resourceName, clientId, args) }
}
}
override fun removeLock(
resourceName: String,
clientId: String,
): String? {
val luaScript = loadScript(REMOVE_LOCK_SCRIPT_PATH)
return failsafe(null) {
convertToString(
redis.sync { sync -> sync.eval(luaScript, ScriptOutputType.INTEGER, arrayOf(resourceName), clientId) },
)
}
}
override fun setSemaphoreLock(
leasersKey: String,
leaserValidityKey: String,
clientId: String,
maxLeases: Int,
ttl: Duration,
): String? {
val luaScript = loadScript(SET_SEMAPHORE_LOCK_SCRIPT_PATH)
return failsafe(null) {
convertToString(
redis.sync { sync ->
sync.eval(
luaScript,
ScriptOutputType.VALUE,
arrayOf(leasersKey, leaserValidityKey),
clientId,
maxLeases.toString(),
ttl.toMillis().toString(),
)
},
)
}
}
override fun removeSemaphoreLock(
leasersKey: String,
leaserValidityKey: String,
clientId: String,
): String? =
failsafe(null) {
redis.sync { sync ->
sync.srem(leasersKey, clientId)
sync.del(leaserValidityKey)
// Regardless return values success execution counts as operation completed.
return@sync "OK"
}
}
override fun cleanUpExpiredSemaphoreLocks(
leasersKey: String,
leaserValidityKeyPrefix: String,
): String? {
val luaScript = loadScript(CLEAN_UP_EXPIRED_SEMAPHORE_LOCKS_SCRIPT_PATH)
return failsafe(null) {
convertToString(
redis.sync { sync ->
sync.eval(
luaScript,
ScriptOutputType.STATUS,
arrayOf(leasersKey),
leaserValidityKeyPrefix,
)
},
)
}
}
}