1
1
import NIO
2
2
import NIOConcurrencyHelpers
3
3
4
- /// A connection to a Redis database instance, with the ability to send and receive commands .
4
+ /// An object capable of sending commands and receiving responses .
5
5
///
6
- /// let result = connection.send(command: "GET", arguments: ["my_key"]
6
+ /// let executor = ...
7
+ /// let result = executor.send(command: "GET", arguments: ["my_key"]
7
8
/// // result == EventLoopFuture<RESPValue>
8
9
///
9
10
/// See [https://redis.io/commands](https://redis.io/commands)
10
- public final class RedisConnection {
11
+ public protocol RedisCommandExecutor {
12
+ /// The `EventLoop` that this executor operates on.
13
+ var eventLoop : EventLoop { get }
14
+
15
+ /// Sends the desired command with the specified arguments.
16
+ /// - Parameters:
17
+ /// - command: The command to execute.
18
+ /// - arguments: The arguments, if any, to be sent with the command.
19
+ /// - Returns: An `EventLoopFuture` that will resolve with the Redis command response.
20
+ func send( command: String , with arguments: [ RESPValueConvertible ] ) -> EventLoopFuture < RESPValue >
21
+ }
22
+
23
+ extension RedisCommandExecutor {
24
+ /// Sends the desired command without arguments.
25
+ /// - Parameter command: The command keyword to execute.
26
+ /// - Returns: An `EventLoopFuture` that will resolve with the Redis command response.
27
+ func send( command: String ) -> EventLoopFuture < RESPValue > {
28
+ return self . send ( command: command, with: [ ] )
29
+ }
30
+ }
31
+
32
+ /// An individual connection to a Redis database instance for executing commands or building `RedisPipeline`s.
33
+ ///
34
+ /// See `RedisCommandExecutor`.
35
+ public protocol RedisConnection : AnyObject , RedisCommandExecutor {
11
36
/// The `Channel` this connection is associated with.
37
+ var channel : Channel { get }
38
+ /// Has the connection been closed?
39
+ var isClosed : Bool { get }
40
+
41
+ /// Creates a `RedisPipeline` for executing a batch of commands.
42
+ func makePipeline( ) -> RedisPipeline
43
+
44
+ /// Closes the connection to Redis.
45
+ /// - Returns: An `EventLoopFuture` that resolves when the connection has been closed.
46
+ @discardableResult
47
+ func close( ) -> EventLoopFuture < Void >
48
+ }
49
+
50
+ extension RedisConnection {
51
+ public var eventLoop : EventLoop { return self . channel. eventLoop }
52
+ }
53
+
54
+ /// A basic `RedisConnection`.
55
+ public final class NIORedisConnection : RedisConnection {
56
+ /// See `RedisConnection.channel`.
12
57
public let channel : Channel
13
58
14
- /// Has the connection been closed?
59
+ /// See `RedisConnection.isClosed`.
15
60
public var isClosed : Bool { return _isClosed. load ( ) }
16
61
private var _isClosed = Atomic < Bool > ( value: false )
17
62
@@ -24,8 +69,7 @@ public final class RedisConnection {
24
69
self . channel = channel
25
70
}
26
71
27
- /// Closes the connection to Redis.
28
- /// - Returns: An `EventLoopFuture` that resolves when the connection has been closed.
72
+ /// See `RedisConnection.close()`.
29
73
@discardableResult
30
74
public func close( ) -> EventLoopFuture < Void > {
31
75
guard !_isClosed. exchange ( with: true ) else { return channel. eventLoop. makeSucceededFuture ( ( ) ) }
@@ -38,40 +82,25 @@ public final class RedisConnection {
38
82
}
39
83
}
40
84
41
- /// Sends the desired command with the specified arguments.
42
- /// - Parameters:
43
- /// - command: The command to execute.
44
- /// - arguments: The arguments to be sent with the command.
45
- /// - Returns: An `EventLoopFuture` that will resolve with the Redis command response.
46
- public func send( command: String , with arguments: [ RESPValueConvertible ] = [ ] ) -> EventLoopFuture < RESPValue > {
47
- let args = arguments. map { $0. convertedToRESPValue ( ) }
48
- return self . command ( command, arguments: args)
85
+ /// See `RedisConnection.makePipeline()`.
86
+ public func makePipeline( ) -> RedisPipeline {
87
+ return NIORedisPipeline ( channel: channel)
49
88
}
50
89
51
- /// Invokes a command against Redis with the provided arguments.
52
- /// - Important: Arguments should be stored as `.bulkString`.
53
- /// - Parameters:
54
- /// - command: The command to execute.
55
- /// - arguments: The arguments to be sent with the command.
56
- /// - Returns: An `EventLoopFuture` that will resolve with the Redis command response.
57
- public func command( _ command: String , arguments: [ RESPValue ] = [ ] ) -> EventLoopFuture < RESPValue > {
58
- guard !_isClosed. load ( ) else {
59
- return channel. eventLoop. makeFailedFuture ( RedisError . connectionClosed)
60
- }
90
+ /// See `RedisCommandExecutor.send(command:with:)`.
91
+ public func send( command: String , with arguments: [ RESPValueConvertible ] = [ ] ) -> EventLoopFuture < RESPValue > {
92
+ guard !_isClosed. load ( ) else { return channel. eventLoop. makeFailedFuture ( RedisError . connectionClosed) }
93
+
94
+ let args = arguments. map { $0. convertedToRESPValue ( ) }
61
95
62
96
let promise = channel. eventLoop. makePromise ( of: RESPValue . self)
63
97
let context = RedisCommandContext (
64
- command: . array( [ RESPValue ( bulk: command) ] + arguments ) ,
98
+ command: . array( [ RESPValue ( bulk: command) ] + args ) ,
65
99
promise: promise
66
100
)
67
101
68
102
_ = channel. writeAndFlush ( context)
69
103
70
104
return promise. futureResult
71
105
}
72
-
73
- /// Creates a `RedisPipeline` for executing a batch of commands.
74
- public func makePipeline( ) -> RedisPipeline {
75
- return . init( channel: channel)
76
- }
77
106
}
0 commit comments