diff --git a/textile/features.textile b/textile/features.textile index 9ebd3cd2..a78dc15f 100644 --- a/textile/features.textile +++ b/textile/features.textile @@ -616,7 +616,7 @@ h3(#realtime-connection). Connection ** @(RTN19a)@ Any @ProtocolMessage@ that is awaiting an @ACK@/@NACK@ on the old transport will not receive the @ACK@/@NACK@ on the new transport. The client library must therefore resend any @ProtocolMessage@ that is awaiting a @ACK@/@NACK@ to Ably in order to receive the expected @ACK@/@NACK@ for that message (subject to @RTN7e@/@RTN7d@). The Ably service is responsible for keeping track of messages, ignoring duplicates and responding with suitable @ACK@/@NACK@ messages *** @(RTN19a1)@ One possible implementation of this requirement would be to add any in-flight messages to the @RTL6c2@ connection-wide queue of messages that will be sent once the connection next becomes @CONNECTED@ *** @(RTN19a2)@ In the case of an @RTN15c6@ successful resume, the @msgSerial@ of the reattempted @ProtocolMessage@s should remain the same as for the original attempt. In the case of an @RTN15c7@ failed resume, the message must be assigned a new @msgSerial@ from the SDK's internal counter. -** @(RTN19b)@ If there are any pending channels i.e. in the @ATTACHING@ or @DETACHING@ state, the respective @ATTACH@ or @DETACH@ message should be resent to Ably +** @(RTN19b)@ This clause has been replaced by "@RTL3d@":#RTL3d and "@RTL3f@":#RTL3f. It was valid up to and including specification version @TBD@. * @(RTN23)@ Heartbeats ** @(RTN23a)@ If a transport does not receive any indication of activity on a transport for a period greater than the sum of the @maxIdleInterval@ (which will be sent in the @connectionDetails@ of the most recent @CONNECTED@ message received on that transport) and the "@realtimeRequestTimeout@":#TO3l11@, that transport should be disconnected. Any message (or non-message indicator, see @RTN23b@) received counts as an indication of activity and should reset the timer, not merely heartbeat messages. However, it must be received (that is, sent from the server to the client); client-sent data does not count. ** @(RTN23b)@ When initiating a connection, the client may send a @heartbeats@ param in the querystring, with value @true@ or @false@. If the value is true, the server will use Ably protocol messages (for example, a message with a @HEARTBEAT@ action) to satisfy the @maxIdleInterval@ requirement. If it is false or unspecified, the server is permitted to use any transport-level mechanism (for example, "websocket":https://ably.com/topic/websockets ping frames) to satisfy this. So for example, for "websocket transports":https://ably.com/topic/websockets, if the client is able to observe websocket pings, then it should send @heartbeats=false@. If not, it should send @heartbeats=true@. @@ -657,22 +657,25 @@ h3(#realtime-channel). RealtimeChannel * @(RTL3)@ Connection state change side effects: ** @(RTL3e)@ If the connection state enters the @DISCONNECTED@ state, it will have no effect on the channel states. ** @(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@ +** @(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. ** @(RTL3b)@ If the connection state enters the @CLOSED@ state, then an @ATTACHING@ or @ATTACHED@ channel state will transition to @DETACHED@ ** @(RTL3c)@ If the connection state enters the @SUSPENDED@ state, then an @ATTACHING@ or @ATTACHED@ channel state will transition to @SUSPENDED@ +** @(RTL3h)@ If the connection enters the @CLOSED@ or @SUSPENDED@ state, then any channels in the @DETACHING@ state should transition to @DETACHED@. ** @(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). +** @(RTL3f)@ If the connection enters the @CONNECTED@ state then any channels in the @DETACHING@ state should initiate an "@RTL5d@":#RTL5d detach sequence. * @(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 ** @(RTL11a)@ For clarity, any messages awaiting an @ACK@ or @NACK@ are unaffected by channel state changes i.e. a channel that becomes detached following an explicit request to detach may still receive an @ACK@ or @NACK@ for messages published on that channel later * @(RTL4)@ @RealtimeChannel#attach@ function: -** @(RTL4a)@ If already @ATTACHED@ nothing is done +** @(RTL4a)@ If already @ATTACHED@ nothing is done, and the optional callback should be called with no argument ** @(RTL4h)@ If the channel is in a pending state @DETACHING@ or @ATTACHING@, do the attach operation after the completion of the pending request ** @(RTL4g)@ If the channel is in the @FAILED@ state, the @attach@ request sets its @errorReason@ to @null@, and proceeds with a channel attach described in "RTL4b":#RTL4b, "RTL4i":#RTL4i and "RTL4c":#RTL4c -** @(RTL4b)@ If the connection state is @INITIALIZED@, @CLOSED@, @CLOSING@, @SUSPENDED@ or @FAILED@, the @attach@ request results in an error +** @(RTL4b)@ If the connection state is @INITIALIZED@, @CLOSED@, @CLOSING@, @SUSPENDED@ or @FAILED@, the @attach@ 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) *** @(RTL4b1)@ Note that an attach attempt immediately after the library is instantiated, assuming @autoConnect@ (@TO3e@)is not set to @false@, should not raise an error (that is, should fall under @RTL4i@, not @RTL4b@), since the library should be in a @CONNECTING@ state at that point ** @(RTL4i)@ If the connection state is @CONNECTING@ or @DISCONNECTED@, the channel should be put into the @ATTACHING@ state. (Attach message will be sent once the the connection becomes @CONNECTED@ per @RTL3d@). ** @(RTL4c)@ Otherwise an @ATTACH@ ProtocolMessage is sent to the server, the state transitions to @ATTACHING@ and the channel becomes @ATTACHED@ when the confirmation @ATTACHED@ ProtocolMessage is received *** @(RTL4c1)@ The @ATTACH@ ProtocolMessage @channelSerial@ field must be set to the "@RTL15b@":#RTL15b @channelSerial@. If the @RTL15b@ @channelSerial@ is not set, the field may be set to @null@ or omitted. ** @(RTL4f)@ Once an @ATTACH@ @ProtocolMessage@ is sent, if an @ATTACHED@ @ProtocolMessage@ is not received within "@realtimeRequestTimeout@":#TO3l11, the attach request should be treated as though it has failed and the channel should transition to the @SUSPENDED@ state. The channel will then be subsequently automatically re-attached as described in "RTL13":#RTL13 -** @(RTL4d)@ A callback (or other language-idiomatic equivalent) can be provided that is called when the channel next moves to one of @ATTACHED@, @DETACHED@, @SUSPENDED@, or @FAILED@ states. In the case of @ATTACHED@ the callback is called with no argument. In all other cases it is called with an @ErrorInfo@ corresponding to the @ChannelStateChange.reason@ of the state change (or a fallback if there is no @reason@) to indicate that the attach has failed. (Note: when combined with RTL4f, this means that if the connection is @CONNECTED@, the callback is guaranteed to be called within @realtimeRequestTimeout@ of the @attach()@ call) +** @(RTL4d)@ A callback (or other language-idiomatic equivalent) can be provided that is called by either "@RTL4a@":#RTL4a or "@RTL4b@":#RTL4b, or when, after transitioning to @ATTACHING@ in "@RTL4c@":#RTL4c, the channel next moves to one of @ATTACHED@, @DETACHED@, @SUSPENDED@, or @FAILED@ states. In the case of @ATTACHED@ the callback is called with no argument. In all other cases it is called with an @ErrorInfo@ corresponding to the @ChannelStateChange.reason@ of the state change (or a fallback if there is no @reason@) to indicate that the attach has failed. (Note: when combined with RTL4f, this means that if the connection is @CONNECTED@, the callback is guaranteed to be called within @realtimeRequestTimeout@ of the @attach()@ call) *** @(RTL4d1)@ Optionally, upon success, the callback may be invoked with the @ChannelStateChange@ object once the channel is attached. If the channel is already attached, it should be invoked with @null@. ** @(RTL4e)@ This clause has been deleted (redundant to "@RTL14@":#RTL14). ** @(RTL4j)@ If the attach is not a clean attach (defined in @RTL4j1@), for example an automatic reattach triggered by "@RTN15c3@":#RTN15c3 or "@RTL13a@":#RTL13a (non-exhaustive), the library should set the "@ATTACH_RESUME@":#TR3f flag in the @ATTACH@ message @@ -683,16 +686,18 @@ h3(#realtime-channel). RealtimeChannel ** @(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) ** @(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) * @(RTL5)@ @RealtimeChannel#detach@ function: -** @(RTL5a)@ If the channel state is @INITIALIZED@ or @DETACHED@ nothing is done +** @(RTL5a)@ If the channel state is @INITIALIZED@ or @DETACHED@ nothing is done, and the optional callback should be called with no argument ** @(RTL5i)@ If the channel is in a pending state @DETACHING@ or @ATTACHING@, do the detach operation after the completion of the pending request -** @(RTL5b)@ If the channel state is @FAILED@, the @detach@ request results in an error -** @(RTL5j)@ If the channel state is @SUSPENDED@, the @detach@ request transitions the channel immediately to the @DETACHED@ state -** @(RTL5g)@ If the connection state is @CLOSING@ or @FAILED@, the @detach@ request results in an error +** @(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) +** @(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 +** @(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) ** @(RTL5h)@ If the connection state is @CONNECTING@ or @DISCONNECTED@, do the detach operation once the connection state is @CONNECTED@ -** @(RTL5d)@ Otherwise 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 -** @(RTL5f)@ 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 return to its previous state +** @(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 +** @(RTL5f)@ This clause has been replaced by "@RTL5l@":#RTL5l. It was valid up to and including specification version @TBD@. +** @(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 ** @(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 -** @(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 +** @(RTL5e)@ This clause has been replaced by "@RTL5m@":#RTL5m. It was valid up to and including specification version @TBD@. +** @(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. * @(RTL6)@ @RealtimeChannel#publish@ function: ** @(RTL6a)@ Messages are encoded in the same way as the @RestChannel#publish@ method, and "RSL1g":#RSL1g (size limit) applies similarly *** @(RTL6a1)@ "RSL1k":#RSL1k (@idempotentRestPublishing@ option), "RSL1j1":#RSL1j1 (idempotent publishing test), and "RSL1l":#RSL1l (@publish(Message, params)@ form) do not apply to realtime publishes @@ -776,7 +781,7 @@ h3(#realtime-channel). RealtimeChannel ** @(RTL22b)@ The method must allow for matching only messages which do not have @extras.ref@. ** @(RTL22c)@ The listener must only execute if all provided criteria are met. ** @(RTL22d)@ The method should use the @MessageFilter@ object if possible and idiomatic for the language. -* @(RTL24)@ @RealtimeChannel#errorReason@ attribute is an optional @ErrorInfo@ object which is set by the library when an error occurs on the channel, as described by "RTN11d":#RTN11d, "RTL3a":#RTL3a, "RTL4g":#RTL4g, "RTL14":#RTL14. +* @(RTL24)@ @RealtimeChannel#errorReason@ attribute is an optional @ErrorInfo@ object which is set by the library when an error occurs on the channel, as described by "RTN11d":#RTN11d, "RTL3a":#RTL3a, "RTL3g":#RTL3g, "RTL4g":#RTL4g, "RTL14":#RTL14. * @(RTL25)@ @RealtimeChannel#whenState@ function: ** @(RTL25a)@ If the channel is already in the given state, calls the listener with a `null` argument. ** @(RTL25b)@ Else, calls @#once@ with the given state and listener.