Class RedisLockService

  • All Implemented Interfaces:

    
    public class RedisLockService
    
                        

    A reentrant, Redis based lock service

    The Redis clock is used as a time source such that all JVMs use the same source.

    • Constructor Detail

      • RedisLockService

        RedisLockService(RedisConnectionPool connectionPool, RedisPubSubService redisPubSubService, Boolean deadlockDetection, Integer expireLocksWhichShallNotBeKeptSeconds, Long pollDelayWhenWaitingForLockMs, String lockKeyPrefix, Long lockLeaseTimeSeconds, Long lockLeaseRenewalTimeSeconds, RedisLockService.LockServiceJsonHandler lockServiceJsonHandler, Function1<Runnable, Runnable> onNewThreadHandler)
        Parameters:
        connectionPool - the pool to be used for communicating with Redis
        redisPubSubService - optional RedisPubSubService to detect faster when other threads release a lock.
        deadlockDetection - if true, throws a RedisLockServiceDeadlockException if it detects that two or more threads wait to acquire locks that the other threads already own
        expireLocksWhichShallNotBeKeptSeconds - expire time in seconds for locks, for which keepLockDataAfterUse (see tryLock) was set to false.
        pollDelayWhenWaitingForLockMs - time to wait between attempts to acquire the locks.
        lockKeyPrefix - prefix that shall be used for all keys in Redis (namespacing)
        lockLeaseTimeSeconds - duration in seconds, for how long a lock should be marked as taken in Redis (lease time)
        lockLeaseRenewalTimeSeconds - duration in seconds, for how often the lease time should automatically be extended while the locks are being held.
        onNewThreadHandler - each time a new virtual thread is started for renewing the leases of an acquisition, this handler is used to wrap the Runnable.
    • Method Detail

      • stop

         final Unit stop()

        Stops the service, for example when the JVM is shutting down. hasLock returns false from now on, and waiting tryLock calls give up. The lock records are not released here, but when the protected code returns.

      • tryLock

         final <T extends Any> Pair<Boolean, T> tryLock(Collection<String> locks, Long timeoutMs, Boolean keepLockDataAfterUse, Function1<Function0<Boolean>, T> protectedCode)

        Tries to acquire all locks atomically and runs the protected code.

        While the lock is being held and the protected code is being executed, the lease is automatically renewed to ensure that the lock does not expire. The protected code can use the provided hasLock lambda to check if the lock is still being held. It should abort if this lambda returns false.

        The calling thread should preferably be a VirtualThread, because Thread.sleep() is used.

        Parameters:
        locks - that must all be acquired before running the protected code
        timeoutMs - max time to wait in case one or more of the requested locks are currently taken/unavailable
        keepLockDataAfterUse - if true, the lock data, stored in Redis, is kept after use.
        protectedCode - the code to be executed once all locks are acquired
        Returns:

        If the locks were acquired and the protected code was executed, then true+result is returned. If the locks could not be acquired within the timeout, then false+null is returned. That is also the case for a nested call, if one of the locks the current thread already holds was lost meanwhile (see hasLock) - it is not acquired again