From d5eb076dc2b8bb9c4ce46578663e2ef0d3546dbc Mon Sep 17 00:00:00 2001 From: Nilendu Bhattacharya Date: Wed, 27 Sep 2023 14:23:05 -0500 Subject: [PATCH] Adding extendLockExpiration function --- .../rediculous/concurrent/RedisLock.scala | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/core/shared/src/main/scala/io/chrisdavenport/rediculous/concurrent/RedisLock.scala b/core/shared/src/main/scala/io/chrisdavenport/rediculous/concurrent/RedisLock.scala index afa1097..4b582b6 100644 --- a/core/shared/src/main/scala/io/chrisdavenport/rediculous/concurrent/RedisLock.scala +++ b/core/shared/src/main/scala/io/chrisdavenport/rediculous/concurrent/RedisLock.scala @@ -62,6 +62,34 @@ object RedisLock { } } + /** + * Extends the lock expiration + * @return Returns true if identifier owns the lock and extends it; false if not the owner + */ + def extendLockExpiration[F[_]: Async]( + connection: RedisConnection[F], + lockname: String, + identifier: UUID, + lockTimeout: FiniteDuration + ): F[Boolean] = { + val lockName = "lock:" ++ lockname + (RedisCtx[RedisPipeline].keyed[Status](lockName, NonEmptyList.of("WATCH", lockName)) *> + RedisCommands.get[RedisPipeline](lockName)).pipeline.run(connection).flatMap { + case Some(value) if value === identifier.toString => + RedisCommands + .expire[RedisTransaction](lockName, lockTimeout.toSeconds) + .transact + .run(connection) + .flatMap { + case Success(_) => Applicative[F].pure(true) + case Aborted => extendLockExpiration(connection, lockName, identifier, lockTimeout) + case Error(value) => + new Throwable(s"lock expiration extension for $lockName encountered error $value").raiseError[F, Boolean] + } + case _ => Applicative[F].pure(false) + } + } + def tryAcquireLockWithTimeout[F[_]: Async: UUIDGen]( connection: RedisConnection[F], lockname: String,