1
+ import Logging
2
+ import Foundation
1
3
import NIO
2
4
import NIOConcurrencyHelpers
3
5
@@ -51,6 +53,8 @@ extension RedisConnection {
51
53
public var eventLoop : EventLoop { return self . channel. eventLoop }
52
54
}
53
55
56
+ private let loggingKeyID = " RedisConnection "
57
+
54
58
/// A basic `RedisConnection`.
55
59
public final class NIORedisConnection : RedisConnection {
56
60
/// See `RedisConnection.channel`.
@@ -60,36 +64,51 @@ public final class NIORedisConnection: RedisConnection {
60
64
public var isClosed : Bool { return _isClosed. load ( ) }
61
65
private var _isClosed = Atomic < Bool > ( value: false )
62
66
67
+ private var logger : Logger
68
+
63
69
deinit { assert ( _isClosed. load ( ) , " Redis connection was not properly shut down! " ) }
64
70
65
71
/// Creates a new connection on the provided channel.
66
72
/// - Note: This connection will take ownership of the `Channel` object.
67
73
/// - Important: Call `close()` before deinitializing to properly cleanup resources.
68
- public init ( channel: Channel ) {
74
+ public init ( channel: Channel , logger : Logger = Logger ( label : " NIORedis.Connection " ) ) {
69
75
self . channel = channel
76
+ self . logger = logger
77
+
78
+ self . logger [ metadataKey: loggingKeyID] = " \( UUID ( ) ) "
79
+ self . logger. debug ( " Connection created. " )
70
80
}
71
81
72
82
/// See `RedisConnection.close()`.
73
83
@discardableResult
74
84
public func close( ) -> EventLoopFuture < Void > {
75
- guard !_isClosed. exchange ( with: true ) else { return channel. eventLoop. makeSucceededFuture ( ( ) ) }
85
+ guard !_isClosed. exchange ( with: true ) else {
86
+ logger. notice ( " Connection received more than one close() request. " )
87
+ return channel. eventLoop. makeSucceededFuture ( ( ) )
88
+ }
76
89
77
90
return send ( command: " QUIT " )
78
91
. flatMap { _ in
79
92
let promise = self . channel. eventLoop. makePromise ( of: Void . self)
80
93
self . channel. close ( promise: promise)
81
94
return promise. futureResult
82
95
}
96
+ . map { self . logger. debug ( " Connection closed. " ) }
83
97
}
84
98
85
99
/// See `RedisConnection.makePipeline()`.
86
100
public func makePipeline( ) -> RedisPipeline {
87
- return NIORedisPipeline ( channel: channel)
101
+ var logger = Logger ( label: " NIORedis.Pipeline " )
102
+ logger [ metadataKey: loggingKeyID] = self . logger [ metadataKey: loggingKeyID]
103
+ return NIORedisPipeline ( channel: channel, logger: logger)
88
104
}
89
105
90
106
/// See `RedisCommandExecutor.send(command:with:)`.
91
107
public func send( command: String , with arguments: [ RESPValueConvertible ] = [ ] ) -> EventLoopFuture < RESPValue > {
92
- guard !_isClosed. load ( ) else { return channel. eventLoop. makeFailedFuture ( RedisError . connectionClosed) }
108
+ guard !_isClosed. load ( ) else {
109
+ logger. error ( " Received command when connection is closed. " )
110
+ return channel. eventLoop. makeFailedFuture ( RedisError . connectionClosed)
111
+ }
93
112
94
113
let args = arguments. map { $0. convertedToRESPValue ( ) }
95
114
@@ -99,6 +118,12 @@ public final class NIORedisConnection: RedisConnection {
99
118
promise: promise
100
119
)
101
120
121
+ promise. futureResult. whenComplete { result in
122
+ guard case let . failure( error) = result else { return }
123
+ self . logger. error ( " \( error) " )
124
+ }
125
+ logger. debug ( " Sending command \" \( command) \" with \( arguments) encoded as \( args) " )
126
+
102
127
_ = channel. writeAndFlush ( context)
103
128
104
129
return promise. futureResult
0 commit comments