-
Notifications
You must be signed in to change notification settings - Fork 26
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
Enforce new connection when last activity > than (idle interval + TTL) #719
Changes from all commits
60cf4eb
deb79a7
014a1c8
4dfd7da
30e0e8f
3bb7493
d1c7a3c
8565908
c64f625
bd30f97
4ea8dc0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2649,6 +2649,118 @@ class RealtimeClientConnection: QuickSpec { | |
} | ||
} | ||
} | ||
|
||
// RTN15g RTN15g1 | ||
context("when connection (ttl + idle interval) period has passed since last activity") { | ||
let options = AblyTests.commonAppSetup() | ||
// We want this to be > than the sum of customTtlInterval and customIdleInterval | ||
options.disconnectedRetryTimeout = 5.0 | ||
var client: ARTRealtime! | ||
var connectionId = "" | ||
let customTtlInterval: TimeInterval = 1.0 | ||
let customIdleInterval: TimeInterval = 1.0 | ||
|
||
it("uses a new connection") { | ||
client = AblyTests.newRealtime(options) | ||
client.connect() | ||
defer { client.close() } | ||
|
||
waitUntil(timeout: testTimeout) { done in | ||
client.connection.once(.connected) { _ in | ||
expect(client.connection.id).toNot(beNil()) | ||
connectionId = client.connection.id! | ||
client.connectionStateTtl = customTtlInterval | ||
client.maxIdleInterval = customIdleInterval | ||
client.connection.once(.disconnected) { _ in | ||
let disconnectedAt = Date() | ||
expect(client.connectionStateTtl).to(equal(customTtlInterval)) | ||
expect(client.maxIdleInterval).to(equal(customIdleInterval)) | ||
client.connection.once(.connecting) { _ in | ||
let reconnectionInterval = Date().timeIntervalSince(disconnectedAt) | ||
expect(reconnectionInterval).to(beGreaterThan(client.connectionStateTtl + client.maxIdleInterval)) | ||
client.connection.once(.connected) { _ in | ||
expect(client.connection.id).toNot(equal(connectionId)) | ||
done() | ||
} | ||
} | ||
} | ||
client.onDisconnected() | ||
} | ||
} | ||
} | ||
// RTN15g3 | ||
it("reattaches to the same channels after a new connection has been established") { | ||
client = AblyTests.newRealtime(options) | ||
client.connect() | ||
defer { client.close() } | ||
let channelName = "test-reattach-after-ttl" | ||
let channel = client.channels.get(channelName) | ||
|
||
waitUntil(timeout: testTimeout) { done in | ||
client.connection.once(.connected) { _ in | ||
connectionId = client.connection.id! | ||
client.connectionStateTtl = customTtlInterval | ||
client.maxIdleInterval = customIdleInterval | ||
channel.attach { error in | ||
if let error = error { | ||
fail(error.message) | ||
} | ||
expect(channel.state).to(equal(ARTRealtimeChannelState.attached)) | ||
} | ||
client.connection.once(.disconnected) { _ in | ||
client.connection.once(.connecting) { _ in | ||
client.connection.once(.connected) { _ in | ||
expect(client.connection.id).toNot(equal(connectionId)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is the connection ID changing? There is no pause as far as I can see. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As above, there should be no pause according to https://docs.ably.io/client-lib-development-guide/features/#RTN15a |
||
channel.once(.attached) { _ in | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are not checking that the attached ChannelStateChange has a flag indicating loss of continuity on the channel. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mattheworiordan you mean I should check if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
done() | ||
} | ||
} | ||
} | ||
} | ||
client.onDisconnected() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this done before the attach is completed? The sequence of events for this test is wrong i.e. the initial There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mattheworiordan I don't understand. Would you prefer to see this within the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, exactly, otherwise how do we know that the channel attached first and thus gets reattached after reconnected? |
||
} | ||
} | ||
} | ||
} | ||
|
||
// RTN15g2 | ||
context("when connection (ttl + idle interval) period has NOT passed since last activity") { | ||
let options = AblyTests.commonAppSetup() | ||
options.disconnectedRetryTimeout = 5.0 | ||
var client: ARTRealtime! | ||
var connectionId = "" | ||
let customTtlInterval: TimeInterval = 20.0 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why even set this, surely a standard connection should reconnect automatically without any custom settings? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mattheworiordan good spot. This is not needed. |
||
let customIdleInterval: TimeInterval = 20.0 | ||
|
||
it("uses the same connection") { | ||
client = AblyTests.newRealtime(options) | ||
client.connect() | ||
defer { client.close() } | ||
|
||
waitUntil(timeout: testTimeout) { done in | ||
client.connection.once(.connected) { _ in | ||
expect(client.connection.id).toNot(beNil()) | ||
connectionId = client.connection.id! | ||
client.connectionStateTtl = customTtlInterval | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does the client really allow these intervals to be changed once it is instanced? Or is this a test thing that allows us to "hack" these values on a running client? Obviously if customers tried the same thing they'd get very odd and unpredictable behaviour. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For our customers We have a bunch of methods to expose and set private variables for whitebox testing. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, thanks for clarifying |
||
client.maxIdleInterval = customIdleInterval | ||
client.connection.once(.disconnected) { _ in | ||
let disconnectedAt = Date() | ||
expect(client.connectionStateTtl).to(equal(customTtlInterval)) | ||
expect(client.maxIdleInterval).to(equal(customIdleInterval)) | ||
client.connection.once(.connecting) { _ in | ||
let reconnectionInterval = Date().timeIntervalSince(disconnectedAt) | ||
expect(reconnectionInterval).to(beLessThan(client.connectionStateTtl + client.maxIdleInterval)) | ||
client.connection.once(.connected) { _ in | ||
expect(client.connection.id).to(equal(connectionId)) | ||
done() | ||
} | ||
} | ||
} | ||
client.onDisconnected() | ||
} | ||
} | ||
} | ||
} | ||
|
||
// RTN15h | ||
context("DISCONNECTED message contains a token error") { | ||
|
@@ -3313,7 +3425,7 @@ class RealtimeClientConnection: QuickSpec { | |
guard let error = stateChange?.reason else { | ||
fail("Error is nil"); done(); return | ||
} | ||
expect(error.message).to(contain("bad response")) | ||
expect(error.message).to(contain("Invalid key")) | ||
done() | ||
} | ||
} | ||
|
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.
Why is this the case? I don't see any explicit request to pause / delay the reconnecting. What has caused this delay then?
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.
@mattheworiordan It was this option, which tries the reconnection after 5s the client has been in a
DISCONNECTED
state https://github.com/ably/ably-ios/blob/develop/Spec/RealtimeClientConnection.swift#L2657There 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.
But this is not according to the spec. The client will retry to reconnect immediately after disconnect, see https://docs.ably.io/client-lib-development-guide/features/#RTN15a, not wait
disconnectedRetryTimeout
. It only waitsdisconnectedRetryTimeout
on subsequent requests.