1+ import Logging
2+ import Foundation
13import NIO
24import NIOConcurrencyHelpers
35
@@ -51,6 +53,8 @@ extension RedisConnection {
5153 public var eventLoop : EventLoop { return self . channel. eventLoop }
5254}
5355
56+ private let loggingKeyID = " RedisConnection "
57+
5458/// A basic `RedisConnection`.
5559public final class NIORedisConnection : RedisConnection {
5660 /// See `RedisConnection.channel`.
@@ -60,36 +64,51 @@ public final class NIORedisConnection: RedisConnection {
6064 public var isClosed : Bool { return _isClosed. load ( ) }
6165 private var _isClosed = Atomic < Bool > ( value: false )
6266
67+ private var logger : Logger
68+
6369 deinit { assert ( _isClosed. load ( ) , " Redis connection was not properly shut down! " ) }
6470
6571 /// Creates a new connection on the provided channel.
6672 /// - Note: This connection will take ownership of the `Channel` object.
6773 /// - 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 " ) ) {
6975 self . channel = channel
76+ self . logger = logger
77+
78+ self . logger [ metadataKey: loggingKeyID] = " \( UUID ( ) ) "
79+ self . logger. debug ( " Connection created. " )
7080 }
7181
7282 /// See `RedisConnection.close()`.
7383 @discardableResult
7484 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+ }
7689
7790 return send ( command: " QUIT " )
7891 . flatMap { _ in
7992 let promise = self . channel. eventLoop. makePromise ( of: Void . self)
8093 self . channel. close ( promise: promise)
8194 return promise. futureResult
8295 }
96+ . map { self . logger. debug ( " Connection closed. " ) }
8397 }
8498
8599 /// See `RedisConnection.makePipeline()`.
86100 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)
88104 }
89105
90106 /// See `RedisCommandExecutor.send(command:with:)`.
91107 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+ }
93112
94113 let args = arguments. map { $0. convertedToRESPValue ( ) }
95114
@@ -99,6 +118,12 @@ public final class NIORedisConnection: RedisConnection {
99118 promise: promise
100119 )
101120
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+
102127 _ = channel. writeAndFlush ( context)
103128
104129 return promise. futureResult
0 commit comments