@@ -2,6 +2,35 @@ import Foundation
2
2
import NIO
3
3
4
4
extension RedisCommandExecutor {
5
+ /// Echos the provided message through the Redis instance.
6
+ ///
7
+ /// See [https://redis.io/commands/echo](https://redis.io/commands/echo)
8
+ /// - Parameter message: The message to echo.
9
+ /// - Returns: The message sent with the command.
10
+ public func echo( _ message: String ) -> EventLoopFuture < String > {
11
+ return send ( command: " ECHO " , with: [ message] )
12
+ . mapFromRESP ( )
13
+ }
14
+
15
+ /// Pings the server, which will respond with a message.
16
+ ///
17
+ /// See [https://redis.io/commands/ping](https://redis.io/commands/ping)
18
+ /// - Parameter with: The optional message that the server should respond with.
19
+ /// - Returns: The provided message or Redis' default response of `"PONG"`.
20
+ public func ping( with message: String ? = nil ) -> EventLoopFuture < String > {
21
+ let arg = message != nil ? [ message] : [ ]
22
+ return send ( command: " PING " , with: arg)
23
+ . mapFromRESP ( )
24
+ }
25
+
26
+ /// Request for authentication in a password-protected Redis server.
27
+ ///
28
+ /// [https://redis.io/commands/auth](https://redis.io/commands/auth)
29
+ public func authorize( with password: String ) -> EventLoopFuture < Void > {
30
+ return send ( command: " AUTH " , with: [ password] )
31
+ . map { _ in return ( ) }
32
+ }
33
+
5
34
/// Select the Redis logical database having the specified zero-based numeric index.
6
35
/// New connections always use the database `0`.
7
36
///
@@ -11,26 +40,28 @@ extension RedisCommandExecutor {
11
40
. map { _ in return ( ) }
12
41
}
13
42
14
- /// Request for authentication in a password-protected Redis server .
43
+ /// Swaps the data of two Redis database by their index ID .
15
44
///
16
- /// [https://redis.io/commands/auth](https://redis.io/commands/auth)
17
- public func authorize( with password: String ) -> EventLoopFuture < Void > {
18
- return send ( command: " AUTH " , with: [ password] )
19
- . map { _ in return ( ) }
45
+ /// See [https://redis.io/commands/swapdb](https://redis.io/commands/swapdb)
46
+ /// - Parameters:
47
+ /// - firstIndex: The index of the first database.
48
+ /// - secondIndex: The index of the second database.
49
+ /// - 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] )
52
+ . mapFromRESP ( to: String . self)
53
+ . map { return $0 == " OK " }
20
54
}
55
+ }
21
56
57
+ extension RedisCommandExecutor {
22
58
/// Removes the specified keys. A key is ignored if it does not exist.
23
59
///
24
60
/// [https://redis.io/commands/del](https://redis.io/commands/del)
25
61
/// - Returns: A future number of keys that were removed.
26
62
public func delete( _ keys: String ... ) -> EventLoopFuture < Int > {
27
63
return send ( command: " DEL " , with: keys)
28
- . flatMapThrowing { res in
29
- guard let count = res. int else {
30
- throw RedisError ( identifier: " delete " , reason: " Unexpected response: \( res) " )
31
- }
32
- return count
33
- }
64
+ . mapFromRESP ( )
34
65
}
35
66
36
67
/// Set a timeout on key. After the timeout has expired, the key will automatically be deleted.
@@ -42,12 +73,8 @@ extension RedisCommandExecutor {
42
73
/// - Returns: A future bool indicating if the expiration was set or not.
43
74
public func expire( _ key: String , after deadline: Int ) -> EventLoopFuture < Bool > {
44
75
return send ( command: " EXPIRE " , with: [ key, deadline. description] )
45
- . flatMapThrowing { res in
46
- guard let value = res. int else {
47
- throw RedisError ( identifier: " expire " , reason: " Unexpected response: \( res) " )
48
- }
49
- return value == 1
50
- }
76
+ . mapFromRESP ( to: Int . self)
77
+ . map { return $0 == 1 }
51
78
}
52
79
53
80
/// Get the value of a key.
@@ -60,6 +87,16 @@ extension RedisCommandExecutor {
60
87
. map { return $0. string }
61
88
}
62
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
+
63
100
/// Set key to hold the string value.
64
101
/// If key already holds a value, it is overwritten, regardless of its type.
65
102
/// Any previous time to live associated with the key is discarded on successful SET operation.
@@ -70,39 +107,85 @@ extension RedisCommandExecutor {
70
107
. map { _ in return ( ) }
71
108
}
72
109
73
- /// Echos the provided message through the Redis instance.
74
- /// - Parameter message: The message to echo.
75
- /// - Returns: The message sent with the command.
76
- public func echo( _ message: String ) -> EventLoopFuture < String > {
77
- return send ( command: " ECHO " , with: [ message] )
78
- . flatMapThrowing {
79
- guard let response = $0. string else { throw RedisError . respConversion ( to: String . self) }
80
- return response
81
- }
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 ( ) }
82
121
}
83
122
84
- /// Pings the server, which will respond with a message .
85
- /// - Parameter with: The optional message that the server should respond with.
86
- /// - Returns: The provided message or Redis' default response of `"PONG"`.
87
- public func ping ( with message : String ? = nil ) -> EventLoopFuture < String > {
88
- let arg = message != nil ? [ message ] : [ ]
89
- return send ( command : " PING " , with : arg )
90
- . flatMapThrowing {
91
- guard let response = $0 . string else { throw RedisError . respConversion ( to : String . self ) }
92
- return response
93
- }
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 )
131
+ . mapFromRESP ( to : Int . self )
132
+ . map { return $0 == 1 }
94
133
}
95
134
96
- /// Swaps the data of two Redis database by their index ID.
97
- /// - Parameters:
98
- /// - firstIndex: The index of the first database.
99
- /// - secondIndex: The index of the second database.
100
- /// - Returns: `true` if the swap was successful.
101
- public func swapdb( firstIndex: Int , secondIndex: Int ) -> EventLoopFuture < Bool > {
102
- return send ( command: " SWAPDB " , with: [ firstIndex, secondIndex] )
103
- . flatMapThrowing {
104
- guard let response = $0. string else { throw RedisError . respConversion ( to: String . self) }
105
- return response == " OK "
106
- }
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
+ }
142
+ }
143
+
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 ( )
107
190
}
108
191
}
0 commit comments