Reduce RESPValue initialization complexities and simplify RedisKey implementation

Motivation:

`RESPValue` exposes a fair amount of complexity on how to intialize a single instance with the various overloads.

This aims to simplify the complexity for developers by providing a single initializer and relying on `RESPValueConvertible` to handle the complexities.

In addition, the Swift complier synthesizes a lot of default conformances that `RedisKey` has manually written, which is just unnecessary code.

Modifications:

- Rename: `RESPValue.init(_:)` to `RESPValue.init(from:)`
- Change: `RESPValue.init` `String?` and `FixedWidthInteger` overloads from `public` to `internal`
- Remove: Unnecessary code for various protocol conformances for `RedisKey`

Result:

Developers should have a direct and guided way of making instances of `RESPValue`
parent 3e1a3d5e
Pipeline #130271393 passed with stage
in 0 seconds
......@@ -111,7 +111,7 @@ extension RedisClient {
/// - Returns: `true` if the expiration was set.
public func expire(_ key: RedisKey, after timeout: TimeAmount) -> EventLoopFuture<Bool> {
let args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
.init(bulk: timeout.seconds)
]
return send(command: "EXPIRE", with: args)
......@@ -154,7 +154,7 @@ extension RedisClient {
var args: [RESPValue] = [.init(bulk: pos)]
if let k = key {
args.insert(.init(bulk: k), at: 0)
args.insert(.init(from: k), at: 0)
}
if let m = match {
......
......@@ -52,7 +52,7 @@ extension RedisClient {
public func hdel(_ fields: [String], from key: RedisKey) -> EventLoopFuture<Int> {
guard fields.count > 0 else { return self.eventLoop.makeSucceededFuture(0) }
var args: [RESPValue] = [.init(bulk: key)]
var args: [RESPValue] = [.init(from: key)]
args.append(convertingContentsOf: fields)
return send(command: "HDEL", with: args)
......@@ -79,7 +79,7 @@ extension RedisClient {
/// - Returns: `true` if the hash contains the field, `false` if either the key or field do not exist.
public func hexists(_ field: String, in key: RedisKey) -> EventLoopFuture<Bool> {
let args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
.init(bulk: field)
]
return send(command: "HEXISTS", with: args)
......@@ -93,7 +93,7 @@ extension RedisClient {
/// - Parameter key: The key of the hash to get field count of.
/// - Returns: The number of fields in the hash, or `0` if the key doesn't exist.
public func hlen(of key: RedisKey) -> EventLoopFuture<Int> {
let args = [RESPValue(bulk: key)]
let args = [RESPValue(from: key)]
return send(command: "HLEN", with: args)
.map()
}
......@@ -107,7 +107,7 @@ extension RedisClient {
/// - Returns: The string length of the hash field's value, or `0` if the field or hash do not exist.
public func hstrlen(of field: String, in key: RedisKey) -> EventLoopFuture<Int> {
let args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
.init(bulk: field)
]
return send(command: "HSTRLEN", with: args)
......@@ -120,7 +120,7 @@ extension RedisClient {
/// - Parameter key: The key of the hash.
/// - Returns: A list of field names stored within the hash.
public func hkeys(in key: RedisKey) -> EventLoopFuture<[String]> {
let args = [RESPValue(bulk: key)]
let args = [RESPValue(from: key)]
return send(command: "HKEYS", with: args)
.map()
}
......@@ -131,7 +131,7 @@ extension RedisClient {
/// - Parameter key: The key of the hash.
/// - Returns: A list of all values stored in a hash.
public func hvals(in key: RedisKey) -> EventLoopFuture<[RESPValue]> {
let args = [RESPValue(bulk: key)]
let args = [RESPValue(from: key)]
return send(command: "HVALS", with: args)
.map()
}
......@@ -216,7 +216,7 @@ extension RedisClient {
in key: RedisKey
) -> EventLoopFuture<Bool> {
let args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
.init(bulk: field),
value.convertedToRESPValue()
]
......@@ -241,7 +241,7 @@ extension RedisClient {
in key: RedisKey
) -> EventLoopFuture<Bool> {
let args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
.init(bulk: field),
value.convertedToRESPValue()
]
......@@ -264,7 +264,7 @@ extension RedisClient {
) -> EventLoopFuture<Void> {
assert(fields.count > 0, "At least 1 key-value pair should be specified")
var args: [RESPValue] = [.init(bulk: key)]
var args: [RESPValue] = [.init(from: key)]
args.add(contentsOf: fields, overestimatedCountBeingAdded: fields.count * 2) { (array, element) in
array.append(.init(bulk: element.key))
array.append(element.value.convertedToRESPValue())
......@@ -287,7 +287,7 @@ extension RedisClient {
/// - Returns: The value of the hash field. If the key or field does not exist, it will be `.null`.
public func hget(_ field: String, from key: RedisKey) -> EventLoopFuture<RESPValue> {
let args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
.init(bulk: field)
]
return send(command: "HGET", with: args)
......@@ -321,7 +321,7 @@ extension RedisClient {
public func hmget(_ fields: [String], from key: RedisKey) -> EventLoopFuture<[RESPValue]> {
guard fields.count > 0 else { return self.eventLoop.makeSucceededFuture([]) }
var args: [RESPValue] = [.init(bulk: key)]
var args: [RESPValue] = [.init(from: key)]
args.append(convertingContentsOf: fields)
return send(command: "HMGET", with: args)
......@@ -380,7 +380,7 @@ extension RedisClient {
/// - Parameter key: The key of the hash to pull from.
/// - Returns: A key-value pair list of fields and their values.
public func hgetall(from key: RedisKey) -> EventLoopFuture<[String: RESPValue]> {
let args = [RESPValue(bulk: key)]
let args = [RESPValue(from: key)]
return send(command: "HGETALL", with: args)
.map(to: [RESPValue].self)
.flatMapThrowing(Self._mapHashResponse)
......@@ -448,7 +448,7 @@ extension RedisClient {
_ key: RedisKey
) -> EventLoopFuture<Value> {
let args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
.init(bulk: field),
amount.convertedToRESPValue()
]
......
......@@ -23,7 +23,7 @@ extension RedisClient {
/// - Parameter key: The key of the list.
/// - Returns: The number of elements in the list.
public func llen(of key: RedisKey) -> EventLoopFuture<Int> {
let args = [RESPValue(bulk: key)]
let args = [RESPValue(from: key)]
return send(command: "LLEN", with: args)
.map()
}
......@@ -37,7 +37,7 @@ extension RedisClient {
/// - Returns: The element stored at index, or `.null` if out of bounds.
public func lindex(_ index: Int, from key: RedisKey) -> EventLoopFuture<RESPValue> {
let args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
.init(bulk: index)
]
return send(command: "LINDEX", with: args)
......@@ -76,7 +76,7 @@ extension RedisClient {
in key: RedisKey
) -> EventLoopFuture<Void> {
let args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
.init(bulk: index),
value.convertedToRESPValue()
]
......@@ -99,7 +99,7 @@ extension RedisClient {
count: Int = 0
) -> EventLoopFuture<Int> {
let args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
.init(bulk: count),
value.convertedToRESPValue()
]
......@@ -121,7 +121,7 @@ extension RedisClient {
/// - Returns: A `NIO.EventLoopFuture` that resolves when the operation has succeeded, or fails with a `RedisError`.
public func ltrim(_ key: RedisKey, before start: Int, after stop: Int) -> EventLoopFuture<Void> {
let args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
.init(bulk: start),
.init(bulk: stop)
]
......@@ -261,7 +261,7 @@ extension RedisClient {
/// - Returns: An array of elements found within the range specified.
public func lrange(from key: RedisKey, firstIndex: Int, lastIndex: Int) -> EventLoopFuture<[RESPValue]> {
let args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
.init(bulk: firstIndex),
.init(bulk: lastIndex)
]
......@@ -533,8 +533,8 @@ extension RedisClient {
/// - Returns: The element that was moved.
public func rpoplpush(from source: RedisKey, to dest: RedisKey) -> EventLoopFuture<RESPValue> {
let args: [RESPValue] = [
.init(bulk: source),
.init(bulk: dest)
.init(from: source),
.init(from: dest)
]
return send(command: "RPOPLPUSH", with: args)
}
......@@ -579,9 +579,9 @@ extension RedisClient {
timeout: TimeAmount = .seconds(0)
) -> EventLoopFuture<RESPValue> {
let args: [RESPValue] = [
.init(bulk: source),
.init(bulk: dest),
.init(bulk: timeout.seconds)
.init(from: source),
.init(from: dest),
.init(from: timeout.seconds)
]
return send(command: "BRPOPLPUSH", with: args)
}
......@@ -662,7 +662,7 @@ extension RedisClient {
_ pivot: Value
) -> EventLoopFuture<Int> {
let args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
.init(bulk: pivotKeyword),
pivot.convertedToRESPValue(),
element.convertedToRESPValue()
......@@ -681,7 +681,7 @@ extension RedisClient {
/// - Parameter key: The key of the list to pop from.
/// - Returns: The element that was popped from the list, or `.null`.
public func lpop(from key: RedisKey) -> EventLoopFuture<RESPValue> {
let args = [RESPValue(bulk: key)]
let args = [RESPValue(from: key)]
return send(command: "LPOP", with: args)
}
......@@ -710,7 +710,7 @@ extension RedisClient {
public func lpush<Value: RESPValueConvertible>(_ elements: [Value], into key: RedisKey) -> EventLoopFuture<Int> {
assert(elements.count > 0, "At least 1 element should be provided.")
var args: [RESPValue] = [.init(bulk: key)]
var args: [RESPValue] = [.init(from: key)]
args.append(convertingContentsOf: elements)
return send(command: "LPUSH", with: args)
......@@ -741,7 +741,7 @@ extension RedisClient {
@inlinable
public func lpushx<Value: RESPValueConvertible>(_ element: Value, into key: RedisKey) -> EventLoopFuture<Int> {
let args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
element.convertedToRESPValue()
]
return send(command: "LPUSHX", with: args)
......@@ -758,7 +758,7 @@ extension RedisClient {
/// - Parameter key: The key of the list to pop from.
/// - Returns: The element that was popped from the list, else `.null`.
public func rpop(from key: RedisKey) -> EventLoopFuture<RESPValue> {
let args = [RESPValue(bulk: key)]
let args = [RESPValue(from: key)]
return send(command: "RPOP", with: args)
}
......@@ -784,7 +784,7 @@ extension RedisClient {
public func rpush<Value: RESPValueConvertible>(_ elements: [Value], into key: RedisKey) -> EventLoopFuture<Int> {
assert(elements.count > 0, "At least 1 element should be provided.")
var args: [RESPValue] = [.init(bulk: key)]
var args: [RESPValue] = [.init(from: key)]
args.append(convertingContentsOf: elements)
return send(command: "RPUSH", with: args)
......@@ -814,7 +814,7 @@ extension RedisClient {
@inlinable
public func rpushx<Value: RESPValueConvertible>(_ element: Value, into key: RedisKey) -> EventLoopFuture<Int> {
let args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
element.convertedToRESPValue()
]
return send(command: "RPUSHX", with: args)
......
......@@ -26,7 +26,7 @@ extension RedisClient {
/// - Parameter key: The key of the set.
/// - Returns: A list of elements found within the set.
public func smembers(of key: RedisKey) -> EventLoopFuture<[RESPValue]> {
let args = [RESPValue(bulk: key)]
let args = [RESPValue(from: key)]
return send(command: "SMEMBERS", with: args)
.map()
}
......@@ -57,7 +57,7 @@ extension RedisClient {
@inlinable
public func sismember<Value: RESPValueConvertible>(_ element: Value, of key: RedisKey) -> EventLoopFuture<Bool> {
let args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
element.convertedToRESPValue()
]
return send(command: "SISMEMBER", with: args)
......@@ -71,7 +71,7 @@ extension RedisClient {
/// - Parameter key: The key of the set.
/// - Returns: The total count of elements in the set.
public func scard(of key: RedisKey) -> EventLoopFuture<Int> {
let args = [RESPValue(bulk: key)]
let args = [RESPValue(from: key)]
return send(command: "SCARD", with: args)
.map()
}
......@@ -87,7 +87,7 @@ extension RedisClient {
public func sadd<Value: RESPValueConvertible>(_ elements: [Value], to key: RedisKey) -> EventLoopFuture<Int> {
guard elements.count > 0 else { return self.eventLoop.makeSucceededFuture(0) }
var args: [RESPValue] = [.init(bulk: key)]
var args: [RESPValue] = [.init(from: key)]
args.append(convertingContentsOf: elements)
return send(command: "SADD", with: args)
......@@ -117,7 +117,7 @@ extension RedisClient {
public func srem<Value: RESPValueConvertible>(_ elements: [Value], from key: RedisKey) -> EventLoopFuture<Int> {
guard elements.count > 0 else { return self.eventLoop.makeSucceededFuture(0) }
var args: [RESPValue] = [.init(bulk: key)]
var args: [RESPValue] = [.init(from: key)]
args.append(convertingContentsOf: elements)
return send(command: "SREM", with: args)
......@@ -149,7 +149,7 @@ extension RedisClient {
guard count > 0 else { return self.eventLoop.makeSucceededFuture([]) }
let args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
.init(bulk: count)
]
return send(command: "SPOP", with: args)
......@@ -189,7 +189,7 @@ extension RedisClient {
guard count != 0 else { return self.eventLoop.makeSucceededFuture([]) }
let args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
.init(bulk: count)
]
return send(command: "SRANDMEMBER", with: args)
......@@ -231,8 +231,8 @@ extension RedisClient {
guard sourceKey != destKey else { return self.eventLoop.makeSucceededFuture(true) }
let args: [RESPValue] = [
.init(bulk: sourceKey),
.init(bulk: destKey),
.init(from: sourceKey),
.init(from: destKey),
element.convertedToRESPValue()
]
return send(command: "SMOVE", with: args)
......@@ -345,7 +345,7 @@ extension RedisClient {
public func sdiffstore(as destination: RedisKey, sources keys: [RedisKey]) -> EventLoopFuture<Int> {
assert(keys.count > 0, "At least 1 key should be provided.")
var args: [RESPValue] = [.init(bulk: destination)]
var args: [RESPValue] = [.init(from: destination)]
args.append(convertingContentsOf: keys)
return send(command: "SDIFFSTORE", with: args)
......@@ -414,7 +414,7 @@ extension RedisClient {
public func sinterstore(as destination: RedisKey, sources keys: [RedisKey]) -> EventLoopFuture<Int> {
assert(keys.count > 0, "At least 1 key should be provided.")
var args: [RESPValue] = [.init(bulk: destination)]
var args: [RESPValue] = [.init(from: destination)]
args.append(convertingContentsOf: keys)
return send(command: "SINTERSTORE", with: args)
......@@ -483,7 +483,7 @@ extension RedisClient {
public func sunionstore(as destination: RedisKey, sources keys: [RedisKey]) -> EventLoopFuture<Int> {
assert(keys.count > 0, "At least 1 key should be provided.")
var args: [RESPValue] = [.init(bulk: destination)]
var args: [RESPValue] = [.init(from: destination)]
args.append(convertingContentsOf: keys)
return send(command: "SUNIONSTORE", with: args)
......
......@@ -114,7 +114,7 @@ extension RedisClient {
inserting insertBehavior: RedisZaddInsertBehavior = .allElements,
returning returnBehavior: RedisZaddReturnBehavior = .insertedElementsCount
) -> EventLoopFuture<Int> {
var args: [RESPValue] = [.init(bulk: key)]
var args: [RESPValue] = [.init(from: key)]
args.append(convertingContentsOf: [insertBehavior.string, returnBehavior.string].compactMap({ $0 }))
args.add(contentsOf: elements, overestimatedCountBeingAdded: elements.count * 2) { (array, next) in
......@@ -175,7 +175,7 @@ extension RedisClient {
/// - Parameter key: The key of the sorted set.
/// - Returns: The number of elements in the sorted set.
public func zcard(of key: RedisKey) -> EventLoopFuture<Int> {
let args = [RESPValue(bulk: key)]
let args = [RESPValue(from: key)]
return send(command: "ZCARD", with: args)
.map()
}
......@@ -190,7 +190,7 @@ extension RedisClient {
@inlinable
public func zscore<Value: RESPValueConvertible>(of element: Value, in key: RedisKey) -> EventLoopFuture<Double?> {
let args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
element.convertedToRESPValue()
]
return send(command: "ZSCORE", with: args)
......@@ -264,7 +264,7 @@ extension RedisClient {
@inlinable
public func zrank<Value: RESPValueConvertible>(of element: Value, in key: RedisKey) -> EventLoopFuture<Int?> {
let args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
element.convertedToRESPValue()
]
return send(command: "ZRANK", with: args)
......@@ -283,7 +283,7 @@ extension RedisClient {
@inlinable
public func zrevrank<Value: RESPValueConvertible>(of element: Value, in key: RedisKey) -> EventLoopFuture<Int?> {
let args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
element.convertedToRESPValue()
]
return send(command: "ZREVRANK", with: args)
......@@ -364,7 +364,7 @@ extension RedisClient {
) -> EventLoopFuture<Int> {
guard range.min.rawValue <= range.max.rawValue else { return self.eventLoop.makeSucceededFuture(0) }
let args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
.init(bulk: range.min.description),
.init(bulk: range.max.description)
]
......@@ -493,7 +493,7 @@ extension RedisClient {
withValuesBetween range: (min: RedisZLexBound<Value>, max: RedisZLexBound<Value>)
) -> EventLoopFuture<Int> {
let args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
.init(bulk: range.min.description),
.init(bulk: range.max.description)
]
......@@ -602,7 +602,7 @@ extension RedisClient {
_ count: Int?,
_ key: RedisKey
) -> EventLoopFuture<[(RESPValue, Double)]> {
var args: [RESPValue] = [.init(bulk: key)]
var args: [RESPValue] = [.init(from: key)]
if let c = count {
guard c != 0 else { return self.eventLoop.makeSucceededFuture([]) }
......@@ -774,7 +774,7 @@ extension RedisClient {
in key: RedisKey
) -> EventLoopFuture<Double> {
let args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
.init(bulk: amount.description),
element.convertedToRESPValue()
]
......@@ -848,7 +848,7 @@ extension RedisClient {
assert(sources.count > 0, "At least 1 source key should be provided.")
var args: [RESPValue] = [
.init(bulk: destination),
.init(from: destination),
.init(bulk: sources.count)
]
args.append(convertingContentsOf: sources)
......@@ -1258,7 +1258,7 @@ extension RedisClient {
_ withScores: Bool
) -> EventLoopFuture<[RESPValue]> {
var args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
.init(bulk: start),
.init(bulk: stop)
]
......@@ -1531,7 +1531,7 @@ extension RedisClient {
_ limit: (offset: Int, count: Int)?
) -> EventLoopFuture<[RESPValue]> {
var args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
.init(bulk: range.min),
.init(bulk: range.max)
]
......@@ -1723,7 +1723,7 @@ extension RedisClient {
_ limit: (offset: Int, count: Int)?
) -> EventLoopFuture<[RESPValue]> {
var args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
.init(bulk: range.min),
.init(bulk: range.max)
]
......@@ -1754,7 +1754,7 @@ extension RedisClient {
public func zrem<Value: RESPValueConvertible>(_ elements: [Value], from key: RedisKey) -> EventLoopFuture<Int> {
guard elements.count > 0 else { return self.eventLoop.makeSucceededFuture(0) }
var args: [RESPValue] = [.init(bulk: key)]
var args: [RESPValue] = [.init(from: key)]
args.append(convertingContentsOf: elements)
return send(command: "ZREM", with: args)
......@@ -1798,7 +1798,7 @@ extension RedisClient {
withValuesBetween range: (min: RedisZLexBound<Value>, max: RedisZLexBound<Value>)
) -> EventLoopFuture<Int> {
let args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
.init(bulk: range.min.description),
.init(bulk: range.max.description)
]
......@@ -1866,7 +1866,7 @@ extension RedisClient {
/// - Returns: The count of elements that were removed from the SortedSet.
public func zremrangebyrank(from key: RedisKey, firstIndex: Int, lastIndex: Int) -> EventLoopFuture<Int> {
let args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
.init(bulk: firstIndex),
.init(bulk: lastIndex)
]
......@@ -1954,7 +1954,7 @@ extension RedisClient {
withScoresBetween range: (min: RedisZScoreBound, max: RedisZScoreBound)
) -> EventLoopFuture<Int> {
let args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
.init(bulk: range.min.description),
.init(bulk: range.max.description)
]
......
......@@ -23,7 +23,7 @@ extension RedisClient {
/// - Parameter key: The key to fetch the value from.
/// - Returns: The value stored at the key provided. If the key does not exist, the value will be `.null`.
public func get(_ key: RedisKey) -> EventLoopFuture<RESPValue> {
let args = [RESPValue(bulk: key)]
let args = [RESPValue(from: key)]
return self.send(command: "GET", with: args)
}
......@@ -105,7 +105,7 @@ extension RedisClient {
@inlinable
public func append<Value: RESPValueConvertible>(_ value: Value, to key: RedisKey) -> EventLoopFuture<Int> {
let args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
value.convertedToRESPValue()
]
return send(command: "APPEND", with: args)
......@@ -126,7 +126,7 @@ extension RedisClient {
@inlinable
public func set<Value: RESPValueConvertible>(_ key: RedisKey, to value: Value) -> EventLoopFuture<Void> {
let args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
value.convertedToRESPValue()
]
return send(command: "SET", with: args)
......@@ -168,7 +168,7 @@ extension RedisClient {
let args: [RESPValue] = operations.reduce(
into: .init(initialCapacity: operations.count * 2),
{ (array, element) in
array.append(.init(bulk: element.key))
array.append(.init(from: element.key))
array.append(element.value.convertedToRESPValue())
}
)
......@@ -186,7 +186,7 @@ extension RedisClient {
/// - Parameter key: The key whose value should be incremented.
/// - Returns: The new value after the operation.
public func increment(_ key: RedisKey) -> EventLoopFuture<Int> {
let args = [RESPValue(bulk: key)]
let args = [RESPValue(from: key)]
return send(command: "INCR", with: args)
.map()
}
......@@ -204,7 +204,7 @@ extension RedisClient {
by count: Value
) -> EventLoopFuture<Value> {
let args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
.init(bulk: count)
]
return send(command: "INCRBY", with: args)
......@@ -224,7 +224,7 @@ extension RedisClient {
by count: Value
) -> EventLoopFuture<Value> {
let args: [RESPValue] = [
.init(bulk: key),
.init(from: key),
count.convertedToRESPValue()
]
return send(command: "INCRBYFLOAT", with: args)
......@@ -242,7 +242,7 @@ extension RedisClient {
/// - Returns: The new value after the operation.
@inlinable
public func decrement(_ key: RedisKey) -> EventLoopFuture<Int> {
let args = [RESPValue(bulk: key)]
let args = [RESPValue(from: key)]
return send(command: "DECR", with: args)
.map()
}
......@@ -260,7 +260,7 @@ extension RedisClient {