From 675f294a4303205a476907dd6fcd276f1f8c44a8 Mon Sep 17 00:00:00 2001 From: Marat Al Date: Sun, 30 Jun 2024 00:00:46 +0200 Subject: [PATCH 1/7] Replaced irrelevant RTL4i attach with re-attach instead (moved reattach from `onConnected`). --- Source/ARTRealtime.m | 19 ++++--------- Test/Tests/RealtimeClientChannelTests.swift | 31 +++++++++------------ 2 files changed, 18 insertions(+), 32 deletions(-) diff --git a/Source/ARTRealtime.m b/Source/ARTRealtime.m index 9623df981..438664b69 100644 --- a/Source/ARTRealtime.m +++ b/Source/ARTRealtime.m @@ -744,16 +744,13 @@ - (void)performTransitionToState:(ARTRealtimeConnectionState)state withParams:(A if ([self shouldSendEvents]) { [self sendQueuedMessages]; - // Channels for (ARTRealtimeChannelInternal *channel in channels) { - if (stateChange.previous == ARTRealtimeInitialized || - stateChange.previous == ARTRealtimeConnecting || - stateChange.previous == ARTRealtimeDisconnected) { - // RTL4i - [channel _attach:nil]; - } + // Reattach channel regardless resume success - RTN15c6, RTN15c7 + ARTAttachRequestParams *const params = [[ARTAttachRequestParams alloc] initWithReason:stateChange.reason]; + [channel reattachWithParams:params]; } - } else if (![self shouldQueueEvents]) { + } + else if (![self shouldQueueEvents]) { if (!channelStateChangeParams) { if (stateChange.reason) { channelStateChangeParams = [[ARTChannelStateChangeParams alloc] initWithState:ARTStateError @@ -867,12 +864,6 @@ - (void)onConnected:(ARTProtocolMessage *)message { else { ARTLogWarn(self.logger, @"RT:%p connection \"%@\" has reconnected, but resume failed. Error: \"%@\"", self, message.connectionId, message.error.message); } - // Reattach all channels regardless resume success - RTN15c6, RTN15c7 - for (ARTRealtimeChannelInternal *channel in self.channels.nosyncIterable) { - ARTAttachRequestParams *const params = [[ARTAttachRequestParams alloc] initWithReason:message.error]; - [channel reattachWithParams:params]; - } - _resuming = false; } // 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). diff --git a/Test/Tests/RealtimeClientChannelTests.swift b/Test/Tests/RealtimeClientChannelTests.swift index d5bcec602..dc6af1908 100644 --- a/Test/Tests/RealtimeClientChannelTests.swift +++ b/Test/Tests/RealtimeClientChannelTests.swift @@ -563,6 +563,7 @@ class RealtimeClientChannelTests: XCTestCase { XCTAssertFalse(stateChange.resumed) } } + channel.attach() channel.publish(nil, data: "A message") } @@ -583,6 +584,7 @@ class RealtimeClientChannelTests: XCTestCase { XCTAssertFalse(stateChange.resumed) } } + recoveredChannel.attach() } } @@ -712,7 +714,6 @@ class RealtimeClientChannelTests: XCTestCase { done() } } - expect(channel.state).toEventually(equal(.attached), timeout: testTimeout) } // TO3g and https://github.com/ably/ably-cocoa/issues/1004 @@ -727,14 +728,13 @@ class RealtimeClientChannelTests: XCTestCase { defer { client.dispose(); client.close() } client.internal.setReachabilityClass(TestReachability.self) let channel = client.channels.get(test.uniqueChannelName()) - - waitUntil(timeout: testTimeout) { done in - client.connection.once(.connected) { _ in - done() - } - client.connect() - } - + + client.connect() + expect(client.connection.state).toEventually(equal(.connected), timeout: testTimeout) + + channel.attach() + expect(channel.state).toEventually(equal(.attached), timeout: testTimeout) + waitUntil(timeout: testTimeout) { done in channel.publish(nil, data: "message") { error in XCTAssertNil(error) @@ -742,13 +742,6 @@ class RealtimeClientChannelTests: XCTestCase { } } - XCTAssertEqual(channel.state, .attached) - channel.on { stateChange in - if stateChange.current != .attached { - fail("Channel state should not change") - } - } - waitUntil(timeout: testTimeout) { done in client.connection.once(.disconnected) { stateChange in expect(stateChange.reason?.message).to(satisfyAnyOf(contain("unreachable host"), contain("network is down"))) @@ -766,7 +759,7 @@ class RealtimeClientChannelTests: XCTestCase { } channel.off() - XCTAssertEqual(channel.state, .attached) + expect(channel.state).toEventually(equal(ARTRealtimeChannelState.attached), timeout: testTimeout) } // RTL3b @@ -1216,8 +1209,8 @@ class RealtimeClientChannelTests: XCTestCase { XCTAssertNil(stateChange.reason) done() } - client.connect() + channel.attach() } XCTAssertEqual(channel.state, .attached) } @@ -2868,6 +2861,7 @@ class RealtimeClientChannelTests: XCTestCase { XCTAssertNil(stateChange.reason) done() } + channel.attach() } let expectationEvent0 = XCTestExpectation(description: "event0") @@ -4614,6 +4608,7 @@ class RealtimeClientChannelTests: XCTestCase { partialDone() } } + channel.attach() } waitUntil(timeout: testTimeout) { done in From 16b3806424a26149fdf18c0a0489a12763741c3a Mon Sep 17 00:00:00 2001 From: Marat Al Date: Sun, 30 Jun 2024 01:08:31 +0200 Subject: [PATCH 2/7] Only queue publish and presence messages (TO3g, see also https://github.com/ably/specification/pull/194). --- Source/ARTRealtime.m | 36 ++++++++++++------- .../Tests/RealtimeClientConnectionTests.swift | 10 ++++-- Test/Tests/RealtimeClientPresenceTests.swift | 20 +++++------ Test/Tests/RestClientChannelTests.swift | 4 +++ 4 files changed, 45 insertions(+), 25 deletions(-) diff --git a/Source/ARTRealtime.m b/Source/ARTRealtime.m index 438664b69..442534eac 100644 --- a/Source/ARTRealtime.m +++ b/Source/ARTRealtime.m @@ -1275,22 +1275,34 @@ - (void)send:(ARTProtocolMessage *)msg reuseMsgSerial:(BOOL)reuseMsgSerial sentC if ([self shouldSendEvents]) { [self sendImpl:msg reuseMsgSerial:reuseMsgSerial sentCallback:sentCallback ackCallback:ackCallback]; } - else if ([self shouldQueueEvents]) { - ARTQueuedMessage *lastQueuedMessage = self.queuedMessages.lastObject; //RTL6d5 - BOOL merged = [lastQueuedMessage mergeFrom:msg sentCallback:nil ackCallback:ackCallback]; - if (!merged) { - ARTQueuedMessage *qm = [[ARTQueuedMessage alloc] initWithProtocolMessage:msg sentCallback:sentCallback ackCallback:ackCallback]; - [self.queuedMessages addObject:qm]; - ARTLogDebug(self.logger, @"RT:%p (channel: %@) protocol message with action '%lu - %@' has been queued (%@)", self, msg.channel, (unsigned long)msg.action, ARTProtocolMessageActionToStr(msg.action), msg.messages); + // see RTL6c2, RTN19, RTN7 and TO3g + else if (msg.ackRequired) { + if ([self shouldQueueEvents]) { + ARTQueuedMessage *lastQueuedMessage = self.queuedMessages.lastObject; //RTL6d5 + BOOL merged = [lastQueuedMessage mergeFrom:msg sentCallback:nil ackCallback:ackCallback]; + if (!merged) { + ARTQueuedMessage *qm = [[ARTQueuedMessage alloc] initWithProtocolMessage:msg sentCallback:sentCallback ackCallback:ackCallback]; + [self.queuedMessages addObject:qm]; + ARTLogDebug(self.logger, @"RT:%p (channel: %@) protocol message with action '%lu - %@' has been queued (%@)", self, msg.channel, (unsigned long)msg.action, ARTProtocolMessageActionToStr(msg.action), msg.messages); + } + else { + ARTLogVerbose(self.logger, @"RT:%p (channel: %@) message %@ has been bundled to %@", self, msg.channel, msg, lastQueuedMessage.msg); + } } + // RTL6c4 else { - ARTLogVerbose(self.logger, @"RT:%p (channel: %@) message %@ has been bundled to %@", self, msg.channel, msg, lastQueuedMessage.msg); + ARTErrorInfo *error = self.connection.error_nosync; + ARTLogDebug(self.logger, @"RT:%p (channel: %@) protocol message with action '%lu - %@' can't be sent or queued: %@", self, msg.channel, (unsigned long)msg.action, ARTProtocolMessageActionToStr(msg.action), error); + if (sentCallback) { + sentCallback(error); + } + if (ackCallback) { + ackCallback([ARTStatus state:ARTStateError info:error]); + } } } - else if (ackCallback) { - ARTErrorInfo *error = self.connection.errorReason_nosync; - if (!error) error = [ARTErrorInfo createWithCode:ARTErrorChannelOperationFailed status:400 message:[NSString stringWithFormat:@"not possile to send message (state is %@)", ARTRealtimeConnectionStateToStr(self.connection.state_nosync)]]; - ackCallback([ARTStatus state:ARTStateError info:error]); + else { + ARTLogDebug(self.logger, @"RT:%p (channel: %@) sending protocol message with action '%lu - %@' was ignored: %@", self, msg.channel, (unsigned long)msg.action, ARTProtocolMessageActionToStr(msg.action), self.connection.error_nosync); } } diff --git a/Test/Tests/RealtimeClientConnectionTests.swift b/Test/Tests/RealtimeClientConnectionTests.swift index ce8138324..d15b9269a 100644 --- a/Test/Tests/RealtimeClientConnectionTests.swift +++ b/Test/Tests/RealtimeClientConnectionTests.swift @@ -2565,7 +2565,8 @@ class RealtimeClientConnectionTests: XCTestCase { let client = AblyTests.newRealtime(options).client defer { client.dispose(); client.close() } let channel = client.channels.get(test.uniqueChannelName()) - + channel.attach() + XCTAssertTrue(client.waitUntilConnected()) let expectedConnectionId = client.connection.id @@ -2601,7 +2602,9 @@ class RealtimeClientConnectionTests: XCTestCase { defer { client.dispose(); client.close() } let channel1 = client.channels.get(test.uniqueChannelName()) let channel2 = client.channels.get(test.uniqueChannelName(prefix: "second_")) - + channel1.attach() + channel2.attach() + XCTAssertTrue(client.waitUntilConnected()) expect(channel1.state).toEventually(equal(ARTRealtimeChannelState.attached), timeout: testTimeout) expect(channel2.state).toEventually(equal(ARTRealtimeChannelState.attached), timeout: testTimeout) @@ -2642,7 +2645,8 @@ class RealtimeClientConnectionTests: XCTestCase { let client = AblyTests.newRealtime(options).client defer { client.dispose(); client.close() } let channel = client.channels.get(test.uniqueChannelName()) - + channel.attach() + XCTAssertTrue(client.waitUntilConnected()) let expectedConnectionId = client.connection.id diff --git a/Test/Tests/RealtimeClientPresenceTests.swift b/Test/Tests/RealtimeClientPresenceTests.swift index 4fd7c401e..166616345 100644 --- a/Test/Tests/RealtimeClientPresenceTests.swift +++ b/Test/Tests/RealtimeClientPresenceTests.swift @@ -647,12 +647,6 @@ class RealtimeClientPresenceTests: XCTestCase { waitUntil(timeout: testTimeout) { done in let partialDone = AblyTests.splitDone(2, done: done) - channel2.presence.enterClient("Client 2", data: nil) { error in - XCTAssertNil(error) - XCTAssertEqual(client2.internal.queuedMessages.count, 0) - XCTAssertEqual(channel2.state, ARTRealtimeChannelState.attached) - partialDone() - } channel2.presence.subscribe(.enter) { _ in if channel2.presence.syncComplete { XCTAssertEqual(channel2.internal.presence.members.count, 2) @@ -662,8 +656,13 @@ class RealtimeClientPresenceTests: XCTestCase { channel2.presence.unsubscribe() partialDone() } - - XCTAssertEqual(client2.internal.queuedMessages.count, 1) + channel2.presence.enterClient("Client 2", data: nil) { error in + XCTAssertNil(error) + XCTAssertEqual(client2.internal.queuedMessages.count, 0) + XCTAssertEqual(channel2.state, ARTRealtimeChannelState.attached) + partialDone() + } + XCTAssertEqual(channel2.internal.presence.pendingPresence.count, 1) XCTAssertFalse(channel2.presence.syncComplete) XCTAssertEqual(channel2.internal.presence.members.count, 0) } @@ -2997,7 +2996,7 @@ class RealtimeClientPresenceTests: XCTestCase { done() } XCTAssertEqual(client.connection.state, ARTRealtimeConnectionState.connecting) - XCTAssertEqual(client.internal.queuedMessages.count, 1) + XCTAssertEqual(channel.internal.presence.pendingPresence.count, 1) } } @@ -3071,7 +3070,7 @@ class RealtimeClientPresenceTests: XCTestCase { waitUntil(timeout: testTimeout) { done in channel.presence.enterClient("user", data: nil) { error in - XCTAssertEqual(error?.code, ARTErrorCode.invalidTransportHandle.intValue) + XCTAssertEqual(error?.code, ARTErrorCode.unableToEnterPresenceChannelInvalidState.intValue) XCTAssertEqual(channel.presence.internal.pendingPresence.count, 0) done() } @@ -3355,6 +3354,7 @@ class RealtimeClientPresenceTests: XCTestCase { expect(client.connection.state).toEventually(equal(.closed), timeout: testTimeout) } let channel = client.channels.get(channelName) + channel.attach() expect(channel.internal.presence.syncInProgress).toEventually(beTrue(), timeout: testTimeout) waitUntil(timeout: testTimeout) { done in diff --git a/Test/Tests/RestClientChannelTests.swift b/Test/Tests/RestClientChannelTests.swift index 77229d742..2afd1fd4b 100644 --- a/Test/Tests/RestClientChannelTests.swift +++ b/Test/Tests/RestClientChannelTests.swift @@ -391,6 +391,7 @@ class RestClientChannelTests: XCTestCase { let chanelName = test.uniqueChannelName(prefix: "ch1") let subscriber = realtime.channels.get(chanelName) + subscriber.attach() waitUntil(timeout: testTimeout) { done in subscriber.once(.attached) { _ in done() @@ -423,6 +424,7 @@ class RestClientChannelTests: XCTestCase { let chanelName = test.uniqueChannelName(prefix: "ch1") let subscriber = realtime.channels.get(chanelName) + subscriber.attach() waitUntil(timeout: testTimeout) { done in subscriber.once(.attached) { _ in done() @@ -453,6 +455,7 @@ class RestClientChannelTests: XCTestCase { let chanelName = test.uniqueChannelName(prefix: "ch1") let subscriber = realtime.channels.get(chanelName) + subscriber.attach() waitUntil(timeout: testTimeout) { done in subscriber.once(.attached) { _ in done() @@ -484,6 +487,7 @@ class RestClientChannelTests: XCTestCase { let chanelName = test.uniqueChannelName(prefix: "ch1") let subscriber = realtime.channels.get(chanelName) + subscriber.attach() waitUntil(timeout: testTimeout) { done in subscriber.once(.attached) { _ in done() From 305d8db396ad8a49f2eb7905acc6349f2949dd1d Mon Sep 17 00:00:00 2001 From: Marat Al Date: Sun, 30 Jun 2024 13:51:48 +0200 Subject: [PATCH 3/7] Sending queued messages should be after reattach. See https://test-observability.herokuapp.com/repos/ably/ably-cocoa/uploads/e4821695-20e2-4d6a-8460-e00b30c9f14f vs https://test-observability.herokuapp.com/repos/ably/ably-cocoa/uploads/7c96655e-6c53-453a-a432-2f9d4bf5e989 --- Source/ARTRealtime.m | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Source/ARTRealtime.m b/Source/ARTRealtime.m index 442534eac..9bd3f3529 100644 --- a/Source/ARTRealtime.m +++ b/Source/ARTRealtime.m @@ -742,13 +742,12 @@ - (void)performTransitionToState:(ARTRealtimeConnectionState)state withParams:(A } if ([self shouldSendEvents]) { - [self sendQueuedMessages]; - for (ARTRealtimeChannelInternal *channel in channels) { // Reattach channel regardless resume success - RTN15c6, RTN15c7 ARTAttachRequestParams *const params = [[ARTAttachRequestParams alloc] initWithReason:stateChange.reason]; [channel reattachWithParams:params]; } + [self sendQueuedMessages]; } else if (![self shouldQueueEvents]) { if (!channelStateChangeParams) { From d60269af89ce3da70f935b4aacdbd75775d718a4 Mon Sep 17 00:00:00 2001 From: Marat Al Date: Sun, 30 Jun 2024 14:44:48 +0200 Subject: [PATCH 4/7] Proceeding with detach on `CONNECTED`. --- Source/ARTRealtime.m | 3 +- Source/ARTRealtimeChannel.m | 53 +++++++++++-------- .../Ably/ARTRealtimeChannel+Private.h | 2 +- 3 files changed, 33 insertions(+), 25 deletions(-) diff --git a/Source/ARTRealtime.m b/Source/ARTRealtime.m index 9bd3f3529..5ab769271 100644 --- a/Source/ARTRealtime.m +++ b/Source/ARTRealtime.m @@ -743,9 +743,8 @@ - (void)performTransitionToState:(ARTRealtimeConnectionState)state withParams:(A if ([self shouldSendEvents]) { for (ARTRealtimeChannelInternal *channel in channels) { - // Reattach channel regardless resume success - RTN15c6, RTN15c7 ARTAttachRequestParams *const params = [[ARTAttachRequestParams alloc] initWithReason:stateChange.reason]; - [channel reattachWithParams:params]; + [channel proceedAttachDetachWithParams:params]; } [self sendQueuedMessages]; } diff --git a/Source/ARTRealtimeChannel.m b/Source/ARTRealtimeChannel.m index 71dfd7116..dfcff2b4c 100644 --- a/Source/ARTRealtimeChannel.m +++ b/Source/ARTRealtimeChannel.m @@ -873,6 +873,15 @@ - (void)reattachWithParams:(ARTAttachRequestParams *)params { } } +- (void)proceedAttachDetachWithParams:(ARTAttachRequestParams *)params { + if (self.state_nosync == ARTChannelEventDetaching) { + ARTLogDebug(self.logger, @"RT:%p C:%p (%@) %@ proceeding with detach", _realtime, self, self.name, ARTRealtimeChannelStateToStr(self.state_nosync)); + [self internalDetach:nil]; + } else { + [self reattachWithParams:params]; + } +} + - (void)internalAttach:(ARTCallback)callback withParams:(ARTAttachRequestParams *)params { switch (self.state_nosync) { case ARTRealtimeChannelDetaching: { @@ -949,17 +958,6 @@ - (void)_detach:(ARTCallback)callback { ARTLogDebug(self.logger, @"RT:%p C:%p (%@) can't detach when not attached", _realtime, self, self.name); if (callback) callback(nil); return; - case ARTRealtimeChannelAttaching: { - ARTLogDebug(self.logger, @"RT:%p C:%p (%@) waiting for the completion of the attaching operation", _realtime, self, self.name); - [_attachedEventEmitter once:^(ARTErrorInfo *errorInfo) { - if (callback && errorInfo) { - callback(errorInfo); - return; - } - [self _detach:callback]; - }]; - return; - } case ARTRealtimeChannelDetaching: ARTLogDebug(self.logger, @"RT:%p C:%p (%@) already detaching", _realtime, self, self.name); if (callback) [_detachedEventEmitter once:callback]; @@ -982,6 +980,27 @@ - (void)_detach:(ARTCallback)callback { default: break; } + [self internalDetach:callback]; +} + +- (void)internalDetach:(ARTCallback)callback { + switch (self.state_nosync) { + case ARTRealtimeChannelAttaching: { + ARTLogDebug(self.logger, @"RT:%p C:%p (%@) waiting for the completion of the attaching operation", _realtime, self, self.name); + [_attachedEventEmitter once:^(ARTErrorInfo *errorInfo) { + if (callback && errorInfo) { + callback(errorInfo); + return; + } + [self _detach:callback]; + }]; + return; + } + default: + break; + } + + _errorReason = nil; if (![self.realtime isActive]) { ARTLogDebug(self.logger, @"RT:%p C:%p (%@) can't detach when not in an active state", _realtime, self, self.name); @@ -1015,17 +1034,7 @@ - (void)detachAfterChecks:(ARTCallback)callback { [self performTransitionToState:ARTRealtimeChannelAttached withParams:params]; [self->_detachedEventEmitter emit:nil with:errorInfo]; }] startTimer]; - - if (![self.realtime shouldQueueEvents]) { - ARTEventListener *reconnectedListener = [self.realtime.connectedEventEmitter once:^(NSNull *n) { - // Disconnected and connected while detaching, re-detach. - [self detachAfterChecks:callback]; - }]; - [_detachedEventEmitter once:^(ARTErrorInfo *err) { - [self.realtime.connectedEventEmitter off:reconnectedListener]; - }]; - } - + if (self.presence.syncInProgress_nosync) { [self.presence failsSync:[ARTErrorInfo createWithCode:ARTErrorChannelOperationFailed message:@"channel is being DETACHED"]]; } diff --git a/Source/PrivateHeaders/Ably/ARTRealtimeChannel+Private.h b/Source/PrivateHeaders/Ably/ARTRealtimeChannel+Private.h index 79dc55276..f2c411170 100644 --- a/Source/PrivateHeaders/Ably/ARTRealtimeChannel+Private.h +++ b/Source/PrivateHeaders/Ably/ARTRealtimeChannel+Private.h @@ -47,7 +47,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithRealtime:(ARTRealtimeInternal *)realtime andName:(NSString *)name withOptions:(ARTRealtimeChannelOptions *)options logger:(ARTInternalLog *)logger; -- (void)reattachWithParams:(ARTAttachRequestParams *)params; +- (void)proceedAttachDetachWithParams:(ARTAttachRequestParams *)params; - (void)_attach:(nullable ARTCallback)callback; - (void)_detach:(nullable ARTCallback)callback; From 77b39d11a9dbcfd6149dca4337e0e76bef92e08e Mon Sep 17 00:00:00 2001 From: Marat Al Date: Sun, 23 Jun 2024 21:17:00 +0200 Subject: [PATCH 5/7] Avoid generation of a second ATTACHING event (RTL3d). --- Source/ARTRealtimeChannel.m | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Source/ARTRealtimeChannel.m b/Source/ARTRealtimeChannel.m index dfcff2b4c..e43da940a 100644 --- a/Source/ARTRealtimeChannel.m +++ b/Source/ARTRealtimeChannel.m @@ -905,9 +905,11 @@ - (void)internalAttach:(ARTCallback)callback withParams:(ARTAttachRequestParams if (callback) [_attachedEventEmitter once:callback]; // Set state: Attaching - const ARTState state = params.reason ? ARTStateError : ARTStateOk; - ARTChannelStateChangeParams *const stateChangeParams = [[ARTChannelStateChangeParams alloc] initWithState:state errorInfo:params.reason storeErrorInfo:NO retryAttempt:params.retryAttempt]; - [self performTransitionToState:ARTRealtimeChannelAttaching withParams:stateChangeParams]; + if (self.state_nosync != ARTRealtimeChannelAttaching) { + const ARTState state = params.reason ? ARTStateError : ARTStateOk; + ARTChannelStateChangeParams *const stateChangeParams = [[ARTChannelStateChangeParams alloc] initWithState:state errorInfo:params.reason storeErrorInfo:NO retryAttempt:params.retryAttempt]; + [self performTransitionToState:ARTRealtimeChannelAttaching withParams:stateChangeParams]; + } [self attachAfterChecks]; } From 586c255ed85ee6320549e9cca149cdff41522185 Mon Sep 17 00:00:00 2001 From: Marat Al Date: Sun, 30 Jun 2024 23:24:33 +0200 Subject: [PATCH 6/7] Removed confusing `shouldQueueEvents` property. `isActive` serves this purpose now. --- Source/ARTRealtime.m | 14 +++++--------- Source/PrivateHeaders/Ably/ARTRealtime+Private.h | 1 - 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/Source/ARTRealtime.m b/Source/ARTRealtime.m index 5ab769271..f76ce096f 100644 --- a/Source/ARTRealtime.m +++ b/Source/ARTRealtime.m @@ -748,7 +748,7 @@ - (void)performTransitionToState:(ARTRealtimeConnectionState)state withParams:(A } [self sendQueuedMessages]; } - else if (![self shouldQueueEvents]) { + else if (!self.isActive) { if (!channelStateChangeParams) { if (stateChange.reason) { channelStateChangeParams = [[ARTChannelStateChangeParams alloc] initWithState:ARTStateError @@ -1207,9 +1207,9 @@ - (BOOL)shouldSendEvents { } } -- (BOOL)shouldQueueEvents { - if(!self.options.queueMessages) { - return false; +- (BOOL)isActive { + if (self.shouldSendEvents) { + return true; } switch (self.connection.state_nosync) { case ARTRealtimeInitialized: @@ -1223,10 +1223,6 @@ - (BOOL)shouldQueueEvents { } } -- (BOOL)isActive { - return [self shouldQueueEvents] || [self shouldSendEvents]; -} - - (void)sendImpl:(ARTProtocolMessage *)pm reuseMsgSerial:(BOOL)reuseMsgSerial sentCallback:(ARTCallback)sentCallback ackCallback:(ARTStatusCallback)ackCallback { if (pm.ackRequired) { if (!reuseMsgSerial) { // RTN19a2 @@ -1275,7 +1271,7 @@ - (void)send:(ARTProtocolMessage *)msg reuseMsgSerial:(BOOL)reuseMsgSerial sentC } // see RTL6c2, RTN19, RTN7 and TO3g else if (msg.ackRequired) { - if ([self shouldQueueEvents]) { + if (self.isActive && self.options.queueMessages) { ARTQueuedMessage *lastQueuedMessage = self.queuedMessages.lastObject; //RTL6d5 BOOL merged = [lastQueuedMessage mergeFrom:msg sentCallback:nil ackCallback:ackCallback]; if (!merged) { diff --git a/Source/PrivateHeaders/Ably/ARTRealtime+Private.h b/Source/PrivateHeaders/Ably/ARTRealtime+Private.h index bb12e3175..4c819255d 100644 --- a/Source/PrivateHeaders/Ably/ARTRealtime+Private.h +++ b/Source/PrivateHeaders/Ably/ARTRealtime+Private.h @@ -51,7 +51,6 @@ NS_ASSUME_NONNULL_BEGIN // State properties - (BOOL)shouldSendEvents; -- (BOOL)shouldQueueEvents; // Message sending - (void)sendQueuedMessages; From 3fbd9770f371277a8ffe4fa7fa611fd40391c4f4 Mon Sep 17 00:00:00 2001 From: Marat Al Date: Tue, 2 Jul 2024 01:28:06 +0200 Subject: [PATCH 7/7] Removed unused callback. --- Source/ARTRealtimeChannel.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/ARTRealtimeChannel.m b/Source/ARTRealtimeChannel.m index e43da940a..17bb3e9da 100644 --- a/Source/ARTRealtimeChannel.m +++ b/Source/ARTRealtimeChannel.m @@ -1015,10 +1015,10 @@ - (void)internalDetach:(ARTCallback)callback { ARTChannelStateChangeParams *const params = [[ARTChannelStateChangeParams alloc] initWithState:ARTStateOk]; [self performTransitionToState:ARTRealtimeChannelDetaching withParams:params]; - [self detachAfterChecks:callback]; + [self detachAfterChecks]; } -- (void)detachAfterChecks:(ARTCallback)callback { +- (void)detachAfterChecks { ARTProtocolMessage *detachMessage = [[ARTProtocolMessage alloc] init]; detachMessage.action = ARTProtocolMessageDetach; detachMessage.channel = self.name;