11import NIO
22import NIOConcurrencyHelpers
33
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 .
55///
6- /// let result = connection.send(command: "GET", arguments: ["my_key"]
6+ /// let executor = ...
7+ /// let result = executor.send(command: "GET", arguments: ["my_key"]
78/// // result == EventLoopFuture<RESPValue>
89///
910/// 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 {
1136 /// 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`.
1257 public let channel : Channel
1358
14- /// Has the connection been closed?
59+ /// See `RedisConnection.isClosed`.
1560 public var isClosed : Bool { return _isClosed. load ( ) }
1661 private var _isClosed = Atomic < Bool > ( value: false )
1762
@@ -24,8 +69,7 @@ public final class RedisConnection {
2469 self . channel = channel
2570 }
2671
27- /// Closes the connection to Redis.
28- /// - Returns: An `EventLoopFuture` that resolves when the connection has been closed.
72+ /// See `RedisConnection.close()`.
2973 @discardableResult
3074 public func close( ) -> EventLoopFuture < Void > {
3175 guard !_isClosed. exchange ( with: true ) else { return channel. eventLoop. makeSucceededFuture ( ( ) ) }
@@ -38,40 +82,25 @@ public final class RedisConnection {
3882 }
3983 }
4084
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)
4988 }
5089
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 ( ) }
6195
6296 let promise = channel. eventLoop. makePromise ( of: RESPValue . self)
6397 let context = RedisCommandContext (
64- command: . array( [ RESPValue ( bulk: command) ] + arguments ) ,
98+ command: . array( [ RESPValue ( bulk: command) ] + args ) ,
6599 promise: promise
66100 )
67101
68102 _ = channel. writeAndFlush ( context)
69103
70104 return promise. futureResult
71105 }
72-
73- /// Creates a `RedisPipeline` for executing a batch of commands.
74- public func makePipeline( ) -> RedisPipeline {
75- return . init( channel: channel)
76- }
77106}
0 commit comments