Skip to content

Commit

Permalink
Update RTL13 for 0.9 (#549)
Browse files Browse the repository at this point in the history
* RTL13a

* RTL13b

* RTL13c

* Add ClientOptions.channelRetryTimeout

* RealtimeChannel reattach after timeout

* Fix: if the channel receives a server initiated DETACHED message and if the channel is in the ATTACHED or SUSPENDED states, then an attempt to reattach the channel should be made immediately

* Fix: move to Suspended if attach times out

* Fix: if the channel receives a server initiated DETACHED message and the channel is Attaching

* Remove test about #454 (replaced by RTL13)

* Update RTL4f
  • Loading branch information
ricardopereira authored Dec 21, 2016
1 parent 7f1309b commit a4819af
Show file tree
Hide file tree
Showing 6 changed files with 372 additions and 72 deletions.
6 changes: 6 additions & 0 deletions Source/ARTClientOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ ART_ASSUME_NONNULL_BEGIN
*/
@property (readwrite, assign, nonatomic) NSTimeInterval suspendedRetryTimeout;

/**
Represents the timeout (in seconds) to re-attach the channel automatically.
When a channel becomes SUSPENDED following a server initiated DETACHED, after this delay in milliseconds, if the channel is still SUSPENDED and the connection is CONNECTED, the client library will attempt to re-attach.
*/
@property (readwrite, assign, nonatomic) NSTimeInterval channelRetryTimeout;

/**
Timeout for opening the connection, available in the client library if supported by the transport.
*/
Expand Down
2 changes: 2 additions & 0 deletions Source/ARTClientOptions.m
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ - (instancetype)initDefaults {
_logLevel = ARTLogLevelNone;
_disconnectedRetryTimeout = 15.0; //Seconds
_suspendedRetryTimeout = 30.0; //Seconds
_channelRetryTimeout = 15.0; //Seconds
_httpOpenTimeout = 4.0; //Seconds
_httpRequestTimeout = 15.0; //Seconds
_httpMaxRetryDuration = 10.0; //Seconds
Expand Down Expand Up @@ -109,6 +110,7 @@ - (id)copyWithZone:(NSZone *)zone {
options.logHandler = self.logHandler;
options.suspendedRetryTimeout = self.suspendedRetryTimeout;
options.disconnectedRetryTimeout = self.disconnectedRetryTimeout;
options.channelRetryTimeout = self.channelRetryTimeout;
options.httpMaxRetryCount = self.httpMaxRetryCount;
options.httpMaxRetryDuration = self.httpMaxRetryDuration;
options.httpOpenTimeout = self.httpOpenTimeout;
Expand Down
100 changes: 71 additions & 29 deletions Source/ARTRealtimeChannel.m
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,10 @@ - (ARTEventListener *)timed:(ARTEventListener *)listener deadline:(NSTimeInterva
- (void)transition:(ARTRealtimeChannelState)state status:(ARTStatus *)status {
ARTChannelStateChange *stateChange = [[ARTChannelStateChange alloc] initWithCurrent:state previous:self.state reason:status.errorInfo];
self.state = state;
_errorReason = status.errorInfo;

if (status.storeErrorInfo) {
_errorReason = status.errorInfo;
}

if (state == ARTRealtimeChannelFailed) {
[_attachedEventEmitter emit:[NSNull null] with:status.errorInfo];
Expand Down Expand Up @@ -410,28 +413,34 @@ - (void)setAttached:(ARTProtocolMessage *)message {

[self sendQueuedMessages];

if (message.error) {
_errorReason = message.error;
[self transition:ARTRealtimeChannelAttached status:[ARTStatus state:ARTStateError info:message.error]];
}
else {
[self transition:ARTRealtimeChannelAttached status:[ARTStatus state:ARTStateOk]];
}
ARTStatus *status = message.error ? [ARTStatus state:ARTStateError info:message.error] : [ARTStatus state:ARTStateOk];
[self transition:ARTRealtimeChannelAttached status:status];
[_attachedEventEmitter emit:[NSNull null] with:nil];
}

- (void)setDetached:(ARTProtocolMessage *)message {
if (self.state == ARTRealtimeChannelFailed) {
return;
switch (self.state) {
case ARTRealtimeChannelAttached:
case ARTRealtimeChannelSuspended:
[self.realtime.logger debug:__FILE__ line:__LINE__ message:@"R:%p C:%p reattach initiated by DETACHED message", _realtime, self];
[self reattach:nil withReason:message.error];
return;
case ARTRealtimeChannelAttaching: {
[self.realtime.logger debug:__FILE__ line:__LINE__ message:@"R:%p C:%p reattach initiated by DETACHED message but it is currently attaching", _realtime, self];
ARTStatus *status = message.error ? [ARTStatus state:ARTStateError info:message.error] : [ARTStatus state:ARTStateOk];
status.storeErrorInfo = false;
[self setSuspended:status retryIn:0];
return;
}
case ARTRealtimeChannelFailed:
return;
default:
break;
}

self.attachSerial = nil;

ARTErrorInfo *errorInfo;
if (message.error) {
errorInfo = message.error;
} else {
errorInfo = [ARTErrorInfo createWithCode:0 message:@"channel has detached"];
}
ARTErrorInfo *errorInfo = message.error ? message.error : [ARTErrorInfo createWithCode:0 message:@"channel has detached"];
ARTStatus *reason = [ARTStatus state:ARTStateNotAttached info:errorInfo];
[self detachChannel:reason];
[_detachedEventEmitter emit:[NSNull null] with:nil];
Expand All @@ -447,9 +456,19 @@ - (void)setFailed:(ARTStatus *)error {
[self transition:ARTRealtimeChannelFailed status:error];
}

- (void)setSuspended:(ARTStatus *)error {
[self failQueuedMessages:error];
[self transition:ARTRealtimeChannelSuspended status:error];
- (void)setSuspended:(ARTStatus *)status {
[self setSuspended:status retryIn:self.realtime.options.channelRetryTimeout];
}

- (void)setSuspended:(ARTStatus *)status retryIn:(NSTimeInterval)retryTimeout {
[self failQueuedMessages:status];
[self transition:ARTRealtimeChannelSuspended status:status];
__weak __typeof(self) weakSelf = self;
[self unlessStateChangesBefore:retryTimeout do:^{
[weakSelf reattach:^(ARTErrorInfo *errorInfo) {
[weakSelf setSuspended:[ARTStatus state:ARTStateError info:errorInfo]];
} withReason:nil];
}];
}

- (void)onMessage:(ARTProtocolMessage *)message {
Expand Down Expand Up @@ -538,15 +557,15 @@ - (void)broadcastPresence:(ARTPresenceMessage *)pm {
}

- (void)onError:(ARTProtocolMessage *)msg {
[self transition:ARTRealtimeChannelFailed status:[ARTStatus state:ARTStateError info: msg.error]];
[self transition:ARTRealtimeChannelFailed status:[ARTStatus state:ARTStateError info:msg.error]];
[self failQueuedMessages:[ARTStatus state:ARTStateError info: msg.error]];
}

- (void)attach {
[self attach:nil];
}

- (void)attach:(void (^)(ARTErrorInfo * _Nullable))callback {
- (void)attach:(void (^)(ARTErrorInfo *))callback {
switch (self.state) {
case ARTRealtimeChannelAttaching:
[self.realtime.logger debug:__FILE__ line:__LINE__ message:@"R:%p C:%p already attaching", _realtime, self];
Expand All @@ -556,19 +575,42 @@ - (void)attach:(void (^)(ARTErrorInfo * _Nullable))callback {
[self.realtime.logger debug:__FILE__ line:__LINE__ message:@"R:%p C:%p already attached", _realtime, self];
if (callback) callback(nil);
return;
default:
break;
}
[self internalAttach:callback withReason:nil];
}

- (void)reattach:(void (^)(ARTErrorInfo *))callback withReason:(ARTErrorInfo *)reason {
switch (self.state) {
case ARTRealtimeChannelAttached:
case ARTRealtimeChannelSuspended:
[self.realtime.logger debug:__FILE__ line:__LINE__ message:@"R:%p C:%p attached or suspended and will reattach", _realtime, self];
break;
case ARTRealtimeChannelAttaching:
[self.realtime.logger debug:__FILE__ line:__LINE__ message:@"R:%p C:%p already attaching", _realtime, self];
if (callback) [_attachedEventEmitter once:callback];
return;
default:
break;
}
[self internalAttach:callback withReason:reason];
}

- (void)internalAttach:(void (^)(ARTErrorInfo *))callback withReason:(ARTErrorInfo *)reason {
switch (self.state) {
case ARTRealtimeChannelDetaching: {
NSString *msg = @"can't attach when in DETACHING state";
[self.realtime.logger debug:__FILE__ line:__LINE__ message:@"R:%p C:%p %@", _realtime, self, msg];
if (callback) callback([ARTErrorInfo createWithCode:90000 message:msg]);
return;
}
case ARTRealtimeChannelFailed:
_errorReason = nil;
break;
default:
break;
}


_errorReason = nil;

if (![self.realtime isActive]) {
[self.realtime.logger debug:__FILE__ line:__LINE__ message:@"R:%p C:%p can't attach when not in an active state", _realtime, self];
if (callback) callback([ARTErrorInfo createWithCode:90000 message:@"Can't attach when not in an active state"]);
Expand All @@ -577,7 +619,9 @@ - (void)attach:(void (^)(ARTErrorInfo * _Nullable))callback {

if (callback) [_attachedEventEmitter once:callback];
// Set state: Attaching
[self transition:ARTRealtimeChannelAttaching status:[ARTStatus state:ARTStateOk]];
ARTStatus *status = reason ? [ARTStatus state:ARTStateError info:reason] : [ARTStatus state:ARTStateOk];
status.storeErrorInfo = false;
[self transition:ARTRealtimeChannelAttaching status:status];

[self attachAfterChecks:callback];
}
Expand All @@ -595,8 +639,7 @@ - (void)attachAfterChecks:(void (^)(ARTErrorInfo * _Nullable))callback {
timeouted = true;
ARTErrorInfo *errorInfo = [ARTErrorInfo createWithCode:ARTStateAttachTimedOut message:@"attach timed out"];
ARTStatus *status = [ARTStatus state:ARTStateAttachTimedOut info:errorInfo];
_errorReason = errorInfo;
[self transition:ARTRealtimeChannelFailed status:status];
[self setSuspended:status];
[_attachedEventEmitter emit:[NSNull null] with:errorInfo];
}];

Expand Down Expand Up @@ -659,7 +702,6 @@ - (void)detachAfterChecks:(void (^)(ARTErrorInfo * _Nullable))callback {
timeouted = true;
ARTErrorInfo *errorInfo = [ARTErrorInfo createWithCode:ARTStateDetachTimedOut message:@"detach timed out"];
ARTStatus *status = [ARTStatus state:ARTStateDetachTimedOut info:errorInfo];
_errorReason = errorInfo;
[self transition:ARTRealtimeChannelFailed status:status];
[_detachedEventEmitter emit:[NSNull null] with:errorInfo];
}];
Expand Down
1 change: 1 addition & 0 deletions Source/ARTStatus.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ FOUNDATION_EXPORT NSString *const ARTAblyMessageNoMeansToRenewToken;
@interface ARTStatus : NSObject

@property (art_nullable, readonly, strong, nonatomic) ARTErrorInfo *errorInfo;
@property (nonatomic, assign) BOOL storeErrorInfo;
@property (nonatomic, assign) ARTState state;

+ (ARTStatus *)state:(ARTState) state;
Expand Down
2 changes: 2 additions & 0 deletions Source/ARTStatus.m
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ - (instancetype)init {
if (self) {
_state = ARTStateOk;
_errorInfo = nil;
_storeErrorInfo = false;
}
return self;
}
Expand All @@ -76,6 +77,7 @@ + (ARTStatus *)state:(ARTState)state {
+ (ARTStatus *)state:(ARTState)state info:(ARTErrorInfo *)info {
ARTStatus * s = [ARTStatus state:state];
s.errorInfo = info;
s.storeErrorInfo = true;
return s;
}

Expand Down
Loading

0 comments on commit a4819af

Please sign in to comment.