Skip to content

Commit 2dd1d30

Browse files
authored
Merge pull request #22 from Mordil/command-audit
Command audit
2 parents 601431a + 16dc4ac commit 2dd1d30

13 files changed

+1312
-944
lines changed

Sources/NIORedis/Commands/BasicCommands.swift

Lines changed: 55 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ extension RedisCommandExecutor {
77
/// See [https://redis.io/commands/echo](https://redis.io/commands/echo)
88
/// - Parameter message: The message to echo.
99
/// - Returns: The message sent with the command.
10+
@inlinable
1011
public func echo(_ message: String) -> EventLoopFuture<String> {
1112
return send(command: "ECHO", with: [message])
1213
.mapFromRESP()
@@ -15,8 +16,9 @@ extension RedisCommandExecutor {
1516
/// Pings the server, which will respond with a message.
1617
///
1718
/// See [https://redis.io/commands/ping](https://redis.io/commands/ping)
18-
/// - Parameter with: The optional message that the server should respond with.
19+
/// - Parameter message: The optional message that the server should respond with.
1920
/// - Returns: The provided message or Redis' default response of `"PONG"`.
21+
@inlinable
2022
public func ping(with message: String? = nil) -> EventLoopFuture<String> {
2123
let arg = message != nil ? [message] : []
2224
return send(command: "PING", with: arg)
@@ -26,196 +28,102 @@ extension RedisCommandExecutor {
2628
/// Request for authentication in a password-protected Redis server.
2729
///
2830
/// [https://redis.io/commands/auth](https://redis.io/commands/auth)
31+
/// - Parameter password: The password being used to access the Redis server.
32+
/// - Returns: An `EventLoopFuture` that resolves when the connection has been authorized, or fails with a `RedisError`.
33+
@inlinable
2934
public func authorize(with password: String) -> EventLoopFuture<Void> {
3035
return send(command: "AUTH", with: [password])
3136
.map { _ in return () }
3237
}
3338

3439
/// Select the Redis logical database having the specified zero-based numeric index.
35-
/// New connections always use the database `0`.
40+
/// - Note: New connections always use the database `0`.
3641
///
3742
/// [https://redis.io/commands/select](https://redis.io/commands/select)
38-
public func select(database id: Int) -> EventLoopFuture<Void> {
39-
return send(command: "SELECT", with: [id.description])
43+
/// - Parameter index: The 0-based index of the database that will receive later commands.
44+
/// - Returns: An `EventLoopFuture` that resolves when the operation has succeeded, or fails with a `RedisError`.
45+
@inlinable
46+
public func select(database index: Int) -> EventLoopFuture<Void> {
47+
return send(command: "SELECT", with: [index])
4048
.map { _ in return () }
4149
}
4250

43-
/// Swaps the data of two Redis database by their index ID.
51+
/// Swaps the data of two Redis databases by their index IDs.
4452
///
4553
/// See [https://redis.io/commands/swapdb](https://redis.io/commands/swapdb)
4654
/// - Parameters:
47-
/// - firstIndex: The index of the first database.
48-
/// - secondIndex: The index of the second database.
55+
/// - first: The index of the first database.
56+
/// - second: The index of the second database.
4957
/// - Returns: `true` if the swap was successful.
50-
public func swapdb(firstIndex: Int, secondIndex: Int) -> EventLoopFuture<Bool> {
51-
return send(command: "SWAPDB", with: [firstIndex, secondIndex])
58+
@inlinable
59+
public func swapDatabase(_ first: Int, with second: Int) -> EventLoopFuture<Bool> {
60+
/// connection.swapDatabase(index: 0, withIndex: 10)
61+
return send(command: "SWAPDB", with: [first, second])
5262
.mapFromRESP(to: String.self)
5363
.map { return $0 == "OK" }
5464
}
55-
}
5665

57-
extension RedisCommandExecutor {
5866
/// Removes the specified keys. A key is ignored if it does not exist.
5967
///
6068
/// [https://redis.io/commands/del](https://redis.io/commands/del)
61-
/// - Returns: A future number of keys that were removed.
62-
public func delete(_ keys: String...) -> EventLoopFuture<Int> {
69+
/// - Parameter keys: A list of keys to delete from the database.
70+
/// - Returns: The number of keys deleted from the database.
71+
@inlinable
72+
public func delete(_ keys: [String]) -> EventLoopFuture<Int> {
73+
guard keys.count > 0 else { return self.eventLoop.makeSucceededFuture(0) }
74+
6375
return send(command: "DEL", with: keys)
6476
.mapFromRESP()
6577
}
6678

67-
/// Set a timeout on key. After the timeout has expired, the key will automatically be deleted.
68-
/// A key with an associated timeout is often said to be volatile in Redis terminology.
79+
/// Sets a timeout on key. After the timeout has expired, the key will automatically be deleted.
80+
/// - Note: A key with an associated timeout is often said to be "volatile" in Redis terminology.
6981
///
7082
/// [https://redis.io/commands/expire](https://redis.io/commands/expire)
7183
/// - Parameters:
72-
/// - after: The lifetime (in seconds) the key will expirate at.
73-
/// - Returns: A future bool indicating if the expiration was set or not.
74-
public func expire(_ key: String, after deadline: Int) -> EventLoopFuture<Bool> {
75-
return send(command: "EXPIRE", with: [key, deadline.description])
76-
.mapFromRESP(to: Int.self)
77-
.map { return $0 == 1 }
78-
}
79-
80-
/// Get the value of a key.
81-
/// If the key does not exist the value will be `nil`.
82-
/// An error is resolved if the value stored at key is not a string, because GET only handles string values.
83-
///
84-
/// [https://redis.io/commands/get](https://redis.io/commands/get)
85-
public func get(_ key: String) -> EventLoopFuture<String?> {
86-
return send(command: "GET", with: [key])
87-
.map { return $0.string }
88-
}
89-
90-
/// Returns the values of all specified keys, using `.null` to represent non-existant values.
91-
///
92-
/// See [https://redis.io/commands/mget](https://redis.io/commands/mget)
93-
public func mget(_ keys: [String]) -> EventLoopFuture<[RESPValue]> {
94-
assert(keys.count > 0, "At least 1 key should be provided.")
95-
96-
return send(command: "MGET", with: keys)
97-
.mapFromRESP()
98-
}
99-
100-
/// Set key to hold the string value.
101-
/// If key already holds a value, it is overwritten, regardless of its type.
102-
/// Any previous time to live associated with the key is discarded on successful SET operation.
103-
///
104-
/// [https://redis.io/commands/set](https://redis.io/commands/set)
105-
public func set(_ key: String, to value: String) -> EventLoopFuture<Void> {
106-
return send(command: "SET", with: [key, value])
107-
.map { _ in return () }
108-
}
109-
110-
/// Sets each key to the respective new value, overwriting existing values.
111-
///
112-
/// - Note: Use `msetnx` if you don't want to overwrite values.
113-
///
114-
/// See [https://redis.io/commands/mset](https://redis.io/commands/mset)
115-
public func mset(_ operations: [String: RESPValueConvertible]) -> EventLoopFuture<Void> {
116-
assert(operations.count > 0, "At least 1 key-value pair should be provided.")
117-
118-
let args = _convertMSET(operations)
119-
return send(command: "MSET", with: args)
120-
.map { _ in return () }
121-
}
122-
123-
/// If every key does not exist, sets each key to the respective new value.
124-
///
125-
/// See [https://redis.io/commands/msetnx](https://redis.io/commands/msetnx)
126-
public func msetnx(_ operations: [String: RESPValueConvertible]) -> EventLoopFuture<Bool> {
127-
assert(operations.count > 0, "At least 1 key-value pair should be provided.")
128-
129-
let args = _convertMSET(operations)
130-
return send(command: "MSETNX", with: args)
84+
/// - key: The key to set the expiration on.
85+
/// - deadline: The time from now the key will expire at.
86+
/// - Returns: `true` if the expiration was set.
87+
@inlinable
88+
public func expire(_ key: String, after deadline: TimeAmount) -> EventLoopFuture<Bool> {
89+
let amount = deadline.nanoseconds / 1_000_000_000
90+
return send(command: "EXPIRE", with: [key, amount])
13191
.mapFromRESP(to: Int.self)
13292
.map { return $0 == 1 }
13393
}
134-
135-
@inline(__always)
136-
private func _convertMSET(_ source: [String: RESPValueConvertible]) -> [RESPValueConvertible] {
137-
return source.reduce(into: [RESPValueConvertible](), { (result, element) in
138-
result.append(element.key)
139-
result.append(element.value)
140-
})
141-
}
14294
}
14395

144-
extension RedisCommandExecutor {
145-
/// Increments the stored value by 1 and returns the new value.
146-
///
147-
/// See [https://redis.io/commands/incr](https://redis.io/commands/incr)
148-
/// - Returns: The new value after the operation.
149-
public func increment(_ key: String) -> EventLoopFuture<Int> {
150-
return send(command: "INCR", with: [key])
151-
.mapFromRESP()
152-
}
153-
154-
/// Increments the stored value by the amount desired and returns the new value.
155-
///
156-
/// See [https://redis.io/commands/incrby](https://redis.io/commands/incrby)
157-
/// - Returns: The new value after the operation.
158-
public func increment(_ key: String, by count: Int) -> EventLoopFuture<Int> {
159-
return send(command: "INCRBY", with: [key, count])
160-
.mapFromRESP()
161-
}
162-
163-
/// Increments the stored value by the amount desired and returns the new value.
164-
///
165-
/// See [https://redis.io/commands/incrbyfloat](https://redis.io/commands/incrbyfloat)
166-
/// - Returns: The new value after the operation.
167-
public func increment<T: BinaryFloatingPoint>(_ key: String, by count: T) -> EventLoopFuture<T>
168-
where T: RESPValueConvertible
169-
{
170-
return send(command: "INCRBYFLOAT", with: [key, count])
171-
.mapFromRESP()
172-
}
173-
174-
/// Decrements the stored value by 1 and returns the new value.
175-
///
176-
/// See [https://redis.io/commands/decr](https://redis.io/commands/decr)
177-
/// - Returns: The new value after the operation.
178-
public func decrement(_ key: String) -> EventLoopFuture<Int> {
179-
return send(command: "DECR", with: [key])
180-
.mapFromRESP()
181-
}
182-
183-
/// Decrements the stored valye by the amount desired and returns the new value.
184-
///
185-
/// See [https://redis.io/commands/decrby](https://redis.io/commands/decrby)
186-
/// - Returns: The new value after the operation.
187-
public func decrement(_ key: String, by count: Int) -> EventLoopFuture<Int> {
188-
return send(command: "DECRBY", with: [key, count])
189-
.mapFromRESP()
190-
}
191-
}
96+
// MARK: Scan
19297

19398
extension RedisCommandExecutor {
19499
/// Incrementally iterates over all keys in the currently selected database.
195100
///
196101
/// [https://redis.io/commands/scan](https://redis.io/commands/scan)
197102
/// - Parameters:
198-
/// - startingFrom: The cursor position to start from.
103+
/// - position: The cursor position to start from.
199104
/// - count: The number of elements to advance by. Redis default is 10.
200-
/// - matching: A glob-style pattern to filter values to be selected from the result set.
201-
/// - Returns: A cursor position for additional invocations with a limited collection of keys stored in the database.
105+
/// - match: A glob-style pattern to filter values to be selected from the result set.
106+
/// - Returns: A cursor position for additional invocations with a limited collection of keys found in the database.
202107
@inlinable
203108
public func scan(
204-
startingFrom pos: Int = 0,
109+
startingFrom position: Int = 0,
205110
count: Int? = nil,
206-
matching match: String? = nil) -> EventLoopFuture<(Int, [String])>
207-
{
208-
return _scan(command: "SCAN", resultType: [String].self, nil, pos, count, match)
111+
matching match: String? = nil
112+
) -> EventLoopFuture<(Int, [String])> {
113+
return _scan(command: "SCAN", nil, position, count, match)
209114
}
210115

211-
@inline(__always)
212-
@usableFromInline func _scan<T: RESPValueConvertible>(
116+
@usableFromInline
117+
func _scan<T>(
213118
command: String,
214-
resultType: T.Type,
119+
resultType: T.Type = T.self,
215120
_ key: String?,
216121
_ pos: Int,
217122
_ count: Int?,
218-
_ match: String?) -> EventLoopFuture<(Int, T)>
123+
_ match: String?
124+
) -> EventLoopFuture<(Int, T)>
125+
where
126+
T: RESPValueConvertible
219127
{
220128
var args: [RESPValueConvertible] = [pos]
221129

@@ -237,7 +145,12 @@ extension RedisCommandExecutor {
237145
guard
238146
let value = result[0].string,
239147
let position = Int(value)
240-
else { throw RedisError(identifier: #function, reason: "Unexpected value in response: \(result[0])") }
148+
else {
149+
throw RedisError(
150+
identifier: #function,
151+
reason: "Unexpected value in response: \(result[0])"
152+
)
153+
}
241154
return position
242155
}
243156
let elements = response

0 commit comments

Comments
 (0)