From a37a3277b58a2c3875fd8584d1799f145a633570 Mon Sep 17 00:00:00 2001 From: Peter Maguire Date: Mon, 30 May 2022 15:39:15 +0100 Subject: [PATCH 01/17] Initial commit with subscription filtering --- textile/features.textile | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/textile/features.textile b/textile/features.textile index 0547ba0c5..d937a16bd 100644 --- a/textile/features.textile +++ b/textile/features.textile @@ -599,6 +599,16 @@ h3(#realtime-channel). Channel ** @(RTL7d)@ Messages delivered are automatically decoded based on the @encoding@ attribute; see REST @Channel@ 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 @Realtime@ library constructor +** @(RTL7g)@ Subscribe with a dictionary argument subscribes a listener which filters which messages to accept based on the dictionary values +*** @(RTL7g1)@ An empty dictionary functions identically to "RTL7a":#RTL7a +*** @(RTL7g2)@ A dictionary with multiple key/value pairs should require each entry to be satisfied in order to accept the Message +*** @(RTL7g3)@ Keys currently must be one of @ref@ or @type@ or a negated version of these (@-ref@ and @-type@) +**** @(RTL7g3a)@ @ref@ and @type@ refer to @ref.timeserial@ and @ref.type@ in the Message body respectively +**** @(RTL7g3b)@ Consideration should be made to allow for easy expansion of the allowed fields here in the future +*** @(RTL7g4)@ Keys which are negated (starting with a @-@) should be treated as a NOT and not accept any Messages which match that value +*** @(RTL7g5)@ A value should be matched exactly, unless it is @*@ which should match any value that is not null +*** @(RTL7g6)@ A Message which matches multiple listeners should be sent to all matched listeners + * @(RTL8)@ @Channel#unsubscribe@ function: ** @(RTL8a)@ Unsubscribe with no arguments unsubscribes the provided listener to all messages if subscribed ** @(RTL8b)@ Unsubscribe with a single name argument unsubscribes the provided listener if previously subscribed with a name-specific subscription @@ -1730,11 +1740,14 @@ class RealtimeChannel: publish(name: String?, data: Data?) => io // RTL6i subscribe((Message) ->) => io // RTL7a subscribe(String, (Message) ->) => io // RTL7b + subscribe(Dict, (Message) ->) // RTL7g unsubscribe() // RTL8a, RTE5 unsubscribe((Message) ->) // RTL8a unsubscribe(String, (Message) ->) // RTL8a setOptions(options: ChannelOptions) => io // RTL16 + + class BatchOperations: publish([BatchSpec]) => BatchResult // BO2a publish(BatchSpec) => BatchResult // BO2a @@ -1886,6 +1899,10 @@ class ConnectionDetails: serverId: String // CD2g maxIdleInterval: Duration // CD2h +class MessageReference: + timeserial: string + type: string + class Message: constructor(name: String?, data: Data?) // TM2 constructor(name: String?, data: Data?, clientId: String?) // TM2 @@ -1899,6 +1916,7 @@ class Message: id: String // TM2a name: String? // TM2g timestamp: Time // TM2f + ref: MessageReference? class PresenceMessage +fromEncoded(JsonObject, ChannelOptions?) -> PresenceMessage // TP4 From 2e6f2cdc6d2f81e02040b32dd9c10c45b25cd768 Mon Sep 17 00:00:00 2001 From: Peter Maguire Date: Tue, 31 May 2022 12:24:06 +0100 Subject: [PATCH 02/17] Move message interaction object to extras and switch to function for subscribe --- textile/features.textile | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/textile/features.textile b/textile/features.textile index d937a16bd..f7d94a847 100644 --- a/textile/features.textile +++ b/textile/features.textile @@ -599,16 +599,7 @@ h3(#realtime-channel). Channel ** @(RTL7d)@ Messages delivered are automatically decoded based on the @encoding@ attribute; see REST @Channel@ 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 @Realtime@ library constructor -** @(RTL7g)@ Subscribe with a dictionary argument subscribes a listener which filters which messages to accept based on the dictionary values -*** @(RTL7g1)@ An empty dictionary functions identically to "RTL7a":#RTL7a -*** @(RTL7g2)@ A dictionary with multiple key/value pairs should require each entry to be satisfied in order to accept the Message -*** @(RTL7g3)@ Keys currently must be one of @ref@ or @type@ or a negated version of these (@-ref@ and @-type@) -**** @(RTL7g3a)@ @ref@ and @type@ refer to @ref.timeserial@ and @ref.type@ in the Message body respectively -**** @(RTL7g3b)@ Consideration should be made to allow for easy expansion of the allowed fields here in the future -*** @(RTL7g4)@ Keys which are negated (starting with a @-@) should be treated as a NOT and not accept any Messages which match that value -*** @(RTL7g5)@ A value should be matched exactly, unless it is @*@ which should match any value that is not null -*** @(RTL7g6)@ A Message which matches multiple listeners should be sent to all matched listeners - +** @(RTL7g)@ Subscribe with a function argument subscribes a listener which only fires when the function returns @true@ * @(RTL8)@ @Channel#unsubscribe@ function: ** @(RTL8a)@ Unsubscribe with no arguments unsubscribes the provided listener to all messages if subscribed ** @(RTL8b)@ Unsubscribe with a single name argument unsubscribes the provided listener if previously subscribed with a name-specific subscription @@ -1740,7 +1731,7 @@ class RealtimeChannel: publish(name: String?, data: Data?) => io // RTL6i subscribe((Message) ->) => io // RTL7a subscribe(String, (Message) ->) => io // RTL7b - subscribe(Dict, (Message) ->) // RTL7g + subscribe((Message) -> Bool, (Message) ->) // RTL7g unsubscribe() // RTL8a, RTE5 unsubscribe((Message) ->) // RTL8a unsubscribe(String, (Message) ->) // RTL8a @@ -1899,10 +1890,6 @@ class ConnectionDetails: serverId: String // CD2g maxIdleInterval: Duration // CD2h -class MessageReference: - timeserial: string - type: string - class Message: constructor(name: String?, data: Data?) // TM2 constructor(name: String?, data: Data?, clientId: String?) // TM2 @@ -1916,7 +1903,6 @@ class Message: id: String // TM2a name: String? // TM2g timestamp: Time // TM2f - ref: MessageReference? class PresenceMessage +fromEncoded(JsonObject, ChannelOptions?) -> PresenceMessage // TP4 @@ -2159,6 +2145,10 @@ class VCDiffDecoder class DeltaExtras from: String // the id of the message the delta was generated from format: String //the delta format. Only vcdiff is supported as at API version 1.2 + +class InteractionExtras + timeserial: String + type: String ``` h2(#old-specs). Old specs From d5010f78c474cc8a2d35508c076bb3e00861bd99 Mon Sep 17 00:00:00 2001 From: Peter Maguire Date: Tue, 31 May 2022 12:24:06 +0100 Subject: [PATCH 03/17] Move message interaction object to extras and switch to function for subscribe --- textile/features.textile | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/textile/features.textile b/textile/features.textile index d937a16bd..cfb475172 100644 --- a/textile/features.textile +++ b/textile/features.textile @@ -599,16 +599,7 @@ h3(#realtime-channel). Channel ** @(RTL7d)@ Messages delivered are automatically decoded based on the @encoding@ attribute; see REST @Channel@ 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 @Realtime@ library constructor -** @(RTL7g)@ Subscribe with a dictionary argument subscribes a listener which filters which messages to accept based on the dictionary values -*** @(RTL7g1)@ An empty dictionary functions identically to "RTL7a":#RTL7a -*** @(RTL7g2)@ A dictionary with multiple key/value pairs should require each entry to be satisfied in order to accept the Message -*** @(RTL7g3)@ Keys currently must be one of @ref@ or @type@ or a negated version of these (@-ref@ and @-type@) -**** @(RTL7g3a)@ @ref@ and @type@ refer to @ref.timeserial@ and @ref.type@ in the Message body respectively -**** @(RTL7g3b)@ Consideration should be made to allow for easy expansion of the allowed fields here in the future -*** @(RTL7g4)@ Keys which are negated (starting with a @-@) should be treated as a NOT and not accept any Messages which match that value -*** @(RTL7g5)@ A value should be matched exactly, unless it is @*@ which should match any value that is not null -*** @(RTL7g6)@ A Message which matches multiple listeners should be sent to all matched listeners - +** @(RTL7g)@ Subscribe with a function argument subscribes a listener which only fires when the function returns @true@ * @(RTL8)@ @Channel#unsubscribe@ function: ** @(RTL8a)@ Unsubscribe with no arguments unsubscribes the provided listener to all messages if subscribed ** @(RTL8b)@ Unsubscribe with a single name argument unsubscribes the provided listener if previously subscribed with a name-specific subscription @@ -1740,7 +1731,7 @@ class RealtimeChannel: publish(name: String?, data: Data?) => io // RTL6i subscribe((Message) ->) => io // RTL7a subscribe(String, (Message) ->) => io // RTL7b - subscribe(Dict, (Message) ->) // RTL7g + subscribe((Message) -> Bool, (Message) ->) // RTL7g unsubscribe() // RTL8a, RTE5 unsubscribe((Message) ->) // RTL8a unsubscribe(String, (Message) ->) // RTL8a @@ -1899,10 +1890,6 @@ class ConnectionDetails: serverId: String // CD2g maxIdleInterval: Duration // CD2h -class MessageReference: - timeserial: string - type: string - class Message: constructor(name: String?, data: Data?) // TM2 constructor(name: String?, data: Data?, clientId: String?) // TM2 @@ -1916,7 +1903,6 @@ class Message: id: String // TM2a name: String? // TM2g timestamp: Time // TM2f - ref: MessageReference? class PresenceMessage +fromEncoded(JsonObject, ChannelOptions?) -> PresenceMessage // TP4 @@ -2159,6 +2145,10 @@ class VCDiffDecoder class DeltaExtras from: String // the id of the message the delta was generated from format: String //the delta format. Only vcdiff is supported as at API version 1.2 + +class InteractionExtras: + timeserial: String + type: String ``` h2(#old-specs). Old specs From 28d3b7329fafbee975d0e1f01e86fc6f4e9aedab Mon Sep 17 00:00:00 2001 From: Peter Maguire Date: Wed, 8 Jun 2022 10:33:22 +0100 Subject: [PATCH 04/17] Update content/client-lib-development-guide/features.textile Co-authored-by: Owen Pearson <48608556+owenpearson@users.noreply.github.com> --- textile/features.textile | 2 -- 1 file changed, 2 deletions(-) diff --git a/textile/features.textile b/textile/features.textile index f7d94a847..853d1d9a3 100644 --- a/textile/features.textile +++ b/textile/features.textile @@ -1737,8 +1737,6 @@ class RealtimeChannel: unsubscribe(String, (Message) ->) // RTL8a setOptions(options: ChannelOptions) => io // RTL16 - - class BatchOperations: publish([BatchSpec]) => BatchResult // BO2a publish(BatchSpec) => BatchResult // BO2a From ac6fcaa7fed4f4754f4f32c0c0e1bb5e1613aadd Mon Sep 17 00:00:00 2001 From: Peter Maguire Date: Mon, 13 Jun 2022 15:15:56 +0100 Subject: [PATCH 05/17] Update to use more generic spec wording + filter object --- textile/features.textile | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/textile/features.textile b/textile/features.textile index 04c42aa54..5e5c580b9 100644 --- a/textile/features.textile +++ b/textile/features.textile @@ -599,7 +599,6 @@ h3(#realtime-channel). Channel ** @(RTL7d)@ Messages delivered are automatically decoded based on the @encoding@ attribute; see REST @Channel@ 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 @Realtime@ library constructor -** @(RTL7g)@ Subscribe with a function argument subscribes a listener which only fires when the function returns @true@ * @(RTL8)@ @Channel#unsubscribe@ function: ** @(RTL8a)@ Unsubscribe with no arguments unsubscribes the provided listener to all messages if subscribed ** @(RTL8b)@ Unsubscribe with a single name argument unsubscribes the provided listener if previously subscribed with a name-specific subscription @@ -631,6 +630,10 @@ h3(#realtime-channel). Channel ** @(RTL19c)@ In the case of a delta message with a @vcdiff@ @encoding@ step, the @vcdiff@ decoder must be used to decode the base payload of the of delta message, applying that delta to the stored base payload. The direct result of that vcdiff delta application, before performing any further decoding steps, is stored as the updated base payload. * @(RTL20)@ The @id@ of the last received message on each channel must be stored along with the base payload. When processing a delta message (i.e. one whose @encoding@ contains @vcdiff@ step) the stored last message @id@ must be compared against the delta reference @id@, indicated in the @Message.extras.delta.from@ field of the delta message. If the delta reference @id@ of the received delta message does not equal the stored @id@ corresponding to the base payload, the message decoding must fail. The recovery procedure from "RTL18":#RTL18 must be executed. * @(RTL21)@ The messages in the @messages@ array of a @ProtocolMessage@ should each be decoded in ascending order of their index in the array. +* @(RTL22)@ A method must be provided for creating a listener which only fires when the message matches a set of criteria +** @(RTL22a)@ The method must allow for filters matching one or more of: @extras.refId@, @extras.refType@ or @name@ +** @(RTL22b)@ The method must allow for matching only messages which contain no @extras.refId@ +** @(RTL22c)@ If multiple filters are supplied, each must be satisfied to fire the listener h3(#realtime-presence). Presence @@ -1731,12 +1734,18 @@ class RealtimeChannel: publish(name: String?, data: Data?) => io // RTL6i subscribe((Message) ->) => io // RTL7a subscribe(String, (Message) ->) => io // RTL7b - subscribe((Message) -> Bool, (Message) ->) // RTL7g + subscribe(FilterObject, (Message) ->) // RTL22 unsubscribe() // RTL8a, RTE5 unsubscribe((Message) ->) // RTL8a unsubscribe(String, (Message) ->) // RTL8a setOptions(options: ChannelOptions) => io // RTL16 +class FilterObject: + references: bool // RTL22b + refId: string // RTL22a + refType: string // RTL22a + name: string // RTL22a + class BatchOperations: publish([BatchSpec]) => BatchResult // BO2a publish(BatchSpec) => BatchResult // BO2a From d9d23835eaa3d0fa0a3fabc8eccfcc81c5df47ab Mon Sep 17 00:00:00 2001 From: Peter Maguire Date: Tue, 14 Jun 2022 15:24:12 +0100 Subject: [PATCH 06/17] Changes to wording and type names --- textile/features.textile | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/textile/features.textile b/textile/features.textile index 5e5c580b9..65434c9a5 100644 --- a/textile/features.textile +++ b/textile/features.textile @@ -1173,7 +1173,7 @@ h4. Message ** @(TM2g)@ @name@ string ** @(TM2d)@ @data@ string, buffer or JSON-encodable object or array ** @(TM2e)@ @encoding@ string -** @(TM2i)@ @extras@ JSON-encodable object, used to contain any arbitrary key value pairs which may also contain other primitive JSON types, JSON-encodable objects or JSON-encodable arrays. The @extras@ field is provided to contain message metadata and/or ancillary payloads in support of specific functionality, e.g. push. Each of these supported extensions is documented separately; for 1.1 the only supported extension is @push@, via the @extras.push@ member; 1.2 adds the @delta@ extension which is of type @DeltaExtras@, and the @headers@ extension, which contains arbitrary @string->string@ key-value pairs, settable at publish time. Unless otherwise specified, the client library should not attempt to do any filtering or validation of the @extras@ field itself, but should treat it opaquely, encoding it and passing it to realtime unaltered. +** @(TM2i)@ @extras@ JSON-encodable object, used to contain any arbitrary key value pairs which may also contain other primitive JSON types, JSON-encodable objects or JSON-encodable arrays. The @extras@ field is provided to contain message metadata and/or ancillary payloads in support of specific functionality, e.g. push. Each of these supported extensions is documented separately; for 1.1 the only supported extension is @push@, via the @extras.push@ member; 1.2 adds the @delta@ extension which is of type @DeltaExtras@, the @headers@ extension, which contains arbitrary @string->string@ key-value pairs, settable at publish time, and @refs@ which is of type @InteractionExtras@. Unless otherwise specified, the client library should not attempt to do any filtering or validation of the @extras@ field itself, but should treat it opaquely, encoding it and passing it to realtime unaltered. ** @(TM2f)@ @timestamp@ time in milliseconds since epoch. If a message received from Ably does not contain a @timestamp@, it should be set to the @timestamp@ of the encapsulating @ProtocolMessage@ * @(TM3)@ @fromEncoded@ and @fromEncodedArray@ are alternative constructors that take an (already deserialized) @Message@-like object (or array of such objects), and optionally a @channelOptions@, and return a @Message@ (or array of such @Messages@) that's decoded and decrypted as specified in @RSL6@, using the cipher in the @channelOptions@ if the message is encrypted, with any residual transforms (ones that the library cannot decode or decrypt) left in the @encoding@ property per @RSL6b@. This is intended for users receiving messages other than from a REST or Realtime channel (for example, from a queue), to avoid them having to parse the @encoding@ string themselves. @@ -1734,14 +1734,15 @@ class RealtimeChannel: publish(name: String?, data: Data?) => io // RTL6i subscribe((Message) ->) => io // RTL7a subscribe(String, (Message) ->) => io // RTL7b - subscribe(FilterObject, (Message) ->) // RTL22 + subscribe(MessageFilterObject, (Message) ->) // RTL22 unsubscribe() // RTL8a, RTE5 unsubscribe((Message) ->) // RTL8a unsubscribe(String, (Message) ->) // RTL8a + unsubscribe(MessageFilterObject, (Message) ->) setOptions(options: ChannelOptions) => io // RTL16 -class FilterObject: - references: bool // RTL22b +class MessageFilterObject: + hasRef: bool // RTL22b refId: string // RTL22a refType: string // RTL22a name: string // RTL22a From 8620ef94dfaf5f71a84dfc92e281b73dc358ffec Mon Sep 17 00:00:00 2001 From: Peter Maguire Date: Tue, 14 Jun 2022 15:34:59 +0100 Subject: [PATCH 07/17] rename extras ref field --- textile/features.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/textile/features.textile b/textile/features.textile index 65434c9a5..965ecb08f 100644 --- a/textile/features.textile +++ b/textile/features.textile @@ -1173,7 +1173,7 @@ h4. Message ** @(TM2g)@ @name@ string ** @(TM2d)@ @data@ string, buffer or JSON-encodable object or array ** @(TM2e)@ @encoding@ string -** @(TM2i)@ @extras@ JSON-encodable object, used to contain any arbitrary key value pairs which may also contain other primitive JSON types, JSON-encodable objects or JSON-encodable arrays. The @extras@ field is provided to contain message metadata and/or ancillary payloads in support of specific functionality, e.g. push. Each of these supported extensions is documented separately; for 1.1 the only supported extension is @push@, via the @extras.push@ member; 1.2 adds the @delta@ extension which is of type @DeltaExtras@, the @headers@ extension, which contains arbitrary @string->string@ key-value pairs, settable at publish time, and @refs@ which is of type @InteractionExtras@. Unless otherwise specified, the client library should not attempt to do any filtering or validation of the @extras@ field itself, but should treat it opaquely, encoding it and passing it to realtime unaltered. +** @(TM2i)@ @extras@ JSON-encodable object, used to contain any arbitrary key value pairs which may also contain other primitive JSON types, JSON-encodable objects or JSON-encodable arrays. The @extras@ field is provided to contain message metadata and/or ancillary payloads in support of specific functionality, e.g. push. Each of these supported extensions is documented separately; for 1.1 the only supported extension is @push@, via the @extras.push@ member; 1.2 adds the @delta@ extension which is of type @DeltaExtras@, the @headers@ extension, which contains arbitrary @string->string@ key-value pairs, settable at publish time, and @reference@ which is of type @InteractionExtras@. Unless otherwise specified, the client library should not attempt to do any filtering or validation of the @extras@ field itself, but should treat it opaquely, encoding it and passing it to realtime unaltered. ** @(TM2f)@ @timestamp@ time in milliseconds since epoch. If a message received from Ably does not contain a @timestamp@, it should be set to the @timestamp@ of the encapsulating @ProtocolMessage@ * @(TM3)@ @fromEncoded@ and @fromEncodedArray@ are alternative constructors that take an (already deserialized) @Message@-like object (or array of such objects), and optionally a @channelOptions@, and return a @Message@ (or array of such @Messages@) that's decoded and decrypted as specified in @RSL6@, using the cipher in the @channelOptions@ if the message is encrypted, with any residual transforms (ones that the library cannot decode or decrypt) left in the @encoding@ property per @RSL6b@. This is intended for users receiving messages other than from a REST or Realtime channel (for example, from a queue), to avoid them having to parse the @encoding@ string themselves. From f08e097b21b6b1240e1043a48597959063bb831e Mon Sep 17 00:00:00 2001 From: Peter Maguire Date: Tue, 14 Jun 2022 16:43:25 +0100 Subject: [PATCH 08/17] update spec to ensure a method exists to remove a listener --- textile/features.textile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/textile/features.textile b/textile/features.textile index 965ecb08f..6b6dee15c 100644 --- a/textile/features.textile +++ b/textile/features.textile @@ -630,9 +630,9 @@ h3(#realtime-channel). Channel ** @(RTL19c)@ In the case of a delta message with a @vcdiff@ @encoding@ step, the @vcdiff@ decoder must be used to decode the base payload of the of delta message, applying that delta to the stored base payload. The direct result of that vcdiff delta application, before performing any further decoding steps, is stored as the updated base payload. * @(RTL20)@ The @id@ of the last received message on each channel must be stored along with the base payload. When processing a delta message (i.e. one whose @encoding@ contains @vcdiff@ step) the stored last message @id@ must be compared against the delta reference @id@, indicated in the @Message.extras.delta.from@ field of the delta message. If the delta reference @id@ of the received delta message does not equal the stored @id@ corresponding to the base payload, the message decoding must fail. The recovery procedure from "RTL18":#RTL18 must be executed. * @(RTL21)@ The messages in the @messages@ array of a @ProtocolMessage@ should each be decoded in ascending order of their index in the array. -* @(RTL22)@ A method must be provided for creating a listener which only fires when the message matches a set of criteria -** @(RTL22a)@ The method must allow for filters matching one or more of: @extras.refId@, @extras.refType@ or @name@ -** @(RTL22b)@ The method must allow for matching only messages which contain no @extras.refId@ +* @(RTL22)@ Methods must be provided for creating and destroying a listener which only fires when the message matches a set of criteria +** @(RTL22a)@ The method must allow for filters matching one or more of: @extras.reference.id@, @extras.reference.type@ or @name@ +** @(RTL22b)@ The method must allow for matching only messages which contain no @extras.reference.type@ ** @(RTL22c)@ If multiple filters are supplied, each must be satisfied to fire the listener h3(#realtime-presence). Presence @@ -1738,7 +1738,7 @@ class RealtimeChannel: unsubscribe() // RTL8a, RTE5 unsubscribe((Message) ->) // RTL8a unsubscribe(String, (Message) ->) // RTL8a - unsubscribe(MessageFilterObject, (Message) ->) + unsubscribe(MessageFilterObject, (Message) ->) // RTL22 setOptions(options: ChannelOptions) => io // RTL16 class MessageFilterObject: From b343e834e98b05d88834041c2a01b7241913e66e Mon Sep 17 00:00:00 2001 From: Peter Maguire Date: Fri, 24 Jun 2022 12:26:04 +0100 Subject: [PATCH 09/17] fix wording of has-ref condition --- textile/features.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/textile/features.textile b/textile/features.textile index 6b6dee15c..c65754dc9 100644 --- a/textile/features.textile +++ b/textile/features.textile @@ -632,7 +632,7 @@ h3(#realtime-channel). Channel * @(RTL21)@ The messages in the @messages@ array of a @ProtocolMessage@ should each be decoded in ascending order of their index in the array. * @(RTL22)@ Methods must be provided for creating and destroying a listener which only fires when the message matches a set of criteria ** @(RTL22a)@ The method must allow for filters matching one or more of: @extras.reference.id@, @extras.reference.type@ or @name@ -** @(RTL22b)@ The method must allow for matching only messages which contain no @extras.reference.type@ +** @(RTL22b)@ The method must allow for matching only messages which do not have @extras.reference@ ** @(RTL22c)@ If multiple filters are supplied, each must be satisfied to fire the listener h3(#realtime-presence). Presence From 044c578968c2a5b814a54c7091756071656cf33a Mon Sep 17 00:00:00 2001 From: Peter Maguire Date: Fri, 24 Jun 2022 12:45:27 +0100 Subject: [PATCH 10/17] Change hasRef to isRef to clarify it's usage --- textile/features.textile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/textile/features.textile b/textile/features.textile index c65754dc9..1091d3c03 100644 --- a/textile/features.textile +++ b/textile/features.textile @@ -1734,15 +1734,15 @@ class RealtimeChannel: publish(name: String?, data: Data?) => io // RTL6i subscribe((Message) ->) => io // RTL7a subscribe(String, (Message) ->) => io // RTL7b - subscribe(MessageFilterObject, (Message) ->) // RTL22 + subscribe(MessageFilter, (Message) ->) // RTL22 unsubscribe() // RTL8a, RTE5 unsubscribe((Message) ->) // RTL8a unsubscribe(String, (Message) ->) // RTL8a - unsubscribe(MessageFilterObject, (Message) ->) // RTL22 + unsubscribe(MessageFilter, (Message) ->) // RTL22 setOptions(options: ChannelOptions) => io // RTL16 -class MessageFilterObject: - hasRef: bool // RTL22b +class MessageFilter: + isRef: bool // RTL22b refId: string // RTL22a refType: string // RTL22a name: string // RTL22a From a3d63dff745d3e0ed97a13f4e067e61a23fcc9b2 Mon Sep 17 00:00:00 2001 From: Peter Maguire Date: Fri, 24 Jun 2022 17:10:01 +0100 Subject: [PATCH 11/17] InteractionExtras -> ReferenceExtras for clarity --- textile/features.textile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/textile/features.textile b/textile/features.textile index 1091d3c03..2bd113551 100644 --- a/textile/features.textile +++ b/textile/features.textile @@ -1173,7 +1173,7 @@ h4. Message ** @(TM2g)@ @name@ string ** @(TM2d)@ @data@ string, buffer or JSON-encodable object or array ** @(TM2e)@ @encoding@ string -** @(TM2i)@ @extras@ JSON-encodable object, used to contain any arbitrary key value pairs which may also contain other primitive JSON types, JSON-encodable objects or JSON-encodable arrays. The @extras@ field is provided to contain message metadata and/or ancillary payloads in support of specific functionality, e.g. push. Each of these supported extensions is documented separately; for 1.1 the only supported extension is @push@, via the @extras.push@ member; 1.2 adds the @delta@ extension which is of type @DeltaExtras@, the @headers@ extension, which contains arbitrary @string->string@ key-value pairs, settable at publish time, and @reference@ which is of type @InteractionExtras@. Unless otherwise specified, the client library should not attempt to do any filtering or validation of the @extras@ field itself, but should treat it opaquely, encoding it and passing it to realtime unaltered. +** @(TM2i)@ @extras@ JSON-encodable object, used to contain any arbitrary key value pairs which may also contain other primitive JSON types, JSON-encodable objects or JSON-encodable arrays. The @extras@ field is provided to contain message metadata and/or ancillary payloads in support of specific functionality, e.g. push. Each of these supported extensions is documented separately; for 1.1 the only supported extension is @push@, via the @extras.push@ member; 1.2 adds the @delta@ extension which is of type @DeltaExtras@, the @headers@ extension, which contains arbitrary @string->string@ key-value pairs, settable at publish time, and @reference@ which is of type @ReferenceExtras@. Unless otherwise specified, the client library should not attempt to do any filtering or validation of the @extras@ field itself, but should treat it opaquely, encoding it and passing it to realtime unaltered. ** @(TM2f)@ @timestamp@ time in milliseconds since epoch. If a message received from Ably does not contain a @timestamp@, it should be set to the @timestamp@ of the encapsulating @ProtocolMessage@ * @(TM3)@ @fromEncoded@ and @fromEncodedArray@ are alternative constructors that take an (already deserialized) @Message@-like object (or array of such objects), and optionally a @channelOptions@, and return a @Message@ (or array of such @Messages@) that's decoded and decrypted as specified in @RSL6@, using the cipher in the @channelOptions@ if the message is encrypted, with any residual transforms (ones that the library cannot decode or decrypt) left in the @encoding@ property per @RSL6b@. This is intended for users receiving messages other than from a REST or Realtime channel (for example, from a queue), to avoid them having to parse the @encoding@ string themselves. @@ -2154,7 +2154,7 @@ class DeltaExtras from: String // the id of the message the delta was generated from format: String //the delta format. Only vcdiff is supported as at API version 1.2 -class InteractionExtras: +class ReferenceExtras: timeserial: String type: String ``` From ba79c67b7c58ca6496da4c201e6b3745e7eb53fa Mon Sep 17 00:00:00 2001 From: Peter Maguire Date: Mon, 27 Jun 2022 13:08:26 +0100 Subject: [PATCH 12/17] Use timeserial instead of ID --- textile/features.textile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/textile/features.textile b/textile/features.textile index 2bd113551..e2954aa18 100644 --- a/textile/features.textile +++ b/textile/features.textile @@ -631,8 +631,8 @@ h3(#realtime-channel). Channel * @(RTL20)@ The @id@ of the last received message on each channel must be stored along with the base payload. When processing a delta message (i.e. one whose @encoding@ contains @vcdiff@ step) the stored last message @id@ must be compared against the delta reference @id@, indicated in the @Message.extras.delta.from@ field of the delta message. If the delta reference @id@ of the received delta message does not equal the stored @id@ corresponding to the base payload, the message decoding must fail. The recovery procedure from "RTL18":#RTL18 must be executed. * @(RTL21)@ The messages in the @messages@ array of a @ProtocolMessage@ should each be decoded in ascending order of their index in the array. * @(RTL22)@ Methods must be provided for creating and destroying a listener which only fires when the message matches a set of criteria -** @(RTL22a)@ The method must allow for filters matching one or more of: @extras.reference.id@, @extras.reference.type@ or @name@ -** @(RTL22b)@ The method must allow for matching only messages which do not have @extras.reference@ +** @(RTL22a)@ The method must allow for filters matching one or more of: @extras.ref.timeserial@, @extras.ref.type@ or @name@ +** @(RTL22b)@ The method must allow for matching only messages which do not have @extras.ref@ ** @(RTL22c)@ If multiple filters are supplied, each must be satisfied to fire the listener h3(#realtime-presence). Presence @@ -1743,7 +1743,7 @@ class RealtimeChannel: class MessageFilter: isRef: bool // RTL22b - refId: string // RTL22a + refTimeserial: string // RTL22a refType: string // RTL22a name: string // RTL22a From 031cd7570446669b8c9cc83580d89768f0545441 Mon Sep 17 00:00:00 2001 From: Peter Maguire Date: Tue, 28 Jun 2022 10:39:18 +0100 Subject: [PATCH 13/17] Update content/client-lib-development-guide/features.textile Co-authored-by: Owen Pearson <48608556+owenpearson@users.noreply.github.com> --- textile/features.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/textile/features.textile b/textile/features.textile index e2954aa18..44fbd1b60 100644 --- a/textile/features.textile +++ b/textile/features.textile @@ -630,7 +630,7 @@ h3(#realtime-channel). Channel ** @(RTL19c)@ In the case of a delta message with a @vcdiff@ @encoding@ step, the @vcdiff@ decoder must be used to decode the base payload of the of delta message, applying that delta to the stored base payload. The direct result of that vcdiff delta application, before performing any further decoding steps, is stored as the updated base payload. * @(RTL20)@ The @id@ of the last received message on each channel must be stored along with the base payload. When processing a delta message (i.e. one whose @encoding@ contains @vcdiff@ step) the stored last message @id@ must be compared against the delta reference @id@, indicated in the @Message.extras.delta.from@ field of the delta message. If the delta reference @id@ of the received delta message does not equal the stored @id@ corresponding to the base payload, the message decoding must fail. The recovery procedure from "RTL18":#RTL18 must be executed. * @(RTL21)@ The messages in the @messages@ array of a @ProtocolMessage@ should each be decoded in ascending order of their index in the array. -* @(RTL22)@ Methods must be provided for creating and destroying a listener which only fires when the message matches a set of criteria +* @(RTL22)@ Methods must be provided for attaching and removing a listener which only executes when the message matches a set of criteria ** @(RTL22a)@ The method must allow for filters matching one or more of: @extras.ref.timeserial@, @extras.ref.type@ or @name@ ** @(RTL22b)@ The method must allow for matching only messages which do not have @extras.ref@ ** @(RTL22c)@ If multiple filters are supplied, each must be satisfied to fire the listener From 49f03d3d9bf682811fba66f1b6f43eb03447dacf Mon Sep 17 00:00:00 2001 From: Peter Maguire Date: Tue, 28 Jun 2022 15:16:58 +0100 Subject: [PATCH 14/17] Improve wording and add recommendation for MessageFilter object --- textile/features.textile | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/textile/features.textile b/textile/features.textile index 44fbd1b60..1b29c68d5 100644 --- a/textile/features.textile +++ b/textile/features.textile @@ -630,10 +630,11 @@ h3(#realtime-channel). Channel ** @(RTL19c)@ In the case of a delta message with a @vcdiff@ @encoding@ step, the @vcdiff@ decoder must be used to decode the base payload of the of delta message, applying that delta to the stored base payload. The direct result of that vcdiff delta application, before performing any further decoding steps, is stored as the updated base payload. * @(RTL20)@ The @id@ of the last received message on each channel must be stored along with the base payload. When processing a delta message (i.e. one whose @encoding@ contains @vcdiff@ step) the stored last message @id@ must be compared against the delta reference @id@, indicated in the @Message.extras.delta.from@ field of the delta message. If the delta reference @id@ of the received delta message does not equal the stored @id@ corresponding to the base payload, the message decoding must fail. The recovery procedure from "RTL18":#RTL18 must be executed. * @(RTL21)@ The messages in the @messages@ array of a @ProtocolMessage@ should each be decoded in ascending order of their index in the array. -* @(RTL22)@ Methods must be provided for attaching and removing a listener which only executes when the message matches a set of criteria -** @(RTL22a)@ The method must allow for filters matching one or more of: @extras.ref.timeserial@, @extras.ref.type@ or @name@ -** @(RTL22b)@ The method must allow for matching only messages which do not have @extras.ref@ -** @(RTL22c)@ If multiple filters are supplied, each must be satisfied to fire the listener +* @(RTL22)@ Methods must be provided for attaching and removing a listener which only executes when the message matches a set of criteria. +** @(RTL22a)@ The method must allow for filters matching one or more of: @extras.ref.timeserial@, @extras.ref.type@ or @name@. +** @(RTL22b)@ The method must allow for matching only messages which do not have @extras.ref@. +** @(RTL22c)@ The listener must only execute if all criteria defined in the provided @MessageFilter@ object are met. +** @(RTL22d)@ The method should use the @MessageFilter@ object if possible and idiomatic for the language. h3(#realtime-presence). Presence From cc824e1907744462eb72e5a1c9610c489d6180e0 Mon Sep 17 00:00:00 2001 From: Peter Maguire Date: Wed, 29 Jun 2022 11:02:37 +0100 Subject: [PATCH 15/17] Remove contradictory MessageFilter reference Co-authored-by: Owen Pearson <48608556+owenpearson@users.noreply.github.com> --- textile/features.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/textile/features.textile b/textile/features.textile index 6e201813e..ab5f1c3a7 100644 --- a/textile/features.textile +++ b/textile/features.textile @@ -633,7 +633,7 @@ h3(#realtime-channel). RealtimeChannel * @(RTL22)@ Methods must be provided for attaching and removing a listener which only executes when the message matches a set of criteria. ** @(RTL22a)@ The method must allow for filters matching one or more of: @extras.ref.timeserial@, @extras.ref.type@ or @name@. ** @(RTL22b)@ The method must allow for matching only messages which do not have @extras.ref@. -** @(RTL22c)@ The listener must only execute if all criteria defined in the provided @MessageFilter@ object are met. +** @(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. h3(#realtime-presence). RealtimePresence From 35a316fe8e27b7086e8c12351fc59dff6dc1faba Mon Sep 17 00:00:00 2001 From: Peter Maguire Date: Fri, 1 Jul 2022 12:03:11 +0100 Subject: [PATCH 16/17] Change reference to ref in extras spec --- textile/features.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/textile/features.textile b/textile/features.textile index ab5f1c3a7..7f0b5d6b2 100644 --- a/textile/features.textile +++ b/textile/features.textile @@ -1179,7 +1179,7 @@ h4. Message ** @(TM2g)@ @name@ string ** @(TM2d)@ @data@ string, buffer or JSON-encodable object or array ** @(TM2e)@ @encoding@ string -** @(TM2i)@ @extras@ JSON-encodable object, used to contain any arbitrary key value pairs which may also contain other primitive JSON types, JSON-encodable objects or JSON-encodable arrays. The @extras@ field is provided to contain message metadata and/or ancillary payloads in support of specific functionality, e.g. push. Each of these supported extensions is documented separately; for 1.1 the only supported extension is @push@, via the @extras.push@ member; 1.2 adds the @delta@ extension which is of type @DeltaExtras@, the @headers@ extension, which contains arbitrary @string->string@ key-value pairs, settable at publish time, and @reference@ which is of type @ReferenceExtras@. Unless otherwise specified, the client library should not attempt to do any filtering or validation of the @extras@ field itself, but should treat it opaquely, encoding it and passing it to realtime unaltered. +** @(TM2i)@ @extras@ JSON-encodable object, used to contain any arbitrary key value pairs which may also contain other primitive JSON types, JSON-encodable objects or JSON-encodable arrays. The @extras@ field is provided to contain message metadata and/or ancillary payloads in support of specific functionality, e.g. push. Each of these supported extensions is documented separately; for 1.1 the only supported extension is @push@, via the @extras.push@ member; 1.2 adds the @delta@ extension which is of type @DeltaExtras@, the @headers@ extension, which contains arbitrary @string->string@ key-value pairs, settable at publish time, and @ref@ which is of type @ReferenceExtras@. Unless otherwise specified, the client library should not attempt to do any filtering or validation of the @extras@ field itself, but should treat it opaquely, encoding it and passing it to realtime unaltered. ** @(TM2f)@ @timestamp@ time in milliseconds since epoch. If a message received from Ably does not contain a @timestamp@, it should be set to the @timestamp@ of the encapsulating @ProtocolMessage@ * @(TM3)@ @fromEncoded@ and @fromEncodedArray@ are alternative constructors that take an (already deserialized) @Message@-like object (or array of such objects), and optionally a @channelOptions@, and return a @Message@ (or array of such @Messages@) that's decoded and decrypted as specified in @RSL6@, using the cipher in the @channelOptions@ if the message is encrypted, with any residual transforms (ones that the library cannot decode or decrypt) left in the @encoding@ property per @RSL6b@. This is intended for users receiving messages other than from a REST or Realtime channel (for example, from a queue), to avoid them having to parse the @encoding@ string themselves. From a7e560e432fabf1d17b652a32f2152398782f082 Mon Sep 17 00:00:00 2001 From: Peter Maguire Date: Fri, 1 Jul 2022 12:53:14 +0100 Subject: [PATCH 17/17] Add spec points for ReferenceExtras and MessageFilters --- textile/features.textile | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/textile/features.textile b/textile/features.textile index 7f0b5d6b2..d17778f15 100644 --- a/textile/features.textile +++ b/textile/features.textile @@ -631,7 +631,7 @@ h3(#realtime-channel). RealtimeChannel * @(RTL20)@ The @id@ of the last received message on each channel must be stored along with the base payload. When processing a delta message (i.e. one whose @encoding@ contains @vcdiff@ step) the stored last message @id@ must be compared against the delta reference @id@, indicated in the @Message.extras.delta.from@ field of the delta message. If the delta reference @id@ of the received delta message does not equal the stored @id@ corresponding to the base payload, the message decoding must fail. The recovery procedure from "RTL18":#RTL18 must be executed. * @(RTL21)@ The messages in the @messages@ array of a @ProtocolMessage@ should each be decoded in ascending order of their index in the array. * @(RTL22)@ Methods must be provided for attaching and removing a listener which only executes when the message matches a set of criteria. -** @(RTL22a)@ The method must allow for filters matching one or more of: @extras.ref.timeserial@, @extras.ref.type@ or @name@. +** @(RTL22a)@ The method must allow for filters matching one or more of: @extras.ref.timeserial@, @extras.ref.type@ or @name@. See #MFI1 for an object implementation. ** @(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. @@ -1415,6 +1415,21 @@ h4. BatchPresence ** @(PBE2b)@ @action@ - identical to #TP3b - null if @error@ is present ** @(PBE2c)@ @error@ - an @ErrorInfo@ object representing the failure reason for this channel - null if @action@ is present +h4. MessageFilter +* @(MFI1)@ Supplies filter options to subscribe as defined in #RTL22 +* @(MFI2)@ Contains the following attributes: +** @(MFI2a)@ @isRef@ - A boolean for checking if a message contains an @extras.ref@ field +** @(MFI2b)@ @refTimeserial@ - A string for checking if a message's @extras.ref.timeserial@ matches the supplied value +** @(MFI2c)@ @refType@ - A string for checking if a message's @extras.ref.type@ matches the supplied value +** @(MFI2d)@ @name@ - A string for checking if a message's @name@ matches the supplied value + +h4. ReferenceExtras +* @(REX1)@ Is an object attached to the @extras@ field of a message to reference a previous message. +* @(REX2)@ Contains the following fields: +** @(REX2a)@ @timeserial@ - The @timeserial@ of the message being referenced +** @(REX2b)@ @type@ - The type of reference, user defined +*** @(REX2b1)@ Should be written in reverse domain name notation +*** @(REX2b2)@ Types beginning with @com.ably.@ are reserved h3(#options). Option types @@ -1764,11 +1779,11 @@ class RealtimeChannel: unsubscribe(MessageFilter, (Message) ->) // RTL22 setOptions(options: ChannelOptions) => io // RTL16 -class MessageFilter: - isRef: bool // RTL22b - refTimeserial: string // RTL22a - refType: string // RTL22a - name: string // RTL22a +class MessageFilter: // RTL22a + isRef: bool // MFI2a + refTimeserial: string // MFI2b + refType: string // MFI2c + name: string // MFI2d class ChannelProperties: attachSerial: String // CP2a @@ -2185,8 +2200,9 @@ class DeltaExtras format: String //the delta format. Only vcdiff is supported as at API version 1.2 class ReferenceExtras: - timeserial: String - type: String + timeserial: String // REX2a + type: String //REX2b + ``` h2(#old-specs). Old specs