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

Update RTL2 for 0.9 #543

Merged
merged 23 commits into from
Dec 20, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
891e8de
Add Realtime Channel Suspended state
ricardopereira Nov 28, 2016
0c02837
Add ChannelStateChange type
ricardopereira Dec 13, 2016
22f1b13
Add ProtocolMessageActionToStr method
ricardopereira Nov 30, 2016
c446fd9
Update RTL2
ricardopereira Nov 28, 2016
340e821
RTL2f: pending
ricardopereira Nov 30, 2016
f41e8c8
Use ChannelStateChange on channel event emitter
ricardopereira Nov 29, 2016
b008a3f
Test suite: simulate client suspension with before suspension callback
ricardopereira Nov 29, 2016
d1ca520
Update tests using channel events
ricardopereira Nov 29, 2016
d97ee8f
Fix RTL14
ricardopereira Dec 15, 2016
a7ad1bc
Fix: Channel on suspended should transition to SUSPENDED state
ricardopereira Dec 15, 2016
f7a2db0
Remove RTN18
ricardopereira Dec 15, 2016
036a696
Fix: set Suspended on all channels when Connection moves to Suspended
ricardopereira Dec 16, 2016
aa34dc0
RTL2g
ricardopereira Dec 16, 2016
76a7991
Fix RTL12
ricardopereira Dec 16, 2016
5cade96
Fix RTL3d
ricardopereira Dec 16, 2016
6389d25
Fix: channel should reattach when connection is Connected
ricardopereira Dec 16, 2016
e8fefcd
Fix: should resume connection when the connection is Suspended
ricardopereira Dec 16, 2016
fad4c16
Fix RTN11
ricardopereira Dec 16, 2016
06edc0c
Fix RTL3e
ricardopereira Dec 16, 2016
cd75e9e
Fix RTC8a1
ricardopereira Dec 16, 2016
e1ab41d
Remove testSuspendingDetachesChannel
ricardopereira Dec 19, 2016
7c7c84e
Fix RTL3d
ricardopereira Dec 19, 2016
3e77e18
Fix: channel is SUSPENDED then operation will result in an error
ricardopereira Dec 19, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Source/ARTProtocolMessage+Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
// Copyright (c) 2014 Ably. All rights reserved.
//

NSString *__art_nonnull ARTProtocolMessageActionToStr(ARTProtocolMessageAction action);

ART_ASSUME_NONNULL_BEGIN

@interface ARTProtocolMessage ()
Expand Down
2 changes: 2 additions & 0 deletions Source/ARTProtocolMessage.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ typedef NS_ENUM(NSUInteger, ARTProtocolMessageAction) {
ARTProtocolMessageAuth = 17,
};

NSString *__art_nonnull ARTProtocolMessageActionToStr(ARTProtocolMessageAction action);

ART_ASSUME_NONNULL_BEGIN

/**
Expand Down
41 changes: 41 additions & 0 deletions Source/ARTProtocolMessage.m
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,44 @@ - (ARTConnectionDetails *)getConnectionDetails {
}

@end

NSString* ARTProtocolMessageActionToStr(ARTProtocolMessageAction action) {
switch(action) {
case ARTProtocolMessageHeartbeat:
return @"Heartbeat"; //0
case ARTProtocolMessageAck:
return @"Ack"; //1
case ARTProtocolMessageNack:
return @"Nack"; //2
case ARTProtocolMessageConnect:
return @"Connect"; //3
case ARTProtocolMessageConnected:
return @"Connected"; //4
case ARTProtocolMessageDisconnect:
return @"Disconnect"; //5
case ARTProtocolMessageDisconnected:
return @"Disconnected"; //6
case ARTProtocolMessageClose:
return @"Close"; //7
case ARTProtocolMessageClosed:
return @"Closed"; //8
case ARTProtocolMessageError:
return @"Error"; //9
case ARTProtocolMessageAttach:
return @"Attach"; //10
case ARTProtocolMessageAttached:
return @"Attached"; //11
case ARTProtocolMessageDetach:
return @"Detach"; //12
case ARTProtocolMessageDetached:
return @"Detached"; //13
case ARTProtocolMessagePresence:
return @"Presence"; //14
case ARTProtocolMessageMessage:
return @"Message"; //15
case ARTProtocolMessageSync:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it not worth adding Auth here now so that we don't forget, or at least a TODO?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

return @"Sync"; //16
case ARTProtocolMessageAuth:
return @"Auth"; //17
}
}
3 changes: 1 addition & 2 deletions Source/ARTRealtime+Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ ART_ASSUME_NONNULL_BEGIN
@property (readonly, strong, nonatomic) __GENERIC(ARTEventEmitter, NSNumber *, ARTConnectionStateChange *) *internalEventEmitter;
@property (readonly, strong, nonatomic) __GENERIC(ARTEventEmitter, NSNull *, NSNull *) *connectedEventEmitter;

+ (NSString *)protocolStr:(ARTProtocolMessageAction)action;

// State properties
- (BOOL)shouldSendEvents;
- (BOOL)shouldQueueEvents;
Expand All @@ -48,6 +46,7 @@ ART_ASSUME_NONNULL_BEGIN
@property (readonly, getter=getTransport, art_nullable) id<ARTRealtimeTransport> transport;
@property (readonly, strong, nonatomic, art_nonnull) id<ARTReachability> reachability;
@property (readonly, getter=getLogger) ARTLog *logger;
@property (nonatomic) NSTimeInterval connectionStateTtl;

/// Current protocol `msgSerial`. Starts at zero.
@property (readwrite, assign, nonatomic) int64_t msgSerial;
Expand Down
91 changes: 29 additions & 62 deletions Source/ARTRealtime.m
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ @implementation ARTRealtime {
BOOL _renewingToken;
__GENERIC(ARTEventEmitter, NSNull *, ARTErrorInfo *) *_pingEventEmitter;
NSDate *_startedReconnection;
NSTimeInterval _connectionStateTtl;
Class _transportClass;
Class _reachabilityClass;
id<ARTRealtimeTransport> _transport;
Expand Down Expand Up @@ -312,7 +311,7 @@ - (void)transitionSideEffects:(ARTConnectionStateChange *)stateChange usingEvent
if (!_transport) {
NSString *resumeKey = nil;
NSNumber *connectionSerial = nil;
if (stateChange.previous == ARTRealtimeFailed || stateChange.previous == ARTRealtimeDisconnected) {
if (stateChange.previous == ARTRealtimeFailed || stateChange.previous == ARTRealtimeDisconnected || stateChange.previous == ARTRealtimeSuspended) {
resumeKey = self.connection.key;
connectionSerial = [NSNumber numberWithLongLong:self.connection.serial];
_resuming = true;
Expand Down Expand Up @@ -432,6 +431,12 @@ - (void)transitionSideEffects:(ARTConnectionStateChange *)stateChange usingEvent

if ([self shouldSendEvents]) {
[self sendQueuedMessages];
// For every Channel
for (ARTRealtimeChannel* channel in self.channels) {
if (channel.state == ARTRealtimeChannelSuspended) {
[channel attach];
}
}
} else if (![self shouldQueueEvents]) {
[self failQueuedMessages:status];
ARTStatus *channelStatus = status;
Expand All @@ -440,22 +445,27 @@ - (void)transitionSideEffects:(ARTConnectionStateChange *)stateChange usingEvent
}
// For every Channel
for (ARTRealtimeChannel* channel in self.channels) {
if (channel.state == ARTRealtimeChannelInitialized || channel.state == ARTRealtimeChannelAttaching || channel.state == ARTRealtimeChannelAttached || channel.state == ARTRealtimeChannelFailed) {
if(stateChange.current == ARTRealtimeClosing) {
//do nothing. Closed state is coming.
}
else if(stateChange.current == ARTRealtimeClosed) {
[channel detachChannel:[ARTStatus state:ARTStateOk]];
}
else if(stateChange.current == ARTRealtimeSuspended) {
[channel detachChannel:channelStatus];
}
else {
[channel setFailed:channelStatus];
}
}
else {
[channel setSuspended:channelStatus];
switch (channel.state) {
case ARTRealtimeChannelInitialized:
case ARTRealtimeChannelAttaching:
case ARTRealtimeChannelAttached:
case ARTRealtimeChannelFailed:
if (stateChange.current == ARTRealtimeClosing) {
//do nothing. Closed state is coming.
}
else if (stateChange.current == ARTRealtimeClosed) {
[channel detachChannel:[ARTStatus state:ARTStateOk]];
}
else if (stateChange.current == ARTRealtimeSuspended) {
[channel setSuspended:channelStatus];
}
else {
[channel setFailed:channelStatus];
}
break;
default:
[channel setSuspended:channelStatus];
break;
}
}
}
Expand Down Expand Up @@ -942,49 +952,6 @@ - (void)setReachabilityClass:(Class)reachabilityClass {
_reachabilityClass = reachabilityClass;
}

+ (NSString *)protocolStr:(ARTProtocolMessageAction) action {
switch(action) {
case ARTProtocolMessageHeartbeat:
return @"Heartbeat"; //0
case ARTProtocolMessageAck:
return @"Ack"; //1
case ARTProtocolMessageNack:
return @"Nack"; //2
case ARTProtocolMessageConnect:
return @"Connect"; //3
case ARTProtocolMessageConnected:
return @"Connected"; //4
case ARTProtocolMessageDisconnect:
return @"Disconnect"; //5
case ARTProtocolMessageDisconnected:
return @"Disconnected"; //6
case ARTProtocolMessageClose:
return @"Close"; //7
case ARTProtocolMessageClosed:
return @"Closed"; //8
case ARTProtocolMessageError:
return @"Error"; //9
case ARTProtocolMessageAttach:
return @"Attach"; //10
case ARTProtocolMessageAttached:
return @"Attached"; //11
case ARTProtocolMessageDetach:
return @"Detach"; //12
case ARTProtocolMessageDetached:
return @"Detached"; //13
case ARTProtocolMessagePresence:
return @"Presence"; //14
case ARTProtocolMessageMessage:
return @"Message"; //15
case ARTProtocolMessageSync:
return @"Sync"; //16
case ARTProtocolMessageAuth:
return @"Auth"; //17
default:
return [NSString stringWithFormat: @"unknown protocol state %d", (int)action];
}
}

#pragma mark - ARTRealtimeTransportDelegate implementation

- (void)realtimeTransport:(id)transport didReceiveMessage:(ARTProtocolMessage *)message {
Expand All @@ -993,7 +960,7 @@ - (void)realtimeTransport:(id)transport didReceiveMessage:(ARTProtocolMessage *)
return;
}

[self.logger verbose:@"R:%p ARTRealtime didReceive Protocol Message %@ ", self, [ARTRealtime protocolStr:message.action]];
[self.logger verbose:@"R:%p ARTRealtime didReceive Protocol Message %@ ", self, ARTProtocolMessageActionToStr(message.action)];

if (message.error) {
[self.logger verbose:@"R:%p ARTRealtime Protocol Message with error %@ ", self, message.error];
Expand Down
2 changes: 1 addition & 1 deletion Source/ARTRealtimeChannel+Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ ART_ASSUME_NONNULL_BEGIN
@property (readwrite, strong, nonatomic) NSMutableArray *queuedMessages;
@property (readwrite, strong, nonatomic, art_nullable) NSString *attachSerial;
@property (readonly, getter=getClientId) NSString *clientId;
@property (readonly, strong, nonatomic) __GENERIC(ARTEventEmitter, NSNumber *, ARTErrorInfo *) *statesEventEmitter;
@property (readonly, strong, nonatomic) __GENERIC(ARTEventEmitter, NSNumber *, ARTChannelStateChange *) *statesEventEmitter;
@property (readonly, strong, nonatomic) __GENERIC(ARTEventEmitter, NSString *, ARTMessage *) *messagesEventEmitter;
@property (readonly, strong, nonatomic) __GENERIC(ARTEventEmitter, NSNumber *, ARTPresenceMessage *) *presenceEventEmitter;
@property (readwrite, strong, nonatomic) ARTPresenceMap *presenceMap;
Expand Down
2 changes: 1 addition & 1 deletion Source/ARTRealtimeChannel.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ ART_ASSUME_NONNULL_BEGIN

- (BOOL)history:(ARTRealtimeHistoryQuery *__art_nullable)query callback:(void(^)(__GENERIC(ARTPaginatedResult, ARTMessage *) *__art_nullable result, ARTErrorInfo *__art_nullable error))callback error:(NSError *__art_nullable *__art_nullable)errorPtr;

ART_EMBED_INTERFACE_EVENT_EMITTER(ARTChannelEvent, ARTErrorInfo *)
ART_EMBED_INTERFACE_EVENT_EMITTER(ARTChannelEvent, ARTChannelStateChange *)

@end

Expand Down
27 changes: 14 additions & 13 deletions Source/ARTRealtimeChannel.m
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ - (void)publishProtocolMessage:(ARTProtocolMessage *)pm callback:(void (^)(ARTSt
[self addToQueue:pm callback:cb];
break;
}
case ARTRealtimeChannelSuspended:
case ARTRealtimeChannelDetaching:
case ARTRealtimeChannelDetached:
case ARTRealtimeChannelFailed:
Expand All @@ -180,8 +181,6 @@ - (void)publishProtocolMessage:(ARTProtocolMessage *)pm callback:(void (^)(ARTSt
}
break;
}
default:
NSAssert(NO, @"Invalid State");
}
}

Expand Down Expand Up @@ -272,19 +271,19 @@ - (void)unsubscribe:(NSString *)name listener:(ARTEventListener<ARTMessage *> *)
[self.messagesEventEmitter off:name listener:listener];
}

- (__GENERIC(ARTEventListener, ARTErrorInfo *) *)on:(ARTChannelEvent)event callback:(void (^)(ARTErrorInfo *))cb {
- (__GENERIC(ARTEventListener, ARTChannelStateChange *) *)on:(ARTChannelEvent)event callback:(void (^)(ARTChannelStateChange *))cb {
return [self.statesEventEmitter on:[NSNumber numberWithInt:event] callback:cb];
}

- (__GENERIC(ARTEventListener, ARTErrorInfo *) *)on:(void (^)(ARTErrorInfo *))cb {
- (__GENERIC(ARTEventListener, ARTChannelStateChange *) *)on:(void (^)(ARTChannelStateChange *))cb {
return [self.statesEventEmitter on:cb];
}

- (__GENERIC(ARTEventListener, ARTErrorInfo *) *)once:(ARTChannelEvent)event callback:(void (^)(ARTErrorInfo *))cb {
- (__GENERIC(ARTEventListener, ARTChannelStateChange *) *)once:(ARTChannelEvent)event callback:(void (^)(ARTChannelStateChange *))cb {
return [self.statesEventEmitter once:[NSNumber numberWithInt:event] callback:cb];
}

- (__GENERIC(ARTEventListener, ARTErrorInfo *) *)once:(void (^)(ARTErrorInfo *))cb {
- (__GENERIC(ARTEventListener, ARTChannelStateChange *) *)once:(void (^)(ARTChannelStateChange *))cb {
return [self.statesEventEmitter once:cb];
}

Expand All @@ -295,11 +294,11 @@ - (void)off:(ARTChannelEvent)event listener:listener {
[self.statesEventEmitter off:[NSNumber numberWithInt:event] listener:listener];
}

- (void)off:(__GENERIC(ARTEventListener, ARTErrorInfo *) *)listener {
- (void)off:(__GENERIC(ARTEventListener, ARTChannelStateChange *) *)listener {
[self.statesEventEmitter off:listener];
}

- (void)emit:(ARTChannelEvent)event with:(ARTErrorInfo *)data {
- (void)emit:(ARTChannelEvent)event with:(ARTChannelStateChange *)data {
[self.statesEventEmitter emit:[NSNumber numberWithInt:event] with:data];
}

Expand All @@ -308,6 +307,7 @@ - (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;

Expand All @@ -321,7 +321,7 @@ - (void)transition:(ARTRealtimeChannelState)state status:(ARTStatus *)status {
[_attachedEventEmitter emit:[NSNull null] with:[ARTErrorInfo createWithCode:90000 message:msg]];
}

[self emit:(ARTChannelEvent)state with:status.errorInfo];
[self emit:(ARTChannelEvent)stateChange.current with:stateChange];
}

- (void)dealloc {
Expand All @@ -339,7 +339,8 @@ - (void)unlessStateChangesBefore:(NSTimeInterval)deadline do:(void(^)())callback
// Already changed; do nothing.
return;
}
[self timed:[self once:^(ARTErrorInfo *errorInfo) {
// FIXME: should not use the global listener for internal purpose
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you raise an issue for this so it's not forgotten?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done #555.

[self timed:[self once:^(ARTChannelStateChange *stateChange) {
// Any state change cancels the timeout.
}] deadline:deadline onTimeout:callback];
});
Expand Down Expand Up @@ -397,8 +398,8 @@ - (void)setAttached:(ARTProtocolMessage *)message {
if (self.state == ARTRealtimeChannelAttached) {
if (message.error != nil) {
_errorReason = message.error;
[self emit:ARTChannelEventUpdate with:message.error];
}
[self emit:ARTChannelEventUpdate with:[[ARTChannelStateChange alloc] initWithCurrent:self.state previous:self.state reason:message.error]];
return;
}

Expand Down Expand Up @@ -448,7 +449,7 @@ - (void)setFailed:(ARTStatus *)error {

- (void)setSuspended:(ARTStatus *)error {
[self failQueuedMessages:error];
[self transition:ARTRealtimeChannelDetached status:error];
[self transition:ARTRealtimeChannelSuspended status:error];
}

- (void)onMessage:(ARTProtocolMessage *)message {
Expand All @@ -463,7 +464,7 @@ - (void)onMessage:(ARTProtocolMessage *)message {
ARTErrorInfo *errorInfo = [ARTErrorInfo wrap:(ARTErrorInfo *)error.userInfo[NSLocalizedFailureReasonErrorKey] prepend:@"Failed to decode data: "];
[self.logger error:@"R:%p C:%p %@", _realtime, self, errorInfo.message];
_errorReason = errorInfo;
[self emit:ARTChannelEventUpdate with:errorInfo];
[self emit:ARTChannelEventUpdate with:[[ARTChannelStateChange alloc] initWithCurrent:self.state previous:self.state reason:errorInfo]];
}
}

Expand Down
25 changes: 25 additions & 0 deletions Source/ARTTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ typedef NS_ENUM(NSUInteger, ARTRealtimeChannelState) {
ARTRealtimeChannelAttached,
ARTRealtimeChannelDetaching,
ARTRealtimeChannelDetached,
ARTRealtimeChannelSuspended,
ARTRealtimeChannelFailed
};

Expand All @@ -90,12 +91,14 @@ typedef NS_ENUM(NSUInteger, ARTChannelEvent) {
ARTChannelEventAttached,
ARTChannelEventDetaching,
ARTChannelEventDetached,
ARTChannelEventSuspended,
ARTChannelEventFailed,
ARTChannelEventUpdate
};

NSString *__art_nonnull ARTChannelEventToStr(ARTChannelEvent event);


typedef NS_ENUM(NSInteger, ARTDataQueryError) {
ARTDataQueryErrorLimit = 1,
ARTDataQueryErrorTimestampRange = 2,
Expand Down Expand Up @@ -144,6 +147,28 @@ NSString *generateNonce();

@end

#pragma mark - ARTChannelStateChange

@interface ARTChannelStateChange : NSObject

- (instancetype)initWithCurrent:(ARTRealtimeChannelState)current
previous:(ARTRealtimeChannelState)previous
reason:(ARTErrorInfo *__art_nullable)reason;

- (instancetype)initWithCurrent:(ARTRealtimeChannelState)current
previous:(ARTRealtimeChannelState)previous
reason:(ARTErrorInfo *__art_nullable)reason
resumed:(BOOL)resumed;

@property (readonly, nonatomic) ARTRealtimeChannelState current;
@property (readonly, nonatomic) ARTRealtimeChannelState previous;
@property (readonly, nonatomic, art_nullable) ARTErrorInfo *reason;
@property (readonly, nonatomic) BOOL resumed;

@end

#pragma mark - ARTJsonCompatible

@protocol ARTJsonCompatible <NSObject>
- (NSDictionary *__art_nullable)toJSON:(NSError *__art_nullable *__art_nullable)error;
@end
Expand Down
Loading