From 9eea22a091383c971fb903926f429830497f3566 Mon Sep 17 00:00:00 2001 From: YisraelU Date: Tue, 1 Oct 2024 00:25:07 -0400 Subject: [PATCH] add unlink and random key commands --- .../main/scala/dev/profunktor/redis4cats/algebra/keys.scala | 3 +++ .../src/main/scala/dev/profunktor/redis4cats/redis.scala | 6 ++++++ .../scala/dev/profunktor/redis4cats/TestScenarios.scala | 2 ++ 3 files changed, 11 insertions(+) diff --git a/modules/effects/src/main/scala/dev/profunktor/redis4cats/algebra/keys.scala b/modules/effects/src/main/scala/dev/profunktor/redis4cats/algebra/keys.scala index a553ecc7..938fb1c7 100644 --- a/modules/effects/src/main/scala/dev/profunktor/redis4cats/algebra/keys.scala +++ b/modules/effects/src/main/scala/dev/profunktor/redis4cats/algebra/keys.scala @@ -35,6 +35,7 @@ trait KeyCommands[F[_], K] { def objectIdletime(key: K): F[Option[FiniteDuration]] def persist(key: K): F[Boolean] def pttl(key: K): F[Option[FiniteDuration]] + def randomKey: F[Option[K]] // restores a key with the given serialized value, previously obtained using DUMP without a ttl def restore(key: K, value: Array[Byte]): F[Unit] def restore(key: K, value: Array[Byte], restoreArgs: RestoreArgs): F[Unit] @@ -48,5 +49,7 @@ trait KeyCommands[F[_], K] { def scan(previous: KeyScanCursor[K], scanArgs: ScanArgs): F[KeyScanCursor[K]] def typeOf(key: K): F[Option[RedisType]] def ttl(key: K): F[Option[FiniteDuration]] + //This command is very similar to DEL: it removes the specified keys. Just like DEL a key is ignored if it does not exist. However the command performs the actual memory reclaiming in a different thread, so it is not blocking, while DEL is. This is where the command name comes from: the command just unlinks the keys from the keyspace. The actual removal will happen later asynchronously. + def unlink(key: K*): F[Long] } diff --git a/modules/effects/src/main/scala/dev/profunktor/redis4cats/redis.scala b/modules/effects/src/main/scala/dev/profunktor/redis4cats/redis.scala index 59c4878b..7f5025f6 100644 --- a/modules/effects/src/main/scala/dev/profunktor/redis4cats/redis.scala +++ b/modules/effects/src/main/scala/dev/profunktor/redis4cats/redis.scala @@ -544,6 +544,9 @@ private[redis4cats] class BaseRedis[F[_]: FutureLift: MonadThrow: Log, K, V]( override def pttl(key: K): F[Option[FiniteDuration]] = async.flatMap(_.pttl(key).futureLift.map(toFiniteDuration(TimeUnit.MILLISECONDS))) + override def randomKey: F[Option[K]] = + async.flatMap(_.randomkey().futureLift.map(Option(_))) + override def restore(key: K, value: Array[Byte]): F[Unit] = async.flatMap(_.restore(key, 0, value).futureLift.void) @@ -574,6 +577,9 @@ private[redis4cats] class BaseRedis[F[_]: FutureLift: MonadThrow: Log, K, V]( override def typeOf(key: K): F[Option[RedisType]] = async.flatMap(_.`type`(key).futureLift.map(RedisType.fromString)) + override def unlink(key: K*): F[Long] = + async.flatMap(_.unlink(key: _*).futureLift.map(x => Long.box(x))) + /******************************* Transactions API **********************************/ // When in a cluster, transactions should run against a single node. diff --git a/modules/tests/src/test/scala/dev/profunktor/redis4cats/TestScenarios.scala b/modules/tests/src/test/scala/dev/profunktor/redis4cats/TestScenarios.scala index 88724aeb..526bc339 100644 --- a/modules/tests/src/test/scala/dev/profunktor/redis4cats/TestScenarios.scala +++ b/modules/tests/src/test/scala/dev/profunktor/redis4cats/TestScenarios.scala @@ -233,6 +233,8 @@ trait TestScenarios { self: FunSuite => _ <- redis.set(key1, "some value") exist2 <- redis.exists(key1) _ <- IO(assert(exist2)) + rkey <- redis.randomKey + _ <- IO(assertEquals(rkey, Some(key1))) dump <- redis.dump(key1) _ <- IO(assert(dump.nonEmpty)) _ <- redis.restore(key1, dump.get, RestoreArgs().replace(true))