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

RTN19b #344

Merged
merged 3 commits into from
Apr 5, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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: 1 addition & 1 deletion Source/ARTProtocolMessage.m
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ - (void)setConnectionSerial:(int64_t)connectionSerial {
}

- (BOOL)ackRequired {
return self.action == ARTProtocolMessageMessage || self.action == ARTProtocolMessagePresence || self.action == ARTProtocolMessageDetach;
return self.action == ARTProtocolMessageMessage || self.action == ARTProtocolMessagePresence;
}

- (BOOL)isSyncEnabled {
Expand Down
1 change: 1 addition & 0 deletions Source/ARTRealtime+Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ ART_ASSUME_NONNULL_BEGIN
@interface ARTRealtime ()

@property (readonly, strong, nonatomic) __GENERIC(ARTEventEmitter, NSNumber *, ARTConnectionStateChange *) *eventEmitter;
@property (readonly, strong, nonatomic) __GENERIC(ARTEventEmitter, NSNull *, NSNull *) *reconnectedEventEmitter;

@end

Expand Down
2 changes: 2 additions & 0 deletions Source/ARTRealtime.m
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ - (instancetype)initWithOptions:(ARTClientOptions *)options {

_rest = [[ARTRest alloc] initWithOptions:options];
_eventEmitter = [[ARTEventEmitter alloc] init];
_reconnectedEventEmitter = [[ARTEventEmitter alloc] init];
_channels = [[ARTRealtimeChannels alloc] initWithRealtime:self];
_transport = nil;
_transportClass = [ARTWebSocketTransport class];
Expand Down Expand Up @@ -233,6 +234,7 @@ - (void)transition:(ARTRealtimeConnectionState)state withErrorInfo:(ARTErrorInfo
}];
}

[_reconnectedEventEmitter emit:[NSNull null] with:nil];
}

break;
Expand Down
43 changes: 36 additions & 7 deletions Source/ARTRealtimeChannel.m
Original file line number Diff line number Diff line change
Expand Up @@ -514,16 +514,23 @@ - (void)attach:(void (^)(ARTErrorInfo * _Nullable))callback {
return;
}

if (callback) [_attachedEventEmitter once:callback];
// Set state: Attaching
[self transition:ARTRealtimeChannelAttaching status:[ARTStatus state:ARTStateOk]];

[self attachAfterChecks:callback];
}

- (void)attachAfterChecks:(void (^)(ARTErrorInfo * _Nullable))callback {
[self cancelAttachTimer];

ARTProtocolMessage *attachMessage = [[ARTProtocolMessage alloc] init];
attachMessage.action = ARTProtocolMessageAttach;
attachMessage.channel = self.name;

__block BOOL timeouted = false;

[self.realtime send:attachMessage callback:nil];
if (callback) [_attachedEventEmitter once:callback];
// Set state: Attaching
[self transition:ARTRealtimeChannelAttaching status:[ARTStatus state:ARTStateOk]];

_attachTimer = [self.realtime startTimer:^{
timeouted = true;
Expand All @@ -533,6 +540,14 @@ - (void)attach:(void (^)(ARTErrorInfo * _Nullable))callback {
[self transition:ARTRealtimeChannelFailed status:status];
[_attachedEventEmitter emit:[NSNull null] with:errorInfo];
} interval:[ARTDefault realtimeRequestTimeout]];

ARTEventListener *reconnectedListener = [self.realtime.reconnectedEventEmitter once:^(NSNull *n) {
// Disconnected and connected while attaching, re-attach.
[self attachAfterChecks:callback];
}];
[_attachedEventEmitter once:^(ARTErrorInfo *err) {
[self.realtime.reconnectedEventEmitter off:reconnectedListener];
}];
}

- (void)detach:(void (^)(ARTErrorInfo * _Nullable))callback {
Expand Down Expand Up @@ -563,16 +578,23 @@ - (void)detach:(void (^)(ARTErrorInfo * _Nullable))callback {
return;
}

if (callback) [_detachedEventEmitter once:callback];
// Set state: Detaching
[self transition:ARTRealtimeChannelDetaching status:[ARTStatus state:ARTStateOk]];

[self detachAfterChecks:callback];
}

- (void)detachAfterChecks:(void (^)(ARTErrorInfo * _Nullable))callback {
[self cancelDetachTimer];

ARTProtocolMessage *detachMessage = [[ARTProtocolMessage alloc] init];
detachMessage.action = ARTProtocolMessageDetach;
detachMessage.channel = self.name;

__block BOOL timeouted = false;

[self.realtime send:detachMessage callback:nil];
if (callback) [_detachedEventEmitter once:callback];
// Set state: Detaching
[self transition:ARTRealtimeChannelDetaching status:[ARTStatus state:ARTStateOk]];

_detachTimer = [self.realtime startTimer:^{
timeouted = true;
Expand All @@ -583,6 +605,13 @@ - (void)detach:(void (^)(ARTErrorInfo * _Nullable))callback {
[_detachedEventEmitter emit:[NSNull null] with:errorInfo];
} interval:[ARTDefault realtimeRequestTimeout]];

ARTEventListener *reconnectedListener = [self.realtime.reconnectedEventEmitter once:^(NSNull *n) {
// Disconnected and connected while attaching, re-detach.
[self detachAfterChecks:callback];
}];
[_detachedEventEmitter once:^(ARTErrorInfo *err) {
[self.realtime.reconnectedEventEmitter off:reconnectedListener];
}];
}

- (void)detach {
Expand Down
62 changes: 62 additions & 0 deletions Spec/RealtimeClientConnection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1736,6 +1736,68 @@ class RealtimeClientConnection: QuickSpec {
}
}

// RTN19b
it("should resent the ATTACH message if there are any pending channels") {
let options = AblyTests.commonAppSetup()
options.disconnectedRetryTimeout = 0.1
let client = AblyTests.newRealtime(options)
defer { client.close() }
let channel = client.channels.get("test")
let transport = client.transport as! TestProxyTransport

expect(client.connection.state).toEventually(equal(ARTRealtimeConnectionState.Connected), timeout: testTimeout)

waitUntil(timeout: testTimeout) { done in
transport.ignoreSends = true
channel.attach() { error in
expect(error).to(beNil())
let newTransport = client.transport as! TestProxyTransport
expect(transport.protocolMessagesReceived.filter{ $0.action == .Connected }).to(haveCount(1))
expect(newTransport.protocolMessagesReceived.filter{ $0.action == .Connected }).to(haveCount(1))
expect(transport.protocolMessagesSent.filter{ $0.action == .Attach }).to(haveCount(0))
expect(transport.protocolMessagesSentIgnored.filter{ $0.action == .Attach }).to(haveCount(1))
expect(newTransport.protocolMessagesSent.filter{ $0.action == .Attach }).to(haveCount(1))
done()
}
expect(channel.state).to(equal(ARTRealtimeChannelState.Attaching))
transport.ignoreSends = false
client.onDisconnected()
}
}

// RTN19b
it("should resent the DETACH message if there are any pending channels") {
let options = AblyTests.commonAppSetup()
options.disconnectedRetryTimeout = 0.1
let client = AblyTests.newRealtime(options)
defer { client.close() }
let channel = client.channels.get("test")
let transport = client.transport as! TestProxyTransport

expect(client.connection.state).toEventually(equal(ARTRealtimeConnectionState.Connected), timeout: testTimeout)

waitUntil(timeout: testTimeout) { done in
channel.attach() { _ in done() }
}

waitUntil(timeout: testTimeout * 1000) { done in
transport.ignoreSends = true
channel.detach() { error in
expect(error).to(beNil())
let newTransport = client.transport as! TestProxyTransport
expect(transport.protocolMessagesReceived.filter{ $0.action == .Connected }).to(haveCount(1))
expect(newTransport.protocolMessagesReceived.filter{ $0.action == .Connected }).to(haveCount(1))
expect(transport.protocolMessagesSent.filter{ $0.action == .Detach }).to(haveCount(0))
expect(transport.protocolMessagesSentIgnored.filter{ $0.action == .Detach }).to(haveCount(1))
expect(newTransport.protocolMessagesSent.filter{ $0.action == .Detach }).to(haveCount(1))
done()
}
expect(channel.state).to(equal(ARTRealtimeChannelState.Detaching))
transport.ignoreSends = false
client.onDisconnected()
}
}

}

}
Expand Down