未验证 提交 9283ff94 编写于 作者: D Dragutin Marjanović 提交者: GitHub

Sort methods in 'api' package (#822)

上级 6e578997
......@@ -38,28 +38,24 @@ trait Cluster extends RedisEnvironment {
AskingCommand(executor).run(())
/**
* Returns details about which cluster slots map to which Redis instances.
*
* @return
* details about which cluster
*/
final def slots: IO[RedisError, Chunk[Partition]] = {
val command = RedisCommand(ClusterSlots, NoInput, ChunkOutput(ClusterPartitionOutput), executor)
command.run(())
}
/**
* Clear any importing / migrating state from hash slot.
* Set a hash slot in importing state. Command should be executed on the node where hash slot will be migrated
* (destination node)
*
* @param slot
* hash slot that will be cleared
* hash slot that will be set in importing state
* @param nodeId
* the source node Id from which hash slot will be imported
* @return
* the Unit value.
*/
final def setSlotStable(slot: Slot): IO[RedisError, Unit] = {
val command =
RedisCommand(ClusterSetSlots, Tuple2(LongInput, ArbitraryValueInput[String]()), UnitOutput, executor)
command.run((slot.number, Stable.asString))
final def setSlotImporting(slot: Slot, nodeId: String): IO[RedisError, Unit] = {
val command = RedisCommand(
ClusterSetSlots,
Tuple3(LongInput, ArbitraryValueInput[String](), ArbitraryValueInput[String]()),
UnitOutput,
executor
)
command.run((slot.number, Importing.asString, nodeId))
}
/**
......@@ -84,53 +80,57 @@ trait Cluster extends RedisEnvironment {
}
/**
* Set a hash slot in importing state. Command should be executed on the node where hash slot will be migrated
* (destination node)
* Bind the hash slot to a different node. It associates the hash slot with the specified node, however the command
* works only in specific situations and has different side effects depending on the slot state.
*
* @param slot
* hash slot that will be set in importing state
* hash slot that will be bind
* @param nodeId
* the source node Id from which hash slot will be imported
* the destination node Id where slot have been migrated
* @return
* the Unit value.
*/
final def setSlotImporting(slot: Slot, nodeId: String): IO[RedisError, Unit] = {
final def setSlotNode(slot: Slot, nodeId: String): IO[RedisError, Unit] = {
val command = RedisCommand(
ClusterSetSlots,
Tuple3(LongInput, ArbitraryValueInput[String](), ArbitraryValueInput[String]()),
UnitOutput,
executor
)
command.run((slot.number, Importing.asString, nodeId))
command.run((slot.number, Node.asString, nodeId))
}
/**
* Bind the hash slot to a different node. It associates the hash slot with the specified node, however the command
* works only in specific situations and has different side effects depending on the slot state.
* Clear any importing / migrating state from hash slot.
*
* @param slot
* hash slot that will be bind
* @param nodeId
* the destination node Id where slot have been migrated
* hash slot that will be cleared
* @return
* the Unit value.
*/
final def setSlotNode(slot: Slot, nodeId: String): IO[RedisError, Unit] = {
val command = RedisCommand(
ClusterSetSlots,
Tuple3(LongInput, ArbitraryValueInput[String](), ArbitraryValueInput[String]()),
UnitOutput,
executor
)
command.run((slot.number, Node.asString, nodeId))
final def setSlotStable(slot: Slot): IO[RedisError, Unit] = {
val command =
RedisCommand(ClusterSetSlots, Tuple2(LongInput, ArbitraryValueInput[String]()), UnitOutput, executor)
command.run((slot.number, Stable.asString))
}
/**
* Returns details about which cluster slots map to which Redis instances.
*
* @return
* details about which cluster
*/
final def slots: IO[RedisError, Chunk[Partition]] = {
val command = RedisCommand(ClusterSlots, NoInput, ChunkOutput(ClusterPartitionOutput), executor)
command.run(())
}
}
private[redis] object Cluster {
final val Asking = "ASKING"
final val ClusterSlots = "CLUSTER SLOTS"
final val ClusterSetSlots = "CLUSTER SETSLOT"
final val ClusterSlots = "CLUSTER SLOTS"
final val AskingCommand: (RedisExecutor) => RedisCommand[Unit, Unit] =
final val AskingCommand: RedisExecutor => RedisCommand[Unit, Unit] =
(executor: RedisExecutor) => RedisCommand(Asking, NoInput, UnitOutput, executor)
}
......@@ -75,6 +75,30 @@ trait Connection extends RedisEnvironment {
command.run(track)
}
/**
* Returns the name of the current connection as set by clientSetName
*
* @return
* the connection name, or None if a name wasn't set.
*/
final def clientGetName: IO[RedisError, Option[String]] = {
val command = RedisCommand(ClientGetName, NoInput, OptionalOutput(MultiStringOutput), executor)
command.run(())
}
/**
* Returns the client ID we are redirecting our tracking notifications to
*
* @return
* the client ID if the tracking is enabled and the notifications are being redirected
*/
final def clientGetRedir: IO[RedisError, ClientTrackingRedirect] = {
val command = RedisCommand(ClientGetRedir, NoInput, ClientTrackingRedirectOutput, executor)
command.run(())
}
/**
* Returns the ID of the current connection. Every connection ID has certain guarantees:
* - It is never repeated, so if clientID returns the same number, the caller can be sure that the underlying client
......@@ -170,41 +194,6 @@ trait Connection extends RedisEnvironment {
command.run((clientType, clientIds))
}
/**
* Returns the name of the current connection as set by clientSetName
*
* @return
* the connection name, or None if a name wasn't set.
*/
final def clientGetName: IO[RedisError, Option[String]] = {
val command = RedisCommand(ClientGetName, NoInput, OptionalOutput(MultiStringOutput), executor)
command.run(())
}
/**
* Returns the client ID we are redirecting our tracking notifications to
*
* @return
* the client ID if the tracking is enabled and the notifications are being redirected
*/
final def clientGetRedir: IO[RedisError, ClientTrackingRedirect] = {
val command = RedisCommand(ClientGetRedir, NoInput, ClientTrackingRedirectOutput, executor)
command.run(())
}
/**
* Resumes command processing for all clients that were paused by clientPause
* @return
* the Unit value.
*/
final def clientUnpause: IO[RedisError, Unit] = {
val command = RedisCommand(ClientUnpause, NoInput, UnitOutput, executor)
command.run(())
}
/**
* Able to suspend all the Redis clients for the specified amount of time (in milliseconds). Currently supports two
* modes:
......@@ -246,6 +235,29 @@ trait Connection extends RedisEnvironment {
command.run(name)
}
/**
* Returns information about the current client connection's use of the server assisted client side caching feature
*
* @return
* tracking information.
*/
final def clientTrackingInfo: IO[RedisError, ClientTrackingInfo] = {
val command = RedisCommand(ClientTrackingInfo, NoInput, ClientTrackingInfoOutput, executor)
command.run(())
}
/**
* Disables the tracking feature of the Redis server, that is used for server assisted client side caching
*
* @return
* the Unit value.
*/
final def clientTrackingOff: IO[RedisError, Unit] = {
val command = RedisCommand(ClientTracking, ClientTrackingInput, UnitOutput, executor)
command.run(None)
}
/**
* Enables the tracking feature of the Redis server, that is used for server assisted client side caching. The feature
* will remain active in the current connection for all its life, unless tracking is turned off with clientTrackingOff
......@@ -271,29 +283,6 @@ trait Connection extends RedisEnvironment {
command.run(Some((redirect, trackingMode, noLoop, Chunk.fromIterable(prefixes))))
}
/**
* Disables the tracking feature of the Redis server, that is used for server assisted client side caching
*
* @return
* the Unit value.
*/
final def clientTrackingOff: IO[RedisError, Unit] = {
val command = RedisCommand(ClientTracking, ClientTrackingInput, UnitOutput, executor)
command.run(None)
}
/**
* Returns information about the current client connection's use of the server assisted client side caching feature
*
* @return
* tracking information.
*/
final def clientTrackingInfo: IO[RedisError, ClientTrackingInfo] = {
val command = RedisCommand(ClientTrackingInfo, NoInput, ClientTrackingInfoOutput, executor)
command.run(())
}
/**
* Unblocks, from a different connection, a client blocked in a blocking operation
*
......@@ -314,6 +303,18 @@ trait Connection extends RedisEnvironment {
command.run((clientId, error))
}
/**
* Resumes command processing for all clients that were paused by clientPause
*
* @return
* the Unit value.
*/
final def clientUnpause: IO[RedisError, Unit] = {
val command = RedisCommand(ClientUnpause, NoInput, UnitOutput, executor)
command.run(())
}
/**
* Echoes the given string.
*
......@@ -389,18 +390,18 @@ trait Connection extends RedisEnvironment {
private[redis] object Connection {
final val Auth = "AUTH"
final val ClientCaching = "CLIENT CACHING"
final val ClientGetName = "CLIENT GETNAME"
final val ClientGetRedir = "CLIENT GETREDIR"
final val ClientId = "CLIENT ID"
final val ClientInfo = "CLIENT INFO"
final val ClientKill = "CLIENT KILL"
final val ClientList = "CLIENT LIST"
final val ClientGetName = "CLIENT GETNAME"
final val ClientGetRedir = "CLIENT GETREDIR"
final val ClientUnpause = "CLIENT UNPAUSE"
final val ClientPause = "CLIENT PAUSE"
final val ClientSetName = "CLIENT SETNAME"
final val ClientTracking = "CLIENT TRACKING"
final val ClientTrackingInfo = "CLIENT TRACKINGINFO"
final val ClientUnblock = "CLIENT UNBLOCK"
final val ClientUnpause = "CLIENT UNPAUSE"
final val Echo = "ECHO"
final val Ping = "PING"
final val Quit = "QUIT"
......
......@@ -207,6 +207,47 @@ trait Hashes extends RedisEnvironment {
}
}
/**
* Returns a random field from the hash value stored at `key`
*
* @param key
* of the hash which fields should be read
* @return
* random field in the hash or `None` when `key` does not exist.
*/
final def hRandField[K: Schema](key: K): ResultBuilder1[Option] =
new ResultBuilder1[Option] {
def returning[V: Schema]: IO[RedisError, Option[V]] =
RedisCommand(HRandField, ArbitraryKeyInput[K](), OptionalOutput(ArbitraryOutput[V]()), executor).run(key)
}
/**
* Returns an array of at most `count` distinct fields randomly. If called with a negative `count`, the command will
* return exactly `count` fields, allowing repeats. If `withValues` is true it will return fields with his values
* intercalated.
*
* @param key
* of the hash which fields should be read
* @param count
* maximum number of different fields to return if positive or the exact number, in absolute value if negative
* @param withValues
* when true includes the respective values of the randomly selected hash fields
* @return
* a list of fields or fields and values if `withValues` is true.
*/
final def hRandField[K: Schema](key: K, count: Long, withValues: Boolean = false): ResultBuilder1[Chunk] =
new ResultBuilder1[Chunk] {
def returning[V: Schema]: IO[RedisError, Chunk[V]] = {
val command = RedisCommand(
HRandField,
Tuple3(ArbitraryKeyInput[K](), LongInput, OptionalInput(StringInput)),
ChunkOutput(ArbitraryOutput[V]()),
executor
)
command.run((key, count, if (withValues) Some("WITHVALUES") else None))
}
}
/**
* Sets the specified `field -> value` pairs in the hash stored at `key`. Deprecated: As per Redis 4.0.0, HMSET is
* considered deprecated. Please use `hSet` instead.
......@@ -348,47 +389,6 @@ trait Hashes extends RedisEnvironment {
def returning[V: Schema]: IO[RedisError, Chunk[V]] =
RedisCommand(HVals, ArbitraryKeyInput[K](), ChunkOutput(ArbitraryOutput[V]()), executor).run(key)
}
/**
* Returns a random field from the hash value stored at `key`
*
* @param key
* of the hash which fields should be read
* @return
* random field in the hash or `None` when `key` does not exist.
*/
final def hRandField[K: Schema](key: K): ResultBuilder1[Option] =
new ResultBuilder1[Option] {
def returning[V: Schema]: IO[RedisError, Option[V]] =
RedisCommand(HRandField, ArbitraryKeyInput[K](), OptionalOutput(ArbitraryOutput[V]()), executor).run(key)
}
/**
* Returns an array of at most `count` distinct fields randomly. If called with a negative `count`, the command will
* return exactly `count` fields, allowing repeats. If `withValues` is true it will return fields with his values
* intercalated.
*
* @param key
* of the hash which fields should be read
* @param count
* maximum number of different fields to return if positive or the exact number, in absolute value if negative
* @param withValues
* when true includes the respective values of the randomly selected hash fields
* @return
* a list of fields or fields and values if `withValues` is true.
*/
final def hRandField[K: Schema](key: K, count: Long, withValues: Boolean = false): ResultBuilder1[Chunk] =
new ResultBuilder1[Chunk] {
def returning[V: Schema]: IO[RedisError, Chunk[V]] = {
val command = RedisCommand(
HRandField,
Tuple3(ArbitraryKeyInput[K](), LongInput, OptionalInput(StringInput)),
ChunkOutput(ArbitraryOutput[V]()),
executor
)
command.run((key, count, if (withValues) Some("WITHVALUES") else None))
}
}
}
private[redis] object Hashes {
......@@ -401,11 +401,11 @@ private[redis] object Hashes {
final val HKeys = "HKEYS"
final val HLen = "HLEN"
final val HmGet = "HMGET"
final val HRandField = "HRANDFIELD"
final val HmSet = "HMSET"
final val HScan = "HSCAN"
final val HSet = "HSET"
final val HSetNx = "HSETNX"
final val HStrLen = "HSTRLEN"
final val HVals = "HVALS"
final val HRandField = "HRANDFIELD"
}
......@@ -467,7 +467,7 @@ trait Keys extends RedisEnvironment {
alpha: Option[Alpha] = None
): IO[RedisError, Long] = {
val command = RedisCommand(
SortStore,
Sort,
Tuple7(
ArbitraryKeyInput[K](),
OptionalInput(ByInput),
......@@ -579,7 +579,6 @@ private[redis] object Keys {
final val Restore = "RESTORE"
final val Scan = "SCAN"
final val Sort = "SORT"
final val SortStore = "SORT"
final val Touch = "TOUCH"
final val Ttl = "TTL"
final val TypeOf = "TYPE"
......
......@@ -27,6 +27,105 @@ import zio.schema.Schema
trait Lists extends RedisEnvironment {
import Lists._
/**
* BLMOVE is the blocking variant of LMOVE. When source contains elements, this command behaves exactly like LMOVE.
* When used inside a MULTI/EXEC block, this command behaves exactly like [[zio.redis.api.Lists#lMove]]. When source
* is empty, Redis will block the connection until another client pushes to it or until timeout is reached. A timeout
* of zero can be used to block indefinitely.
*
* @param source
* the key where the element is removed
* @param destination
* the key where the element is inserted
* @param sourceSide
* the side where the element is removed
* @param destinationSide
* the side where the element is inserted
* @param timeout
* the timeout in seconds
* @return
* the element which is moved or nil when the timeout is reached.
*/
final def blMove[S: Schema, D: Schema](
source: S,
destination: D,
sourceSide: Side,
destinationSide: Side,
timeout: Duration
): ResultBuilder1[Option] =
new ResultBuilder1[Option] {
def returning[V: Schema]: IO[RedisError, Option[V]] = {
val command = RedisCommand(
BlMove,
Tuple5(ArbitraryValueInput[S](), ArbitraryValueInput[D](), SideInput, SideInput, DurationSecondsInput),
OptionalOutput(ArbitraryOutput[V]()),
executor
)
command.run((source, destination, sourceSide, destinationSide, timeout))
}
}
/**
* Removes and gets the first element in a list, or blocks until one is available. An element is popped from the head
* of the first list that is non-empty, with the given keys being checked in the order that they are given.
*
* @param key
* the key identifier of the first list to be checked
* @param keys
* the key identifiers of the rest of the lists
* @param timeout
* the maximum time to wait until an element is available. A timeout of zero can be used to block indefinitely
* @return
* a tuple with the first element being the name of the key where an element was popped and the second element being
* the value of the popped element. An empty value is returned when no element could be popped and the timeout
* expired.
*/
final def blPop[K: Schema](key: K, keys: K*)(
timeout: Duration
): ResultBuilder1[({ type lambda[x] = Option[(K, x)] })#lambda] =
new ResultBuilder1[({ type lambda[x] = Option[(K, x)] })#lambda] {
def returning[V: Schema]: IO[RedisError, Option[(K, V)]] = {
val command = RedisCommand(
BlPop,
Tuple2(NonEmptyList(ArbitraryKeyInput[K]()), DurationSecondsInput),
OptionalOutput(Tuple2Output(ArbitraryOutput[K](), ArbitraryOutput[V]())),
executor
)
command.run(((key, keys.toList), timeout))
}
}
/**
* Removes and gets the last element in a list, or block until one is available. An element is popped from the tail of
* the first list that is non-empty, with the given keys being checked in the order that they are given.
*
* @param key
* the key identifier of the first list to be checked
* @param keys
* the key identifiers of the rest of the lists
* @param timeout
* the maximum time to wait until an element is available. A timeout of zero can be used to block indefinitely
* @return
* a tuple with the first element being the name of the key where an element was popped and the second element being
* the value of the popped element. An empty value is returned when no element could be popped and the timeout
* expired.
*/
final def brPop[K: Schema](key: K, keys: K*)(
timeout: Duration
): ResultBuilder1[({ type lambda[x] = Option[(K, x)] })#lambda] =
new ResultBuilder1[({ type lambda[x] = Option[(K, x)] })#lambda] {
def returning[V: Schema]: IO[RedisError, Option[(K, V)]] = {
val command = RedisCommand(
BrPop,
Tuple2(NonEmptyList(ArbitraryKeyInput[K]()), DurationSecondsInput),
OptionalOutput(Tuple2Output(ArbitraryOutput[K](), ArbitraryOutput[V]())),
executor
)
command.run(((key, keys.toList), timeout))
}
}
/**
* Pops an element from the list stored at source, pushes it to the list stored at destination; or block until one is
* available. This is the blocking variant of [[zio.redis.api.Lists#rPopLPush]].
......@@ -77,6 +176,35 @@ trait Lists extends RedisEnvironment {
.run((key, index))
}
/**
* Inserts element in the list stored at key either before or after the reference value pivot.
*
* @param key
* the key identifier
* @param position
* the position in which the element will be inserted
* @param pivot
* the reference value
* @param element
* the value to be inserted
* @return
* the length of the list after the insert operation, or -1 when the value pivot was not found.
*/
final def lInsert[K: Schema, V: Schema](
key: K,
position: Position,
pivot: V,
element: V
): IO[RedisError, Long] = {
val command = RedisCommand(
LInsert,
Tuple4(ArbitraryKeyInput[K](), PositionInput, ArbitraryValueInput[V](), ArbitraryValueInput[V]()),
LongOutput,
executor
)
command.run((key, position, pivot, element))
}
/**
* Returns the length of the list stored at key.
*
......@@ -90,6 +218,40 @@ trait Lists extends RedisEnvironment {
command.run(key)
}
/**
* Atomically returns and removes the first/last element (head/tail depending on the wherefrom argument) of the list
* stored at source, and pushes the element at the first/last element (head/tail depending on the whereto argument) of
* the list stored at destination.
*
* @param source
* the key where the element is removed
* @param destination
* the key where the element is inserted
* @param sourceSide
* the side where the element is removed
* @param destinationSide
* the side where the element is inserted
* @return
* the element which is moved or nil when the source is empty.
*/
final def lMove[S: Schema, D: Schema](
source: S,
destination: D,
sourceSide: Side,
destinationSide: Side
): ResultBuilder1[Option] =
new ResultBuilder1[Option] {
def returning[V: Schema]: IO[RedisError, Option[V]] = {
val command = RedisCommand(
LMove,
Tuple4(ArbitraryValueInput[S](), ArbitraryValueInput[D](), SideInput, SideInput),
OptionalOutput(ArbitraryOutput[V]()),
executor
)
command.run((source, destination, sourceSide, destinationSide))
}
}
/**
* Removes and returns the first element of the list stored at key.
*
......@@ -104,6 +266,84 @@ trait Lists extends RedisEnvironment {
RedisCommand(LPop, ArbitraryKeyInput[K](), OptionalOutput(ArbitraryOutput[V]()), executor).run(key)
}
/**
* The command returns the index of matching elements inside a Redis list. By default, when no options are given, it
* will scan the list from head to tail, looking for the first match of "element". If the element is found, its index
* (the zero-based position in the list) is returned. Otherwise, if no match is found, NULL is returned.
*
* @param key
* the key identifier
* @param element
* the element to search for
* @param rank
* the rank of the element
* @param maxLen
* limit the number of performed comparisons
* @return
* Either an integer or an array depending on the count option.
*/
final def lPos[K: Schema, V: Schema](
key: K,
element: V,
rank: Option[Rank] = None,
maxLen: Option[ListMaxLen] = None
): IO[RedisError, Option[Long]] = {
val command = RedisCommand(
LPos,
Tuple4(
ArbitraryKeyInput[K](),
ArbitraryValueInput[V](),
OptionalInput(RankInput),
OptionalInput(ListMaxLenInput)
),
OptionalOutput(LongOutput),
executor
)
command.run((key, element, rank, maxLen))
}
/**
* The command returns the index of matching elements inside a Redis list. By default, when no options are given, it
* will scan the list from head to tail, looking for the first match of "element". If the element is found, its index
* (the zero-based position in the list) is returned. Otherwise, if no match is found, NULL is returned.
*
* @param key
* the key identifier
* @param element
* the element to search for
* @param rank
* the rank of the element
* @param count
* return up count element indexes
* @param maxLen
* limit the number of performed comparisons
* @return
* Either an integer or an array depending on the count option.
*/
final def lPosCount[K: Schema, V: Schema](
key: K,
element: V,
count: Count,
rank: Option[Rank] = None,
maxLen: Option[ListMaxLen] = None
): IO[RedisError, Chunk[Long]] = {
val command = RedisCommand(
LPos,
Tuple5(
ArbitraryKeyInput[K](),
ArbitraryValueInput[V](),
CountInput,
OptionalInput(RankInput),
OptionalInput(ListMaxLenInput)
),
ChunkOutput(LongOutput),
executor
)
command.run((key, element, count, rank, maxLen))
}
/**
* Prepends one or multiple elements to the list stored at key. If key does not exist, it is created as empty list
* before performing the push operations.
......@@ -292,253 +532,19 @@ trait Lists extends RedisEnvironment {
RedisCommand(RPushX, Tuple2(ArbitraryKeyInput[K](), NonEmptyList(ArbitraryValueInput[V]())), LongOutput, executor)
command.run((key, (element, elements.toList)))
}
/**
* Removes and gets the first element in a list, or blocks until one is available. An element is popped from the head
* of the first list that is non-empty, with the given keys being checked in the order that they are given.
*
* @param key
* the key identifier of the first list to be checked
* @param keys
* the key identifiers of the rest of the lists
* @param timeout
* the maximum time to wait until an element is available. A timeout of zero can be used to block indefinitely
* @return
* a tuple with the first element being the name of the key where an element was popped and the second element being
* the value of the popped element. An empty value is returned when no element could be popped and the timeout
* expired.
*/
final def blPop[K: Schema](key: K, keys: K*)(
timeout: Duration
): ResultBuilder1[({ type lambda[x] = Option[(K, x)] })#lambda] =
new ResultBuilder1[({ type lambda[x] = Option[(K, x)] })#lambda] {
def returning[V: Schema]: IO[RedisError, Option[(K, V)]] = {
val command = RedisCommand(
BlPop,
Tuple2(NonEmptyList(ArbitraryKeyInput[K]()), DurationSecondsInput),
OptionalOutput(Tuple2Output(ArbitraryOutput[K](), ArbitraryOutput[V]())),
executor
)
command.run(((key, keys.toList), timeout))
}
}
/**
* Removes and gets the last element in a list, or block until one is available. An element is popped from the tail of
* the first list that is non-empty, with the given keys being checked in the order that they are given.
*
* @param key
* the key identifier of the first list to be checked
* @param keys
* the key identifiers of the rest of the lists
* @param timeout
* the maximum time to wait until an element is available. A timeout of zero can be used to block indefinitely
* @return
* a tuple with the first element being the name of the key where an element was popped and the second element being
* the value of the popped element. An empty value is returned when no element could be popped and the timeout
* expired.
*/
final def brPop[K: Schema](key: K, keys: K*)(
timeout: Duration
): ResultBuilder1[({ type lambda[x] = Option[(K, x)] })#lambda] =
new ResultBuilder1[({ type lambda[x] = Option[(K, x)] })#lambda] {
def returning[V: Schema]: IO[RedisError, Option[(K, V)]] = {
val command = RedisCommand(
BrPop,
Tuple2(NonEmptyList(ArbitraryKeyInput[K]()), DurationSecondsInput),
OptionalOutput(Tuple2Output(ArbitraryOutput[K](), ArbitraryOutput[V]())),
executor
)
command.run(((key, keys.toList), timeout))
}
}
/**
* Inserts element in the list stored at key either before or after the reference value pivot.
*
* @param key
* the key identifier
* @param position
* the position in which the element will be inserted
* @param pivot
* the reference value
* @param element
* the value to be inserted
* @return
* the length of the list after the insert operation, or -1 when the value pivot was not found.
*/
final def lInsert[K: Schema, V: Schema](
key: K,
position: Position,
pivot: V,
element: V
): IO[RedisError, Long] = {
val command = RedisCommand(
LInsert,
Tuple4(ArbitraryKeyInput[K](), PositionInput, ArbitraryValueInput[V](), ArbitraryValueInput[V]()),
LongOutput,
executor
)
command.run((key, position, pivot, element))
}
/**
* Atomically returns and removes the first/last element (head/tail depending on the wherefrom argument) of the list
* stored at source, and pushes the element at the first/last element (head/tail depending on the whereto argument) of
* the list stored at destination.
*
* @param source
* the key where the element is removed
* @param destination
* the key where the element is inserted
* @param sourceSide
* the side where the element is removed
* @param destinationSide
* the side where the element is inserted
* @return
* the element which is moved or nil when the source is empty.
*/
final def lMove[S: Schema, D: Schema](
source: S,
destination: D,
sourceSide: Side,
destinationSide: Side
): ResultBuilder1[Option] =
new ResultBuilder1[Option] {
def returning[V: Schema]: IO[RedisError, Option[V]] = {
val command = RedisCommand(
LMove,
Tuple4(ArbitraryValueInput[S](), ArbitraryValueInput[D](), SideInput, SideInput),
OptionalOutput(ArbitraryOutput[V]()),
executor
)
command.run((source, destination, sourceSide, destinationSide))
}
}
/**
* BLMOVE is the blocking variant of LMOVE. When source contains elements, this command behaves exactly like LMOVE.
* When used inside a MULTI/EXEC block, this command behaves exactly like [[zio.redis.api.Lists#lMove]]. When source
* is empty, Redis will block the connection until another client pushes to it or until timeout is reached. A timeout
* of zero can be used to block indefinitely.
*
* @param source
* the key where the element is removed
* @param destination
* the key where the element is inserted
* @param sourceSide
* the side where the element is removed
* @param destinationSide
* the side where the element is inserted
* @param timeout
* the timeout in seconds
* @return
* the element which is moved or nil when the timeout is reached.
*/
final def blMove[S: Schema, D: Schema](
source: S,
destination: D,
sourceSide: Side,
destinationSide: Side,
timeout: Duration
): ResultBuilder1[Option] =
new ResultBuilder1[Option] {
def returning[V: Schema]: IO[RedisError, Option[V]] = {
val command = RedisCommand(
BlMove,
Tuple5(ArbitraryValueInput[S](), ArbitraryValueInput[D](), SideInput, SideInput, DurationSecondsInput),
OptionalOutput(ArbitraryOutput[V]()),
executor
)
command.run((source, destination, sourceSide, destinationSide, timeout))
}
}
/**
* The command returns the index of matching elements inside a Redis list. By default, when no options are given, it
* will scan the list from head to tail, looking for the first match of "element". If the element is found, its index
* (the zero-based position in the list) is returned. Otherwise, if no match is found, NULL is returned.
*
* @param key
* the key identifier
* @param element
* the element to search for
* @param rank
* the rank of the element
* @param maxLen
* limit the number of performed comparisons
* @return
* Either an integer or an array depending on the count option.
*/
final def lPos[K: Schema, V: Schema](
key: K,
element: V,
rank: Option[Rank] = None,
maxLen: Option[ListMaxLen] = None
): IO[RedisError, Option[Long]] = {
val command = RedisCommand(
LPos,
Tuple4(
ArbitraryKeyInput[K](),
ArbitraryValueInput[V](),
OptionalInput(RankInput),
OptionalInput(ListMaxLenInput)
),
OptionalOutput(LongOutput),
executor
)
command.run((key, element, rank, maxLen))
}
/**
* The command returns the index of matching elements inside a Redis list. By default, when no options are given, it
* will scan the list from head to tail, looking for the first match of "element". If the element is found, its index
* (the zero-based position in the list) is returned. Otherwise, if no match is found, NULL is returned.
*
* @param key
* the key identifier
* @param element
* the element to search for
* @param rank
* the rank of the element
* @param count
* return up count element indexes
* @param maxLen
* limit the number of performed comparisons
* @return
* Either an integer or an array depending on the count option.
*/
final def lPosCount[K: Schema, V: Schema](
key: K,
element: V,
count: Count,
rank: Option[Rank] = None,
maxLen: Option[ListMaxLen] = None
): IO[RedisError, Chunk[Long]] = {
val command = RedisCommand(
LPos,
Tuple5(
ArbitraryKeyInput[K](),
ArbitraryValueInput[V](),
CountInput,
OptionalInput(RankInput),
OptionalInput(ListMaxLenInput)
),
ChunkOutput(LongOutput),
executor
)
command.run((key, element, count, rank, maxLen))
}
}
private[redis] object Lists {
final val BlMove = "BLMOVE"
final val BlPop = "BLPOP"
final val BrPop = "BRPOP"
final val BrPopLPush = "BRPOPLPUSH"
final val LIndex = "LINDEX"
final val LInsert = "LINSERT"
final val LLen = "LLEN"
final val LMove = "LMOVE"
final val LPop = "LPOP"
final val LPos = "LPOS"
final val LPush = "LPUSH"
final val LPushX = "LPUSHX"
final val LRange = "LRANGE"
......@@ -549,11 +555,4 @@ private[redis] object Lists {
final val RPopLPush = "RPOPLPUSH"
final val RPush = "RPUSH"
final val RPushX = "RPUSHX"
final val BlPop = "BLPOP"
final val BrPop = "BRPOP"
final val LInsert = "LINSERT"
final val LMove = "LMOVE"
final val BlMove = "BLMOVE"
final val LPos = "LPOS"
final val LPosCount = "LPOS"
}
......@@ -462,6 +462,22 @@ trait SortedSets extends RedisEnvironment {
command.run((key, lexRange.min.asString, lexRange.max.asString))
}
/**
* Returns the scores associated with the specified members in the sorted set stored at key.
*
* @param key
* Key of the set
* @param keys
* Keys of the rest sets
* @return
* List of scores or None associated with the specified member values (a double precision floating point number).
*/
final def zMScore[K: Schema](key: K, keys: K*): IO[RedisError, Chunk[Option[Double]]] = {
val command =
RedisCommand(ZMScore, NonEmptyList(ArbitraryKeyInput[K]()), ChunkOutput(OptionalOutput(DoubleOutput)), executor)
command.run((key, keys.toList))
}
/**
* Remove and return members with the highest scores in a sorted set.
*
......@@ -520,6 +536,79 @@ trait SortedSets extends RedisEnvironment {
}
}
/**
* Return a random element from the sorted set value stored at key.
*
* @param key
* Key of a sorted set
* @return
* Return a random element from the sorted set value stored at key.
*/
final def zRandMember[K: Schema](key: K): ResultBuilder1[Option] =
new ResultBuilder1[Option] {
def returning[R: Schema]: IO[RedisError, Option[R]] =
RedisCommand(ZRandMember, ArbitraryKeyInput[K](), OptionalOutput(ArbitraryOutput[R]()), executor)
.run(key)
}
/**
* Return random elements from the sorted set value stored at key.
*
* @param key
* Key of a sorted set
* @param count
* If the provided count argument is positive, return an array of distinct elements. The array's length is either
* count or the sorted set's cardinality (ZCARD), whichever is lower
* @return
* Return an array of elements from the sorted set value stored at key.
*/
final def zRandMember[K: Schema](
key: K,
count: Long
): ResultBuilder1[Chunk] =
new ResultBuilder1[Chunk] {
def returning[M: Schema]: IO[RedisError, Chunk[M]] = {
val command = RedisCommand(
ZRandMember,
Tuple2(ArbitraryKeyInput[K](), LongInput),
ZRandMemberOutput(ArbitraryOutput[M]()),
executor
)
command.run((key, count))
}
}
/**
* Return random elements from the sorted set value stored at key.
*
* @param key
* Key of a sorted set
* @param count
* If the provided count argument is positive, return an array of distinct elements. The array's length is either
* count or the sorted set's cardinality (ZCARD), whichever is lower
* @return
* When the additional count argument is passed, the command returns an array of elements, or an empty array when
* key does not exist. If the WITHSCORES modifier is used, the reply is a list elements and their scores from the
* sorted set.
*/
final def zRandMemberWithScores[K: Schema](
key: K,
count: Long
): ResultBuilder1[MemberScores] =
new ResultBuilder1[MemberScores] {
def returning[M: Schema]: IO[RedisError, Chunk[MemberScore[M]]] = {
val command = RedisCommand(
ZRandMember,
Tuple3(ArbitraryKeyInput[K](), LongInput, ArbitraryValueInput[String]()),
ZRandMemberTuple2Output(ArbitraryOutput[M](), DoubleOutput)
.map(_.map { case (m, s) => MemberScore(s, m) }),
executor
)
command.run((key, count, WithScores.asString))
}
}
/**
* Return a range of members in a sorted set, by index.
*
......@@ -699,21 +788,17 @@ trait SortedSets extends RedisEnvironment {
*
* @param key
* Key of a sorted set
* @param firstMember
* @param member
* Member to be removed
* @param restMembers
* @param members
* Rest members to be removed
* @return
* The number of members removed from the sorted set, not including non existing members.
*/
final def zRem[K: Schema, M: Schema](
key: K,
firstMember: M,
restMembers: M*
): IO[RedisError, Long] = {
final def zRem[K: Schema, M: Schema](key: K, member: M, members: M*): IO[RedisError, Long] = {
val command =
RedisCommand(ZRem, Tuple2(ArbitraryKeyInput[K](), NonEmptyList(ArbitraryValueInput[M]())), LongOutput, executor)
command.run((key, (firstMember, restMembers.toList)))
command.run((key, (member, members.toList)))
}
/**
......@@ -1122,95 +1207,6 @@ trait SortedSets extends RedisEnvironment {
)
command.run((destination, inputKeysNum, (key, keys.toList), weights, aggregate))
}
/**
* Returns the scores associated with the specified members in the sorted set stored at key.
*
* @param key
* Key of the set
* @param keys
* Keys of the rest sets
* @return
* List of scores or None associated with the specified member values (a double precision floating point number).
*/
final def zMScore[K: Schema](key: K, keys: K*): IO[RedisError, Chunk[Option[Double]]] = {
val command =
RedisCommand(ZMScore, NonEmptyList(ArbitraryKeyInput[K]()), ChunkOutput(OptionalOutput(DoubleOutput)), executor)
command.run((key, keys.toList))
}
/**
* Return a random element from the sorted set value stored at key.
*
* @param key
* Key of a sorted set
* @return
* Return a random element from the sorted set value stored at key.
*/
final def zRandMember[K: Schema](key: K): ResultBuilder1[Option] =
new ResultBuilder1[Option] {
def returning[R: Schema]: IO[RedisError, Option[R]] =
RedisCommand(ZRandMember, ArbitraryKeyInput[K](), OptionalOutput(ArbitraryOutput[R]()), executor)
.run(key)
}
/**
* Return random elements from the sorted set value stored at key.
*
* @param key
* Key of a sorted set
* @param count
* If the provided count argument is positive, return an array of distinct elements. The array's length is either
* count or the sorted set's cardinality (ZCARD), whichever is lower
* @return
* Return an array of elements from the sorted set value stored at key.
*/
final def zRandMember[K: Schema](
key: K,
count: Long
): ResultBuilder1[Chunk] =
new ResultBuilder1[Chunk] {
def returning[M: Schema]: IO[RedisError, Chunk[M]] = {
val command = RedisCommand(
ZRandMember,
Tuple2(ArbitraryKeyInput[K](), LongInput),
ZRandMemberOutput(ArbitraryOutput[M]()),
executor
)
command.run((key, count))
}
}
/**
* Return random elements from the sorted set value stored at key.
*
* @param key
* Key of a sorted set
* @param count
* If the provided count argument is positive, return an array of distinct elements. The array's length is either
* count or the sorted set's cardinality (ZCARD), whichever is lower
* @return
* When the additional count argument is passed, the command returns an array of elements, or an empty array when
* key does not exist. If the WITHSCORES modifier is used, the reply is a list elements and their scores from the
* sorted set.
*/
final def zRandMemberWithScores[K: Schema](
key: K,
count: Long
): ResultBuilder1[MemberScores] =
new ResultBuilder1[MemberScores] {
def returning[M: Schema]: IO[RedisError, Chunk[MemberScore[M]]] = {
val command = RedisCommand(
ZRandMember,
Tuple3(ArbitraryKeyInput[K](), LongInput, ArbitraryValueInput[String]()),
ZRandMemberTuple2Output(ArbitraryOutput[M](), DoubleOutput)
.map(_.map { case (m, s) => MemberScore(s, m) }),
executor
)
command.run((key, count, WithScores.asString))
}
}
}
private[redis] object SortedSets {
......@@ -1228,6 +1224,7 @@ private[redis] object SortedSets {
final val ZMScore = "ZMSCORE"
final val ZPopMax = "ZPOPMAX"
final val ZPopMin = "ZPOPMIN"
final val ZRandMember = "ZRANDMEMBER"
final val ZRange = "ZRANGE"
final val ZRangeByLex = "ZRANGEBYLEX"
final val ZRangeByScore = "ZRANGEBYSCORE"
......@@ -1244,5 +1241,4 @@ private[redis] object SortedSets {
final val ZScore = "ZSCORE"
final val ZUnion = "ZUNION"
final val ZUnionStore = "ZUNIONSTORE"
final val ZRandMember = "ZRANDMEMBER"
}
......@@ -95,107 +95,6 @@ trait Streams extends RedisEnvironment {
}
}
/**
* An introspection command used in order to retrieve different information about the stream.
*
* @param key
* ID of the stream
* @return
* General information about the stream stored at the specified key.
*/
final def xInfoStream[SK: Schema](
key: SK
): ResultBuilder3[StreamInfo] = new ResultBuilder3[StreamInfo] {
def returning[RI: Schema, RK: Schema, RV: Schema]: IO[RedisError, StreamInfo[RI, RK, RV]] = {
val command = RedisCommand(XInfoStream, ArbitraryKeyInput[SK](), StreamInfoOutput[RI, RK, RV](), executor)
command.run(key)
}
}
/**
* Returns the entire state of the stream, including entries, groups, consumers and PELs.
*
* @param key
* ID of the stream
* @return
* General information about the stream stored at the specified key.
*/
final def xInfoStreamFull[SK: Schema](
key: SK
): ResultBuilder3[FullStreamInfo] = new ResultBuilder3[FullStreamInfo] {
def returning[RI: Schema, RK: Schema, RV: Schema]: IO[RedisError, FullStreamInfo[RI, RK, RV]] = {
val command = RedisCommand(
XInfoStream,
Tuple2(ArbitraryKeyInput[SK](), ArbitraryValueInput[String]()),
StreamInfoFullOutput[RI, RK, RV](),
executor
)
command.run((key, "FULL"))
}
}
/**
* Returns the entire state of the stream, including entries, groups, consumers and PELs.
*
* @param key
* ID of the stream
* @param count
* limit the amount of stream/PEL entries that are returned (The first <count> entries are returned)
* @return
* General information about the stream stored at the specified key.
*/
final def xInfoStreamFull[SK: Schema](
key: SK,
count: Long
): ResultBuilder3[FullStreamInfo] = new ResultBuilder3[FullStreamInfo] {
def returning[RI: Schema, RK: Schema, RV: Schema]: IO[RedisError, FullStreamInfo[RI, RK, RV]] = {
val command = RedisCommand(
XInfoStream,
Tuple3(ArbitraryKeyInput[SK](), ArbitraryValueInput[String](), CountInput),
StreamInfoFullOutput[RI, RK, RV](),
executor
)
command.run((key, "FULL", Count(count)))
}
}
/**
* An introspection command used in order to retrieve different information about the group.
*
* @param key
* ID of the stream
* @return
* List of consumer groups associated with the stream stored at the specified key.
*/
final def xInfoGroups[SK: Schema](key: SK): IO[RedisError, Chunk[StreamGroupsInfo]] = {
val command = RedisCommand(XInfoGroups, ArbitraryKeyInput[SK](), StreamGroupsInfoOutput, executor)
command.run(key)
}
/**
* An introspection command used in order to retrieve different information about the consumers.
*
* @param key
* ID of the stream
* @param group
* ID of the consumer group
* @return
* List of every consumer in a specific consumer group.
*/
final def xInfoConsumers[SK: Schema, SG: Schema](
key: SK,
group: SG
): IO[RedisError, Chunk[StreamConsumersInfo]] = {
val command =
RedisCommand(
XInfoConsumers,
Tuple2(ArbitraryKeyInput[SK](), ArbitraryValueInput[SG]()),
StreamConsumersInfoOutput,
executor
)
command.run((key, group))
}
/**
* Appends the specified stream entry to the stream at the specified key while limiting the size of the stream.
*
......@@ -402,22 +301,45 @@ trait Streams extends RedisEnvironment {
}
/**
* Set the consumer group last delivered ID to something else.
* Create a new consumer associated with a consumer group.
*
* @param key
* ID of the stream
* @param group
* ID of the consumer group
* @param id
* last delivered ID to set
* @param consumer
* ID of the consumer
* @return
* the number of created consumer groups.
*/
final def xGroupSetId[SK: Schema, SG: Schema, I: Schema](
final def xGroupCreateConsumer[SK: Schema, SG: Schema, SC: Schema](
key: SK,
group: SG,
id: I
): IO[RedisError, Unit] = {
val command = RedisCommand(XGroup, XGroupSetIdInput[SK, SG, I](), UnitOutput, executor)
command.run(SetId(key, group, id))
consumer: SC
): IO[RedisError, Boolean] = {
val command = RedisCommand(XGroup, XGroupCreateConsumerInput[SK, SG, SC](), BoolOutput, executor)
command.run(CreateConsumer(key, group, consumer))
}
/**
* Remove a specific consumer from a consumer group.
*
* @param key
* ID of the stream
* @param group
* ID of the consumer group
* @param consumer
* ID of the consumer
* @return
* the number of pending messages that the consumer had before it was deleted.
*/
final def xGroupDelConsumer[SK: Schema, SG: Schema, SC: Schema](
key: SK,
group: SG,
consumer: SC
): IO[RedisError, Long] = {
val command = RedisCommand(XGroup, XGroupDelConsumerInput[SK, SG, SC](), LongOutput, executor)
command.run(DelConsumer(key, group, consumer))
}
/**
......@@ -434,45 +356,123 @@ trait Streams extends RedisEnvironment {
RedisCommand(XGroup, XGroupDestroyInput[SK, SG](), BoolOutput, executor).run(Destroy(key, group))
/**
* Create a new consumer associated with a consumer group.
* Set the consumer group last delivered ID to something else.
*
* @param key
* ID of the stream
* @param group
* ID of the consumer group
* @param consumer
* ID of the consumer
* @return
* the number of created consumer groups.
* @param id
* last delivered ID to set
*/
final def xGroupCreateConsumer[SK: Schema, SG: Schema, SC: Schema](
final def xGroupSetId[SK: Schema, SG: Schema, I: Schema](
key: SK,
group: SG,
consumer: SC
): IO[RedisError, Boolean] = {
val command = RedisCommand(XGroup, XGroupCreateConsumerInput[SK, SG, SC](), BoolOutput, executor)
command.run(CreateConsumer(key, group, consumer))
id: I
): IO[RedisError, Unit] = {
val command = RedisCommand(XGroup, XGroupSetIdInput[SK, SG, I](), UnitOutput, executor)
command.run(SetId(key, group, id))
}
/**
* Remove a specific consumer from a consumer group.
* An introspection command used in order to retrieve different information about the consumers.
*
* @param key
* ID of the stream
* @param group
* ID of the consumer group
* @param consumer
* ID of the consumer
* @return
* the number of pending messages that the consumer had before it was deleted.
* List of every consumer in a specific consumer group.
*/
final def xGroupDelConsumer[SK: Schema, SG: Schema, SC: Schema](
final def xInfoConsumers[SK: Schema, SG: Schema](
key: SK,
group: SG,
consumer: SC
): IO[RedisError, Long] = {
val command = RedisCommand(XGroup, XGroupDelConsumerInput[SK, SG, SC](), LongOutput, executor)
command.run(DelConsumer(key, group, consumer))
group: SG
): IO[RedisError, Chunk[StreamConsumersInfo]] = {
val command =
RedisCommand(
XInfoConsumers,
Tuple2(ArbitraryKeyInput[SK](), ArbitraryValueInput[SG]()),
StreamConsumersInfoOutput,
executor
)
command.run((key, group))
}
/**
* An introspection command used in order to retrieve different information about the group.
*
* @param key
* ID of the stream
* @return
* List of consumer groups associated with the stream stored at the specified key.
*/
final def xInfoGroups[SK: Schema](key: SK): IO[RedisError, Chunk[StreamGroupsInfo]] = {
val command = RedisCommand(XInfoGroups, ArbitraryKeyInput[SK](), StreamGroupsInfoOutput, executor)
command.run(key)
}
/**
* An introspection command used in order to retrieve different information about the stream.
*
* @param key
* ID of the stream
* @return
* General information about the stream stored at the specified key.
*/
final def xInfoStream[SK: Schema](
key: SK
): ResultBuilder3[StreamInfo] = new ResultBuilder3[StreamInfo] {
def returning[RI: Schema, RK: Schema, RV: Schema]: IO[RedisError, StreamInfo[RI, RK, RV]] = {
val command = RedisCommand(XInfoStream, ArbitraryKeyInput[SK](), StreamInfoOutput[RI, RK, RV](), executor)
command.run(key)
}
}
/**
* Returns the entire state of the stream, including entries, groups, consumers and PELs.
*
* @param key
* ID of the stream
* @return
* General information about the stream stored at the specified key.
*/
final def xInfoStreamFull[SK: Schema](
key: SK
): ResultBuilder3[FullStreamInfo] = new ResultBuilder3[FullStreamInfo] {
def returning[RI: Schema, RK: Schema, RV: Schema]: IO[RedisError, FullStreamInfo[RI, RK, RV]] = {
val command = RedisCommand(
XInfoStream,
Tuple2(ArbitraryKeyInput[SK](), ArbitraryValueInput[String]()),
StreamInfoFullOutput[RI, RK, RV](),
executor
)
command.run((key, "FULL"))
}
}
/**
* Returns the entire state of the stream, including entries, groups, consumers and PELs.
*
* @param key
* ID of the stream
* @param count
* limit the amount of stream/PEL entries that are returned (The first <count> entries are returned)
* @return
* General information about the stream stored at the specified key.
*/
final def xInfoStreamFull[SK: Schema](
key: SK,
count: Long
): ResultBuilder3[FullStreamInfo] = new ResultBuilder3[FullStreamInfo] {
def returning[RI: Schema, RK: Schema, RV: Schema]: IO[RedisError, FullStreamInfo[RI, RK, RV]] = {
val command = RedisCommand(
XInfoStream,
Tuple3(ArbitraryKeyInput[SK](), ArbitraryValueInput[String](), CountInput),
StreamInfoFullOutput[RI, RK, RV](),
executor
)
command.run((key, "FULL", Count(count)))
}
}
/**
......@@ -807,9 +807,9 @@ private object Streams {
final val XClaim = "XCLAIM"
final val XDel = "XDEL"
final val XGroup = "XGROUP"
final val XInfoStream = "XINFO STREAM"
final val XInfoGroups = "XINFO GROUPS"
final val XInfoConsumers = "XINFO CONSUMERS"
final val XInfoGroups = "XINFO GROUPS"
final val XInfoStream = "XINFO STREAM"
final val XLen = "XLEN"
final val XPending = "XPENDING"
final val XRange = "XRANGE"
......
......@@ -201,50 +201,6 @@ trait Strings extends RedisEnvironment {
command.run((key, offset))
}
/**
* Get a substring of the string stored at key.
*
* @param key
* Key of the string to get a substring of
* @param range
* Range of the substring
* @return
* Returns the substring.
*/
final def getRange[K: Schema](key: K, range: Range): ResultBuilder1[Option] =
new ResultBuilder1[Option] {
def returning[R: Schema]: IO[RedisError, Option[R]] =
RedisCommand(
GetRange,
Tuple2(ArbitraryKeyInput[K](), RangeInput),
OptionalOutput(ArbitraryOutput[R]()),
executor
)
.run((key, range))
}
/**
* Set the string value of a key and return its old value.
*
* @param key
* Key of string to set
* @param value
* New value of the string
* @return
* Returns the previous value of the string or None if it did not previously have a value.
*/
final def getSet[K: Schema, V: Schema](key: K, value: V): ResultBuilder1[Option] =
new ResultBuilder1[Option] {
def returning[R: Schema]: IO[RedisError, Option[R]] =
RedisCommand(
GetSet,
Tuple2(ArbitraryKeyInput[K](), ArbitraryValueInput[V]()),
OptionalOutput(ArbitraryOutput[R]()),
executor
)
.run((key, value))
}
/**
* Get the string value of a key and delete it on success (if and only if the key's value type is a string).
*
......@@ -316,6 +272,50 @@ trait Strings extends RedisEnvironment {
.run((key, persist))
}
/**
* Get a substring of the string stored at key.
*
* @param key
* Key of the string to get a substring of
* @param range
* Range of the substring
* @return
* Returns the substring.
*/
final def getRange[K: Schema](key: K, range: Range): ResultBuilder1[Option] =
new ResultBuilder1[Option] {
def returning[R: Schema]: IO[RedisError, Option[R]] =
RedisCommand(
GetRange,
Tuple2(ArbitraryKeyInput[K](), RangeInput),
OptionalOutput(ArbitraryOutput[R]()),
executor
)
.run((key, range))
}
/**
* Set the string value of a key and return its old value.
*
* @param key
* Key of string to set
* @param value
* New value of the string
* @return
* Returns the previous value of the string or None if it did not previously have a value.
*/
final def getSet[K: Schema, V: Schema](key: K, value: V): ResultBuilder1[Option] =
new ResultBuilder1[Option] {
def returning[R: Schema]: IO[RedisError, Option[R]] =
RedisCommand(
GetSet,
Tuple2(ArbitraryKeyInput[K](), ArbitraryValueInput[V]()),
OptionalOutput(ArbitraryOutput[R]()),
executor
)
.run((key, value))
}
/**
* Increment the integer value of a key by one.
*
......@@ -593,19 +593,6 @@ trait Strings extends RedisEnvironment {
command.run((key, offset, value))
}
/**
* Get the length of a value stored in a key.
*
* @param key
* Key of the string to get the length of
* @return
* Returns the length of the string.
*/
final def strLen[K: Schema](key: K): IO[RedisError, Long] = {
val command = RedisCommand(StrLen, ArbitraryKeyInput[K](), LongOutput, executor)
command.run(key)
}
/**
* Get the longest common subsequence of values stored in the given keys.
*
......@@ -623,7 +610,7 @@ trait Strings extends RedisEnvironment {
* length and all the ranges in both the strings, start and end offset for each string, where there are matches.
* When withMatchLen is given each array representing a match will also have the length of the match (see examples).
*/
final def stralgoLcs[K: Schema](
final def strAlgoLcs[K: Schema](
command: StrAlgoLCS,
keyA: K,
keyB: K,
......@@ -642,6 +629,19 @@ trait Strings extends RedisEnvironment {
)
redisCommand.run((command.asString, keyA, keyB, lcsQueryType))
}
/**
* Get the length of a value stored in a key.
*
* @param key
* Key of the string to get the length of
* @return
* Returns the length of the string.
*/
final def strLen[K: Schema](key: K): IO[RedisError, Long] = {
val command = RedisCommand(StrLen, ArbitraryKeyInput[K](), LongOutput, executor)
command.run(key)
}
}
private[redis] object Strings {
......@@ -654,6 +654,8 @@ private[redis] object Strings {
final val DecrBy = "DECRBY"
final val Get = "GET"
final val GetBit = "GETBIT"
final val GetDel = "GETDEL"
final val GetEx = "GETEX"
final val GetRange = "GETRANGE"
final val GetSet = "GETSET"
final val Incr = "INCR"
......@@ -668,8 +670,6 @@ private[redis] object Strings {
final val SetEx = "SETEX"
final val SetNx = "SETNX"
final val SetRange = "SETRANGE"
final val StrLen = "STRLEN"
final val StrAlgoLcs = "STRALGO LCS"
final val GetDel = "GETDEL"
final val GetEx = "GETEX"
final val StrLen = "STRLEN"
}
......@@ -321,7 +321,7 @@ trait StringsSpec extends BaseSpec {
test("get LCS from 2 strings") {
val str1 = "foo"
val str2 = "fao"
assertZIO(ZIO.serviceWithZIO[Redis](_.stralgoLcs(StralgoLCS.Strings, str1, str2)))(
assertZIO(ZIO.serviceWithZIO[Redis](_.strAlgoLcs(StralgoLCS.Strings, str1, str2)))(
equalTo(LcsOutput.Lcs("fo"))
)
},
......@@ -335,7 +335,7 @@ trait StringsSpec extends BaseSpec {
_ <- redis.set(key1, str1, None, None, None)
key2 <- uuid
_ <- redis.set(key2, str2, None, None, None)
result <- redis.stralgoLcs(StralgoLCS.Keys, key1, key2)
result <- redis.strAlgoLcs(StralgoLCS.Keys, key1, key2)
} yield assert(result)(equalTo(LcsOutput.Lcs("fo")))
},
test("get LCS from unknown keys") {
......@@ -348,14 +348,14 @@ trait StringsSpec extends BaseSpec {
_ <- redis.set(key1, str1, None, None, None)
key2 <- uuid
_ <- redis.set(key2, str2, None, None, None)
result <- redis.stralgoLcs(StralgoLCS.Keys, "unknown", "unknown")
result <- redis.strAlgoLcs(StralgoLCS.Keys, "unknown", "unknown")
} yield assert(result)(equalTo(LcsOutput.Lcs("")))
},
test("Get length of LCS for strings") {
val str1 = "foo"
val str2 = "fao"
assertZIO(
ZIO.serviceWithZIO[Redis](_.stralgoLcs(StralgoLCS.Strings, str1, str2, Some(StrAlgoLcsQueryType.Len)))
ZIO.serviceWithZIO[Redis](_.strAlgoLcs(StralgoLCS.Strings, str1, str2, Some(StrAlgoLcsQueryType.Len)))
)(
equalTo(LcsOutput.Length(2))
)
......@@ -370,7 +370,7 @@ trait StringsSpec extends BaseSpec {
_ <- redis.set(key1, str1, None, None, None)
key2 <- uuid
_ <- redis.set(key2, str2, None, None, None)
result <- redis.stralgoLcs(StralgoLCS.Keys, key1, key2, Some(StrAlgoLcsQueryType.Len))
result <- redis.strAlgoLcs(StralgoLCS.Keys, key1, key2, Some(StrAlgoLcsQueryType.Len))
} yield assert(result)(equalTo(LcsOutput.Length(2)))
},
test("get length of LCS for unknown keys") {
......@@ -383,7 +383,7 @@ trait StringsSpec extends BaseSpec {
_ <- redis.set(key1, str1, None, None, None)
key2 <- uuid
_ <- redis.set(key2, str2, None, None, None)
result <- redis.stralgoLcs(
result <- redis.strAlgoLcs(
StralgoLCS.Keys,
"unknown",
"unknown",
......@@ -395,7 +395,7 @@ trait StringsSpec extends BaseSpec {
val str1 = "ohmytext"
val str2 = "mynewtext"
assertZIO(
ZIO.serviceWithZIO[Redis](_.stralgoLcs(StralgoLCS.Strings, str1, str2, Some(StrAlgoLcsQueryType.Idx())))
ZIO.serviceWithZIO[Redis](_.strAlgoLcs(StralgoLCS.Strings, str1, str2, Some(StrAlgoLcsQueryType.Idx())))
)(
equalTo(
LcsOutput.Matches(
......@@ -418,7 +418,7 @@ trait StringsSpec extends BaseSpec {
_ <- redis.set(key1, str1)
key2 <- uuid
_ <- redis.set(key2, str2)
result <- redis.stralgoLcs(StralgoLCS.Keys, key1, key2, Some(StrAlgoLcsQueryType.Idx()))
result <- redis.strAlgoLcs(StralgoLCS.Keys, key1, key2, Some(StrAlgoLcsQueryType.Idx()))
} yield {
assert(result)(
equalTo(
......@@ -444,7 +444,7 @@ trait StringsSpec extends BaseSpec {
_ <- redis.set(key1, str1)
key2 <- uuid
_ <- redis.set(key2, str2)
result <- redis.stralgoLcs(
result <- redis.strAlgoLcs(
StralgoLCS.Keys,
key1,
key2,
......@@ -474,7 +474,7 @@ trait StringsSpec extends BaseSpec {
_ <- redis.set(key1, str1)
key2 <- uuid
_ <- redis.set(key2, str2)
result <- redis.stralgoLcs(
result <- redis.strAlgoLcs(
StralgoLCS.Keys,
key1,
key2,
......@@ -505,7 +505,7 @@ trait StringsSpec extends BaseSpec {
_ <- redis.set(key1, str1)
key2 <- uuid
_ <- redis.set(key2, str2)
result <- redis.stralgoLcs(
result <- redis.strAlgoLcs(
StralgoLCS.Keys,
key1,
key2,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册