Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix SUSPENDED channel reattach #909

Merged
merged 10 commits into from
Jan 6, 2020
34 changes: 18 additions & 16 deletions Source/ARTRealtime.m
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,6 @@ @implementation ARTRealtimeInternal {
ARTScheduledBlockHandle *_idleTimer;
dispatch_queue_t _userQueue;
dispatch_queue_t _queue;

}

- (instancetype)initWithOptions:(ARTClientOptions *)options {
Expand Down Expand Up @@ -574,7 +573,9 @@ - (ARTEventListener *)transitionSideEffects:(ARTConnectionStateChange *)stateCha
if (!_transport) {
NSString *resumeKey = nil;
NSNumber *connectionSerial = nil;
if (stateChange.previous == ARTRealtimeFailed || stateChange.previous == ARTRealtimeDisconnected || stateChange.previous == ARTRealtimeSuspended) {
if (stateChange.previous == ARTRealtimeFailed ||
stateChange.previous == ARTRealtimeDisconnected ||
stateChange.previous == ARTRealtimeSuspended) {
resumeKey = self.connection.key_nosync;
connectionSerial = [NSNumber numberWithLongLong:self.connection.serial_nosync];
_resuming = true;
Expand Down Expand Up @@ -793,19 +794,20 @@ - (void)onConnected:(ARTProtocolMessage *)message {
// Resuming
if (_resuming) {
if (![message.connectionId isEqualToString:self.connection.id_nosync]) {
[self.logger warn:@"R:%p ARTRealtime: connection has reconnected, but resume failed. Reattaching any attached channels", self];
[self.logger warn:@"RT:%p connection \"%@\" has reconnected, but resume failed. Reattaching any attached channels", self, message.connectionId];
// Reattach all channels
for (ARTRealtimeChannelInternal *channel in self.channels.nosyncIterable) {
[channel reattachWithReason:message.error callback:nil];
}
_resuming = false;
}
else if (message.error) {
[self.logger warn:@"R:%p ARTRealtime: connection has resumed with non-fatal error %@", self, message.error.message];
[self.logger warn:@"RT:%p connection \"%@\" has resumed with non-fatal error %@", self, message.connectionId, message.error.message];
// The error will be emitted on `transition`
}

[self.logger debug:@"RT:%p connection \"%@\" has reconnected and resumed successfully", self, self.connection.id_nosync];
else {
[self.logger debug:@"RT:%p connection \"%@\" has reconnected and resumed successfully", self, message.connectionId];
}

for (ARTRealtimeChannelInternal *channel in self.channels.nosyncIterable) {
if (channel.presenceMap.syncInProgress) {
Expand All @@ -817,8 +819,8 @@ - (void)onConnected:(ARTProtocolMessage *)message {

switch (self.connection.state_nosync) {
case ARTRealtimeConnecting: {
// If no previous connectionId, don't reset the msgSerial
//as it may have been set by recover data (unless the recover failed)
// If there's no previous connectionId, then don't reset the msgSerial
//as it may have been set by recover data (unless the recover failed).
NSString *prevConnId = self.connection.id_nosync;
BOOL connIdChanged = prevConnId && ![message.connectionId isEqualToString:prevConnId];
BOOL recoverFailure = !prevConnId && message.error;
Expand Down Expand Up @@ -1556,35 +1558,35 @@ - (void)realtimeTransportDisconnected:(id<ARTRealtimeTransport>)transport withEr
} ART_TRY_OR_MOVE_TO_FAILED_END
}

- (void)realtimeTransportFailed:(id<ARTRealtimeTransport>)transport withError:(ARTRealtimeTransportError *)error {
- (void)realtimeTransportFailed:(id<ARTRealtimeTransport>)transport withError:(ARTRealtimeTransportError *)transportError {
ART_TRY_OR_MOVE_TO_FAILED_START(self) {
if (transport != self.transport) {
// Old connection
return;
}

[self.logger debug:__FILE__ line:__LINE__ message:@"R:%p realtime transport failed: %@", self, error];
[self.logger debug:__FILE__ line:__LINE__ message:@"R:%p realtime transport failed: %@", self, transportError];

if ([self shouldRetryWithFallback:error]) {
if ([self shouldRetryWithFallback:transportError]) {
[self.logger debug:__FILE__ line:__LINE__ message:@"R:%p host is down; can retry with fallback host", self];
if (!_fallbacks && [error.url.host isEqualToString:[ARTDefault realtimeHost]]) {
if (!_fallbacks && [transportError.url.host isEqualToString:[ARTDefault realtimeHost]]) {
[self.rest internetIsUp:^void(BOOL isUp) {
self->_fallbacks = [[ARTFallback alloc] initWithOptions:[self getClientOptions]];
(self->_fallbacks != nil) ? [self reconnectWithFallback] : [self transition:ARTRealtimeFailed withErrorInfo:[ARTErrorInfo createFromNSError:error.error]];
(self->_fallbacks != nil) ? [self reconnectWithFallback] : [self transition:ARTRealtimeFailed withErrorInfo:[ARTErrorInfo createFromNSError:transportError.error]];
}];
return;
} else if (_fallbacks && [self reconnectWithFallback]) {
return;
}
}

switch (error.type) {
switch (transportError.type) {
case ARTRealtimeTransportErrorTypeBadResponse:
case ARTRealtimeTransportErrorTypeOther:
[self transition:ARTRealtimeFailed withErrorInfo:[ARTErrorInfo createFromNSError:error.error]];
[self transition:ARTRealtimeFailed withErrorInfo:[ARTErrorInfo createFromNSError:transportError.error]];
break;
default:
[self transition:ARTRealtimeDisconnected withErrorInfo:[ARTErrorInfo createFromNSError:error.error]];
[self transition:ARTRealtimeDisconnected withErrorInfo:[ARTErrorInfo createFromNSError:transportError.error]];
}
} ART_TRY_OR_MOVE_TO_FAILED_END
}
Expand Down
Loading