-
Notifications
You must be signed in to change notification settings - Fork 25
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
RTP17b #835
RTP17b #835
Conversation
Swift Regression https://bugs.swift.org/browse/SR-2429 That's why sometimes some tests were failing because the server responded differently: X-Ably-Errorcode or X-Ably-errorcode, etc.
is now ARTPresenceMessage.isNewerThan.
when channel is Suspended. Realtime sends an ATTACHED message after a successful resume.
for (ARTRealtimeChannel* channel in self.channels.nosyncIterable) { | ||
if (channel.state_nosync == ARTRealtimeChannelSuspended) { | ||
[channel _attach:nil]; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did this fix in this PR because the RTP17b test was failing because of this. Discussion here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ricardopereira With this removal, does the library comply with RTN15c3? "when a resume request results in a CONNECTED with a new connectionId ... The client library should initiate an attach for channels that are in the SUSPENDED state. For all channels in the ATTACHING or ATTACHED state, the client library should fail any previously queued messages for that channel and initiate a new attach..."
cf my comment in slack "you shouldn't be sending an attached after a successful resume, only for an unsuccessful one" -- you still need to do the latter.
(From that test log it looks like the connection moved to suspended
, but it's not obvious why from the log, the resume was successful so I can't see any reason for it to do so)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With this removal, does the library comply with RTN15c3?
@SimonWoolf Yes it does. When I implemented RTN15c3
, I forgot to remove that bit because the new implementation already handle that case. You can see that the channel will reattach
ably-cocoa/Source/ARTRealtime.m
Lines 608 to 615 in 8dbc03d
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]; | |
// Reattach all channels | |
for (ARTRealtimeChannel *channel in self.channels.nosyncIterable) { | |
[channel reattachWithReason:message.error callback:nil]; | |
} | |
_resuming = false; | |
} |
ably-cocoa/Source/ARTRealtimeChannel.m
Lines 924 to 934 in 8dbc03d
case ARTRealtimeChannelSuspended: | |
[self.realtime.logger debug:__FILE__ line:__LINE__ message:@"R:%p C:%p (%@) attached or suspended and will reattach", _realtime, self, self.name]; | |
break; | |
case ARTRealtimeChannelAttaching: | |
[self.realtime.logger debug:__FILE__ line:__LINE__ message:@"R:%p C:%p (%@) already attaching", _realtime, self, self.name]; | |
if (callback) [_attachedEventEmitter once:callback]; | |
return; | |
default: | |
break; | |
} | |
[self internalAttach:callback withReason:reason storeErrorInfo:false]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(From that test log it looks like the connection moved to suspended, but it's not obvious why from the log, the resume was successful so I can't see any reason for it to do so)
@SimonWoolf That's because the test forces to suspend:
ably-cocoa/Spec/RealtimeClientPresence.swift
Lines 3034 to 3039 in 8dbc03d
// Inject an additional member into the myMember set, then force a suspended state | |
client.simulateSuspended(beforeSuspension: { done in | |
channel.presenceMap.localMembers.add(additionalMember) | |
done() | |
}) | |
expect(client.connection.state).to(equal(.suspended)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I forgot to remove that bit because the new implementation already handle that case
👍
Though looking at reattachWithReason
, it looks to me like it's reattaching channels in every state except attaching. So (1) it's starting an attach for channels in initialized
, detached
, or failed
, which it really shouldn't be; and (2) it isn't initiating a new attach for a channel in the attaching
state (we've just started a completely new connection, so any previously-in-progress attach needs to be started again). Or am I misreading it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@SimonWoolf You're not misreading. It seems so, it's not respecting RTN15c3
. Issue has been created: #847
Case: Push test was failing because lib was returning an error with 204 status code which shouldn't.
…gnized selector sent to instance Because of 8fb2e0c, there are 2 ARTBaseMessage (ARTPresenceMessage) class method swizzling and Aspects doesn't support that and that's why the error occurs. There are similar issues in the Aspects repo like this one: Aspects/issues/145. I tried the fix of that PR but it didn't work. So, I decided to change all of the class methods swizzling to fix this case and reduce future issues.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The actual RTP17b bit (newer comparison etc.) looks good, but some questions re the sync() method and the channel reattaching bit
@@ -119,6 +120,10 @@ - (void)internalRemove:(ARTPresenceMessage *)message { | |||
} | |||
|
|||
- (void)internalRemove:(ARTPresenceMessage *)message force:(BOOL)force { | |||
if ([message.connectionId isEqualToString:self.delegate.connectionId] && !message.isSynthesized) { | |||
[_localMembers removeObject:message]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now you've added this, you need to remove line 134, or it'll do the remove unconditionally
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed ca32ef2. Thanks
for (ARTRealtimeChannel* channel in self.channels.nosyncIterable) { | ||
if (channel.state_nosync == ARTRealtimeChannelSuspended) { | ||
[channel _attach:nil]; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ricardopereira With this removal, does the library comply with RTN15c3? "when a resume request results in a CONNECTED with a new connectionId ... The client library should initiate an attach for channels that are in the SUSPENDED state. For all channels in the ATTACHING or ATTACHED state, the client library should fail any previously queued messages for that channel and initiate a new attach..."
cf my comment in slack "you shouldn't be sending an attached after a successful resume, only for an unsuccessful one" -- you still need to do the latter.
(From that test log it looks like the connection moved to suspended
, but it's not obvious why from the log, the resume was successful so I can't see any reason for it to do so)
Source/ARTRealtimeChannel.m
Outdated
if (self.presenceMap.syncMsgSerial) { | ||
msg.channelSerial = self.presenceMap.syncChannelSerial; | ||
msg.msgSerial = [NSNumber numberWithLongLong:self.presenceMap.syncMsgSerial]; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand this. What is a syncMsgSerial? It looks like it's being set from a SYNC msgSerial, but that isn't a thing (no incoming messages ever have msgSerials, and SYNCs don't have them in either direction). Nothing in RTP3 tells you to do this, it only asks for the channelSerial.
Also, AFAICS syncChannelSerial and syncMsgSerial are never unset in endSync, so any sync() call will result in the lib trying to resume an actually-successfully-completed sync, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@SimonWoolf Thanks for pointing this out. Fixed dc84181.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And the second issue (second paragraph of my comment)? presenceMap.syncChannelSerial
is only ever set, never unset, and you're setting it on the sync unconditionally, requesting a resume of a sync that actually completed successfully?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@SimonWoolf Right, fixed 0d7cdc0. Set syncChannelSerial
to nil when the sync ends.
} | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't see the bit of this test that tests synthesized leave's effect on the own-members set, as the test name implies? (If it is there than it's odd that it passed, since https://github.com/ably/ably-cocoa/pull/835/files#r278056029 means that the logic wasn't actually taking effect)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@SimonWoolf You're right, that part is missing. What's the best way to test the synthesized leave's effect? I'm thinking in forcing a synthesized leave of one existing presence and force a sync. Then after the sync, the user should be updated since the user is re-entered and the final members map should remain the same, no leave has taken effect.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A proper end-to-end test that forces realtime to do a synthesized leave is a bit annoying if only because it means the test will take at least 15 seconds. But if you want to do that, something like: enter, force a disconnect, wait 20s, reconnect, wait to see the synthesized leave (& sync showing the member not present), wait for lib to automatically re-enter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@SimonWoolf Thanks, updated the test case 46dd5e7.
Branch updated. |
Related #737