@@ -40,17 +40,28 @@ private let loggingKeyID = "RedisConnection"
40
40
///
41
41
/// See `RedisClient`
42
42
public final class RedisConnection : RedisClient {
43
+ private enum ConnectionState {
44
+ case open
45
+ case closed
46
+ }
47
+
43
48
/// See `RedisClient.eventLoop`
44
49
public var eventLoop : EventLoop { return channel. eventLoop }
45
50
/// Is the client still connected to Redis?
46
- public var isConnected : Bool { return !sentQuitCommand . load ( ) }
51
+ public var isConnected : Bool { return state != . closed }
47
52
48
53
private let channel : Channel
49
54
private var logger : Logger
50
- private var sentQuitCommand = Atomic < Bool > ( value: false )
55
+
56
+ private let _stateLock = Lock ( )
57
+ private var _state : ConnectionState
58
+ private var state : ConnectionState {
59
+ get { return _stateLock. withLock { self . _state } }
60
+ set ( newValue) { _stateLock. withLockVoid { self . _state = newValue } }
61
+ }
51
62
52
63
deinit {
53
- if !sentQuitCommand . load ( ) {
64
+ if isConnected {
54
65
assertionFailure ( " close() was not called before deinit! " )
55
66
logger. warning ( " RedisConnection did not properly shutdown before deinit! " )
56
67
}
@@ -68,6 +79,7 @@ public final class RedisConnection: RedisClient {
68
79
69
80
self . logger [ metadataKey: loggingKeyID] = " \( UUID ( ) ) "
70
81
self . logger. debug ( " Connection created. " )
82
+ self . _state = . open
71
83
}
72
84
73
85
/// Sends a `QUIT` command, then closes the `Channel` this instance was initialized with.
@@ -76,10 +88,6 @@ public final class RedisConnection: RedisClient {
76
88
/// - Returns: An `EventLoopFuture` that resolves when the connection has been closed.
77
89
@discardableResult
78
90
public func close( ) -> EventLoopFuture < Void > {
79
- // this needs to be true in order to prevent multiple close() chains, and to stop
80
- // allowing commands to be sent - but we don't want to set it before we send the QUIT command
81
- defer { sentQuitCommand. store ( true ) }
82
-
83
91
guard isConnected else {
84
92
logger. notice ( " Connection received more than one close() request. " )
85
93
return channel. eventLoop. makeSucceededFuture ( ( ) )
@@ -94,9 +102,13 @@ public final class RedisConnection: RedisClient {
94
102
. map { self . logger. debug ( " Connection closed. " ) }
95
103
. recover {
96
104
self . logger. error ( " Encountered error during close(): \( $0) " )
97
- self . sentQuitCommand . store ( false )
105
+ self . state = . open
98
106
}
99
107
108
+ // setting it to closed now prevents multiple close() chains, but doesn't stop the QUIT command
109
+ // if the connection wasn't closed, it's reset in the callback chain
110
+ state = . closed
111
+
100
112
return result
101
113
}
102
114
0 commit comments