You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add side effects of more connection states for DETACHING channels
We add handling for the following connection states:
FAILED: We're never going to receive the DETACHED that we're waiting
for, but we don't want to remain in DETACHING forever. So, let's put the
channel into FAILED and fail the #detach request.
CLOSED: We're never going to receive the DETACHED that we're waiting
for, but we don't want to remain in DETACHING forever. I don't think we
should consider this as a failure of the #detach request, because by
becoming CLOSED we've decided that we consider the server-side
connection state to have been torn down, and so it seems like we should
also consider the server-side attachment state to have also been torn
down. So, succeed the #detach request.
SUSPENDED: By becoming SUSPENDED, we've decided that there is no longer
any server-side connection state, and so I think we can conclude there
is also no longer any server-side attachment state and thus consider the
request to tear it down (that is, the #detach request) to have
succeeded. It's also consistent with what we do in RTL5j when #detach is
called on a SUSPENDED channel.
Now that there are more ways in which a #detach request can resolve, we
bring #detach in line with #attach and make its callback be driven by
the channel state.
Note: we noticed the need for these spec points because we noticed ([1],
[2]) that, in the absence of guidance from the spec, in ably-js a
DETACHING channel actually ends up becoming SUSPENDED when the
connection becomes SUSPENDED, which means it ends up reattaching when
the connection becomes CONNECTED again. This is not what we want — a
DETACHING channel should never autonomously reattach.
[1] https://ably-real-time.slack.com/archives/C8SPU4589/p1732273028523529?thread_ts=1732191641.458019&cid=C8SPU4589
[2] https://github.com/ably/ably-js/blob/18a255948c38d1e60715c8f5d6173369b57cb8d6/src/common/lib/client/baserealtime.ts#L178
** @(RTL3e)@ If the connection state enters the @DISCONNECTED@ state, it will have no effect on the channel states.
659
659
** @(RTL3a)@ If the connection state enters the @FAILED@ state, then an @ATTACHING@ or @ATTACHED@ channel state will transition to @FAILED@ and set the @RealtimeChannel#errorReason@
660
+
** @(RTL3g)@ If the connection state enters the @FAILED@ state, then any channels in the @DETACHING@ state should transition to @FAILED@ and set their @errorReason@ to that of the connection.
660
661
** @(RTL3b)@ If the connection state enters the @CLOSED@ state, then an @ATTACHING@ or @ATTACHED@ channel state will transition to @DETACHED@
661
662
** @(RTL3c)@ If the connection state enters the @SUSPENDED@ state, then an @ATTACHING@ or @ATTACHED@ channel state will transition to @SUSPENDED@
663
+
** @(RTL3h)@ If the connection enters the @CLOSED@ or @SUSPENDED@ state, then any channels in the @DETACHING@ state should transition to @DETACHED@.
662
664
** @(RTL3d)@ If the connection state enters the @CONNECTED@ state, any channels in the @ATTACHING@, @ATTACHED@, or @SUSPENDED@ states should be transitioned to @ATTACHING@ (other than ones already in that state), and initiate an @RTL4c@ attach sequence. (If the attach operation times out and the channel was previously @SUSPENDED@, it should return to the @SUSPENDED@ state, see "RTL4f":#RTL4f). The connection should also process any messages that had been queued per @RTL6c2@ (it should do this immediately, without waiting for the attach operations to finish).
663
665
** @(RTL3f)@ If the connection enters the @CONNECTED@ state then any channels in the @DETACHING@ state should initiate an "@RTL5d@":#RTL5d detach sequence.
664
666
* @(RTL11)@ If a channel enters the @DETACHED@, @SUSPENDED@ or @FAILED@ state, then all presence actions that are still queued for send on that channel per "RTP16b":#RTP16b should be deleted from the queue, and any callback passed to the corresponding presence method invocation should be called with an @ErrorInfo@ indicating the failure
** @(RTL4l)@ If the user has specified a @modes@ array in the @ChannelOptions@ ("@TB2d@":#TB2d), it must be encoded as a bitfield per "@TR3@":#TR3 and set as the @flags@ field of the @ATTACH@ @ProtocolMessage@. (For the avoidance of doubt, when multiple different spec items require flags to be set in the @ATTACH@, the final @flags@ field should be the bitwise OR of them all)
685
687
** @(RTL4m)@ On receipt of an @ATTACHED@, the client library should decode the @flags@ into an array of @ChannelMode@ s (that is, the same format as @ChannelOptions.modes@) and expose it as a read-only @modes@ field of the @RealtimeChannel@ (or a @getModes()@ method where that is more idiomatic). This should only contain @ChannelMode@ s: it should not contain flags which are not modes (see "@TB2d@":#TB2d)
686
688
* @(RTL5)@ @RealtimeChannel#detach@ function:
687
-
** @(RTL5a)@ If the channel state is @INITIALIZED@ or @DETACHED@ nothing is done
689
+
** @(RTL5a)@ If the channel state is @INITIALIZED@ or @DETACHED@ nothing is done, and the optional callback should be called with no argument
688
690
** @(RTL5i)@ If the channel is in a pending state @DETACHING@ or @ATTACHING@, do the detach operation after the completion of the pending request
689
-
** @(RTL5b)@ If the channel state is @FAILED@, the @detach@ request results in an error
690
-
** @(RTL5j)@ If the channel state is @SUSPENDED@, the @detach@ request transitions the channel immediately to the @DETACHED@ state
691
-
** @(RTL5g)@ If the connection state is @CLOSING@ or @FAILED@, the @detach@ request results in an error
691
+
** @(RTL5b)@ If the channel state is @FAILED@, the @detach@ request results in an error (that is, depending on what is idiomatic for the language it should either throw an error or call its optional callback with an error)
692
+
** @(RTL5j)@ If the channel state is @SUSPENDED@, the @detach@ request transitions the channel immediately to the @DETACHED@ state, and calls the optional callback with no argument
693
+
** @(RTL5g)@ If the connection state is @CLOSING@ or @FAILED@, the @detach@ request results in an error (that is, depending on what is idiomatic for the language it should either throw an error or call its optional callback with an error)
692
694
** @(RTL5h)@ If the connection state is @CONNECTING@ or @DISCONNECTED@, do the detach operation once the connection state is @CONNECTED@
693
695
** @(RTL5d)@ Otherwise (i.e. the channel state is @ATTACHED@ and the connection — given this channel state, "@RTL3@":#RTL3, and the above connection state conditions — is thus @CONNECTED@) a @DETACH@ ProtocolMessage is sent to the server, the state transitions to @DETACHING@ and the channel becomes @DETACHED@ when the confirmation @DETACHED@ ProtocolMessage is received
694
696
** @(RTL5f)@ This clause has been replaced by "@RTL5l@":#RTL5l. It was valid up to and including specification version @TBD@.
695
-
** @(RTL5l)@ Once a @DETACH@ @ProtocolMessage@ is sent, if a @DETACHED@ @ProtocolMessage@ is not received within "@realtimeRequestTimeout@":#TO3l11, the detach request should be treated as though it has failed and the channel will transition back to @ATTACHED@
697
+
** @(RTL5l)@ Once a @DETACH@ @ProtocolMessage@ is sent, if a @DETACHED@ @ProtocolMessage@ is not received within "@realtimeRequestTimeout@":#TO3l11, the detach request should be treated as though it has failed, and the channel will transition back to @ATTACHED@ and call its optional callback with an error
696
698
** @(RTL5k)@ If the channel receives an @ATTACHED@ message while in the @DETACHING@ or @DETACHED@ state, it should send a new @DETACH@ message and remain in (or transition to) the @DETACHING@ state
697
-
** @(RTL5e)@ If the language permits, a callback can be provided that is called when the channel is detached successfully or the detach fails and the @ErrorInfo@ error is passed as an argument to the callback
699
+
** @(RTL5e)@ This clause has been replaced by "@RTL5m@":#RTL5m. It was valid up to and including specification version @TBD@.
700
+
** @(RTL5m)@ A callback (or other language-idiomatic equivalent) can be provided that is called by either "@RTL5a@":#RTL5a, "@RTL5b@":#RTL5b, "@RTL5j@":#RTL5j, "@RTL5g@":#RTL5g or "@RTL5l@":#RTL5l, or when, after the channel transitions to @DETACHING@ in "@RTL5d@":#RTL5d and the request does not subsequently time out in "@RTL5l@":#RTL5l, the channel next moves to one of the @DETACHED@ or @FAILED@ states. In the case of @DETACHED@ the callback is called with no argument. In the case of @FAILED@ it is called with an @ErrorInfo@ corresponding to the @ChannelStateChange.reason@ of the state change to indicate that the detach has failed.
698
701
* @(RTL6)@ @RealtimeChannel#publish@ function:
699
702
** @(RTL6a)@ Messages are encoded in the same way as the @RestChannel#publish@ method, and "RSL1g":#RSL1g (size limit) applies similarly
700
703
*** @(RTL6a1)@ "RSL1k":#RSL1k (@idempotentRestPublishing@ option), "RSL1j1":#RSL1j1 (idempotent publishing test), and "RSL1l":#RSL1l (@publish(Message, params)@ form) do not apply to realtime publishes
0 commit comments