Skip to content

Commit 91744c6

Browse files
committed
Reworked reconnection logic to be easier to understand and more stable
1 parent d654936 commit 91744c6

File tree

2 files changed

+58
-47
lines changed

2 files changed

+58
-47
lines changed

Source/PusherConnection.swift

Lines changed: 7 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,17 @@ public class PusherConnection {
2525
public var reconnectAttemptsMax: Int? = 6
2626
public var reconnectAttempts: Int = 0
2727
public var maxReconnectGapInSeconds: Double? = nil
28-
private var reconnectTimer: NSTimer? = nil
29-
internal var reconnectOperation: NSOperation?
28+
internal var reconnectTimer: NSTimer? = nil
3029

3130
public lazy var reachability: Reachability? = {
3231
let reachability = try? Reachability.reachabilityForInternetConnection()
3332
reachability?.whenReachable = { [unowned self] reachability in
34-
self.reconnectOperation?.cancel()
33+
self.debugLogger?("[PUSHER DEBUG] WE ARE REACHABLE AGAIN")
3534
if self.connectionState == .Disconnected {
36-
self.socket.connect()
35+
self.attemptReconnect()
3736
}
3837
}
3938
reachability?.whenUnreachable = { [unowned self] reachability in
40-
self.reconnectOperation?.cancel()
4139
print("Network unreachable")
4240
}
4341
return reachability
@@ -182,7 +180,7 @@ public class PusherConnection {
182180
/**
183181
Establish a websocket connection
184182
*/
185-
public func connect() {
183+
@objc public func connect() {
186184
if self.connectionState == .Connected {
187185
return
188186
} else {
@@ -283,13 +281,13 @@ public class PusherConnection {
283281
updateConnectionState(.Connected)
284282
self.socketId = socketId
285283

286-
// cancel any other outstanding reconnect attempts
287-
self.reconnectOperation?.cancel()
288284
self.reconnectAttempts = 0
289285
self.reconnectTimer?.invalidate()
290286

291287
for (_, channel) in self.channels.channels {
288+
print("Here's my channel \(channel.name)")
292289
if !channel.subscribed {
290+
print("And we aren't subbed")
293291
if !self.authorize(channel) {
294292
print("Unable to subscribe to channel: \(channel.name)")
295293
}
@@ -665,35 +663,14 @@ public class PusherConnection {
665663
)
666664
}
667665
}
668-
669-
/**
670-
Attempt to reconnect triggered by a disconnection
671-
*/
672-
@objc internal func attemptReconnect() {
673-
if connectionState != .Connected {
674-
if (reconnectAttemptsMax == nil || reconnectAttempts < reconnectAttemptsMax) {
675-
connect()
676-
reconnectAttempts += 1
677-
let reconnectInterval = Double(reconnectAttempts * reconnectAttempts) * 2.0
678-
let timeInterval = maxReconnectGapInSeconds != nil ? max(reconnectInterval, maxReconnectGapInSeconds!)
679-
: reconnectInterval
680-
reconnectTimer = NSTimer.scheduledTimerWithTimeInterval(
681-
timeInterval,
682-
target: self,
683-
selector: #selector(attemptReconnect),
684-
userInfo: nil,
685-
repeats: false
686-
)
687-
}
688-
}
689-
}
690666
}
691667

692668
public enum ConnectionState {
693669
case Connecting
694670
case Connected
695671
case Disconnecting
696672
case Disconnected
673+
case Reconnecting
697674
}
698675

699676
public protocol ConnectionStateChangeDelegate: class {

Source/PusherWebsocketDelegate.swift

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -30,37 +30,71 @@ extension PusherConnection: WebSocketDelegate {
3030
- parameter error: The error, if one exists, when disconnected
3131
*/
3232
public func websocketDidDisconnect(ws: WebSocket, error: NSError?) {
33-
updateConnectionState(.Disconnected)
34-
for (_, channel) in self.channels.channels {
35-
channel.subscribed = false
33+
// Handles setting channel subscriptions to unsubscribed wheter disconnection
34+
// is intentional or not
35+
if connectionState == .Disconnecting || connectionState == .Connected {
36+
for (_, channel) in self.channels.channels {
37+
channel.subscribed = false
38+
}
3639
}
3740

3841
// Handle error (if any)
3942
guard let error = error where error.code != Int(WebSocket.CloseCode.Normal.rawValue) else {
40-
return
43+
self.debugLogger?("[PUSHER DEBUG] Deliberate disconnection - skipping reconnect attempts")
44+
return updateConnectionState(.Disconnected)
4145
}
4246

4347
print("Websocket is disconnected. Error: \(error.localizedDescription)")
48+
// Attempt reconnect if possible
4449

45-
// Reconnect if possible
46-
if self.options.autoReconnect && reconnectAttempts == 0 {
47-
if let reachability = self.reachability where reachability.isReachable() {
48-
let operation = NSBlockOperation {
49-
self.socket.connect()
50-
}
50+
guard self.options.autoReconnect else {
51+
return updateConnectionState(.Disconnected)
52+
}
5153

52-
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(NSEC_PER_SEC)), dispatch_get_main_queue()) {
53-
NSOperationQueue.mainQueue().addOperation(operation)
54-
}
54+
guard reconnectAttemptsMax != nil && reconnectAttempts < reconnectAttemptsMax! else {
55+
self.debugLogger?("[PUSHER DEBUG] Max reconnect attempts reached")
56+
return updateConnectionState(.Disconnected)
57+
}
5558

56-
self.reconnectOperation?.cancel()
57-
self.reconnectOperation = operation
58-
}
59+
guard let reachability = self.reachability where reachability.isReachable() else {
60+
self.debugLogger?("[PUSHER DEBUG] Network unreachable so waiting to attempt reconnect")
61+
return updateConnectionState(.Disconnected)
62+
}
63+
64+
if connectionState != .Reconnecting {
65+
updateConnectionState(.Reconnecting)
66+
}
67+
self.debugLogger?("[PUSHER DEBUG] Network reachable so will setup reconnect attempt")
68+
69+
attemptReconnect()
70+
}
71+
72+
/**
73+
Attempt to reconnect triggered by a disconnection
74+
*/
75+
internal func attemptReconnect() {
76+
if connectionState != .Connected {
77+
if (reconnectAttemptsMax == nil || reconnectAttempts < reconnectAttemptsMax!) {
78+
let reconnectInterval = Double(reconnectAttempts * reconnectAttempts)
5979

60-
attemptReconnect()
80+
let timeInterval = maxReconnectGapInSeconds != nil ? min(reconnectInterval, maxReconnectGapInSeconds!)
81+
: reconnectInterval
82+
83+
self.debugLogger?("[PUSHER DEBUG] Waiting \(timeInterval) seconds before attempting to reconnect (attempt \(reconnectAttempts + 1) of \(reconnectAttemptsMax))")
84+
85+
reconnectTimer = NSTimer.scheduledTimerWithTimeInterval(
86+
timeInterval,
87+
target: self,
88+
selector: #selector(connect),
89+
userInfo: nil,
90+
repeats: false
91+
)
92+
reconnectAttempts += 1
93+
}
6194
}
6295
}
6396

97+
6498
public func websocketDidConnect(ws: WebSocket) {}
6599
public func websocketDidReceiveData(ws: WebSocket, data: NSData) {}
66100
}

0 commit comments

Comments
 (0)