From 270fde7be60d3ffc32a3c9160a5fb022e332c1a1 Mon Sep 17 00:00:00 2001 From: Lawrence Forooghian Date: Mon, 7 Oct 2024 15:33:51 -0300 Subject: [PATCH] Tighten up attachOnSubscribe == false behaviour MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sachin pointed out that the behaviour specified in ba79aba of ignoring the user-provided “on attach” callback (which I mentioned there I wasn’t very happy with but whose implications I didn’t fully think through) isn’t great (especially in SDKs where some mechanism other an an optional callback is used to communicate the result of the explicit attach operation, in which it’s not clear how to interpret the behaviour of ba79aba), and in #208 proposed changing the spec to say that this callback should always be called. But there was some disagreement there because some of our SDKs’ APIs (e.g. ably-cocoa) have the fact that this is an “on attach” callback baked into their names, and this can’t be changed to give this callback a new meaning. So, I’ve expanded the point to make sure: - existing SDKs can maintain API semantics where they have no alternative - the user can’t provide a callback that won’t get called - the SDK doesn’t have a method that never returns (or equivalents; e.g. it doesn’t return a promise that never resolves) --- textile/features.textile | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/textile/features.textile b/textile/features.textile index 1a2ac4f2..f07f96d7 100644 --- a/textile/features.textile +++ b/textile/features.textile @@ -688,7 +688,9 @@ h3(#realtime-channel). RealtimeChannel ** @(RTL7b)@ Subscribe with a name argument and a listener argument subscribes a listener to only messages whose @name@ member matches the string name ** @(RTL7c)@ This clause has been replaced by "@RTL7g@":#RTL7g. It was valid up to and including specification version @3.0@. ** @(RTL7g)@ If the @attachOnSubscribe@ channel option is @true@, implicitly attaches the @RealtimeChannel@ if the channel is in the @INITIALIZED@, @DETACHING@, or @DETACHED@ states. The optional callback, if provided, is called according to "@RTL4d@":#RTL4d based on the implicit attach operation. The listener will always be registered regardless of the implicit attach result -** @(RTL7h)@ If the @attachOnSubscribe@ channel option is @false@, the optional callback must not be called. +** @(RTL7h)@ If the @attachOnSubscribe@ channel option is @false@, then the behaviour depends on the public API that a given SDK uses to communicate the result of an "@RTL7g@":#RTL7g implicit attach: +*** If the SDK’s API accepts an optional callback to communicate the result of an "@RTL7g@":#RTL7g implicit attach, then it is a programmer error to provide such a callback when the @attachOnSubscribe@ channel option is @false@. This programmer error should be handled in an idiomatic fashion (e.g. by halting the program). +*** If the SDK’s API communicates the result of an "@RTL7g@"#RTL7g implicit attach in some other fashion (for example by returning a @ChannelStateChange?@), then, when the @attachOnSubscribe@ channel option is @false@, @#subscribe@ should respond in the same way as if would if an "@RTL7g@"#RTL7g implicit attach had been performed on an already-@ATTACHED@ channel (for example by returning a @null@ state change). ** @(RTL7d)@ Messages delivered are automatically decoded based on the @encoding@ attribute; see @RestChannel@ encoding features. Tests should exist to publish and subscribe to encoded messages using the "AES 128":https://github.com/ably/ably-common/blob/main/test-resources/crypto-data-128.json and "AES 256":https://github.com/ably/ably-common/blob/main/test-resources/crypto-data-256.json fixture test data ** @(RTL7e)@ If a message cannot be decoded or decrypted successfully, it should be delivered to the listener with the @encoding@ attribute set indicating the residual encoding state, and an error should be logged ** @(RTL7f)@ A test should exist ensuring published messages are not echoed back to the subscriber when @echoMessages@ is set to false in the @RealtimeClient@ library constructor @@ -782,7 +784,9 @@ h3(#realtime-presence). RealtimePresence ** @(RTP6b)@ Subscribe with an action argument and a listener argument - such as @ENTER@, @LEAVE@, @UPDATE@ or @PRESENT@ - subscribes a listener to receive only presence messages with that action. In lanuages where method overloading is supported the action argument may also be an array of actions to receive only presence messages with an action included in the supplied array. ** @(RTP6c)@ This clause has been replaced by "@RTP6d@":#RTP6d. It was valid up to and including specification version @3.0@. ** @(RTP6d)@ If the @attachOnSubscribe@ channel option is @true@, implicitly attaches the @RealtimeChannel@ if the channel is in the @INITIALIZED@, @DETACHING@, or @DETACHED@ states. The optional callback, if provided, is called according to "@RTL4d@":#RTL4d based on the implicit attach operation. The listener will always be registered regardless of the implicit attach result -** @(RTP6e)@ If the @attachOnSubscribe@ channel option is @false@, the optional callback must not be called. +** @(RTP6e)@ If the @attachOnSubscribe@ channel option is @false@, then the behaviour depends on the public API that a given SDK uses to communicate the result of an "@RTP6d@":#RTP6d implicit attach: +*** If the SDK’s API accepts an optional callback to communicate the result of an "@RTP6d@":#RTP6d implicit attach, then it is a programmer error to provide such a callback when the @attachOnSubscribe@ channel option is @false@. This programmer error should be handled in an idiomatic fashion (e.g. by halting the program). +*** If the SDK’s API communicates the result of an "@RTP6d@"#RTP6d implicit attach in some other fashion (for example by returning a @ChannelStateChange?@), then, when the @attachOnSubscribe@ channel option is @false@, @#subscribe@ should respond in the same way as if would if an "@RTP6d@"#RTP6d implicit attach had been performed on an already-@ATTACHED@ channel (for example by returning a @null@ state change). * @(RTP7)@ @RealtimePresence#unsubscribe@ function: ** @(RTP7c)@ Unsubscribe with no arguments unsubscribes all listeners ** @(RTP7a)@ Unsubscribe with a single listener argument unsubscribes the listener if previously subscribed with an action-specific subscription