From 41cc3be3da5e0d88b47bde805e3ededd23874a41 Mon Sep 17 00:00:00 2001 From: Matt Kaschula Date: Tue, 27 Jan 2026 10:40:01 +0000 Subject: [PATCH] docs: Add notification inband mode for LiveObjects Document the new `notification` inband mode for LiveObjects which notifies clients when objects operations are received without sending the full state data. --- src/pages/docs/liveobjects/inband-objects.mdx | 155 +++++++++++++++++- 1 file changed, 146 insertions(+), 9 deletions(-) diff --git a/src/pages/docs/liveobjects/inband-objects.mdx b/src/pages/docs/liveobjects/inband-objects.mdx index ca30536478..d4c1d74d4a 100644 --- a/src/pages/docs/liveobjects/inband-objects.mdx +++ b/src/pages/docs/liveobjects/inband-objects.mdx @@ -37,16 +37,27 @@ If you're using LiveObjects from one of the the following languages, then use th Inband objects works by delivering changes to channel objects as regular channel messages, similar to [inband occupancy](/docs/channels/options#occupancy). +There are two inband modes available: + +| Mode | Description | +| --- | --- | +| `objects` | Sends the full state of all objects on the channel. Delivers an initial state snapshot on attach and sends updates whenever an object operation is applied. | +| `notification` | Sends a notification when an object operation has been received, without the full state data. Clients can then fetch the current state via the REST API. Does not send an initial state on attach. | + ## Enable Inband Objects -To enable inband objects, use the `objects` [channel parameter](/docs/channels/options#objects) when getting a channel: +To enable inband objects, use the `objects` [channel parameter](/docs/channels/options#objects) when getting a channel. Set the value to either `objects` or `notification` depending on which mode you want to use: ```javascript -// When getting a channel instance +// Enable full state sync mode const channelOpts = { params: { objects: 'objects' } }; const channel = realtime.channels.get('my-channel', channelOpts); +// Or enable notification mode +const channelOpts = { params: { objects: 'notification' } }; +const channel = realtime.channels.get('my-channel', channelOpts); + // Or using setOptions on an existing channel await channel.setOptions({ params: { objects: 'objects' } }); ``` @@ -58,10 +69,10 @@ Clients require the `channel-metadata` [capability](/docs/auth/capabilities) to ## Subscribe to updates -When using inband objects, the client will receive special `[meta]objects` messages whenever the objects on the channel are updated. These messages provide a snapshot of the current set of objects on the channel. +When using inband objects, the client will receive special `[meta]objects` messages whenever the objects on the channel are updated. [Subscribe](/docs/api/realtime-sdk/channels#subscribe) to `[meta]objects` messages like you would any other message on the channel. For convenience, use a message name filter to only receive messages with the name `[meta]objects` in your listener: @@ -70,15 +81,18 @@ If there is a high rate of updates to the channel objects the inband messages ar ```javascript // Subscribe to [meta]objects messages channel.subscribe('[meta]objects', (message) => { - const { syncId, nextCursor, object } = message.data; - console.log("Received inband objects message:", syncId, nextCursor, JSON.stringify(message.data)); + console.log("Received inband objects message:", JSON.stringify(message.data)); }); ``` -## Message Format +## Objects mode + +The `objects` mode sends the full state of all objects on the channel. When a client attaches to the channel, it immediately receives the current state. Subsequent updates are sent whenever the objects change. -Inband objects messages are sent as a sequence of messages, where each message contains a snapshot of a single object on the channel. Taken together, a set of messages belonging to the same sequence describes the complete set of objects on the channel. +### Message format + +Inband objects messages in `objects` mode are sent as a sequence of messages, where each message contains a snapshot of a single object on the channel. Taken together, a set of messages belonging to the same sequence describes the complete set of objects on the channel. Each inband objects message has a message `name` of `[meta]objects`. @@ -90,4 +104,127 @@ The message `data` is a JSON object with the following top-level properties: | `nextCursor` | A cursor for the next message in the sequence, or `undefined` if this is the last message in the sequence. | | `object` | A JSON representation of the object included in the message. | -The shape of the `object` is the same as the response format of an object when listing them via the [REST API](/docs/liveobjects/rest-api-usage#fetching-objects-list-values). +The shape of the `object` is the following format: + +**Inband Counter Message** + +```javascript +{ + "name": "[meta]objects", + "data": { + "syncId": "1148d241", + "nextCursor": "root", + "object": { + "objectId": "counter:APjeaY7i_IQmrlxV5sEcR7NLTualutgS1QF3wNVJNYI@1769502401136", + "counter": { + "count": 12 + }, + "siteTimeserials": { + "cbf": "01769502451073-000@cbfpt5aQQByRKW13548557:000" + }, + "tombstone": false + } + } +} +``` + + +**Inband Map Message** + + +```javascript +{ + "name": "[meta]objects", + "data": { + "syncId": "95ad3a9f", + "object": { + "objectId": "root", + "map": { + "semantics": 0, + "entries": { + "hello": { + "timeserial": "01769446125853-000@cbfpt5aQQByRKW61375059:000", + "data": { + "string": "world" + }, + "tombstone": false + }, + "votes": { + "timeserial": "01769502401144-000@cbfpt5aQQByRKW13548557:001", + "data": { + "objectId": "counter:APjeaY7i_IQmrlxV5sEcR7NLTualutgS1QF3wNVJNYI@1769502401136" + }, + "tombstone": false + } + } + }, + "siteTimeserials": { + "cbf": "01769446125853-000@cbfpt5aQQByRKW61375059:000" + }, + "tombstone": false + } + } +} +``` + + + +### Example + + +```javascript +// Subscribe to [meta]objects messages in objects mode +channel.subscribe('[meta]objects', (message) => { + const { syncId, nextCursor, object } = message.data; + console.log("Received object:", syncId, nextCursor, JSON.stringify(object)); +}); +``` + + +## Notification mode + +The `notification` mode notifies clients when an objects operation is received, without sending the full state data. This reduces bandwidth for use cases where clients only need to know that an operation occurred and can fetch the state on demand. + +Unlike `objects` mode, `notification` mode does not send an initial state when the client attaches to the channel. The first notification is sent immediately when the first object operation is received. + +### Message format + +Each notification message has a message `name` of `[meta]objects`. + +The message `data` is a JSON object with the following property: + +| Property | Description | +| --- | --- | +| `link` | A relative URL path to fetch the current state of the channel object on the channel via the [REST API](/docs/liveobjects/rest-api-usage#fetch-channel-object). This can be used directly with the Ably REST client's [request](/docs/api/rest-sdk#request) method. | + +### Example + + +```javascript +// Subscribe to [meta]objects messages in notification mode +channel.subscribe('[meta]objects', async (message) => { + const { link } = message.data; + console.log("Objects operation received, fetching state from:", link); + + // Fetch the current state using the REST API + const response = await ablyREST.request('GET', link); + if (response.items.length > 0 ) { + console.log("Current state:", response.items[0]); + } +}); +``` + + +### When to use notification mode + +Use `notification` mode when: + +* You want to minimize bandwidth usage and only fetch state when needed. +* Your application can tolerate fetching state on demand rather than receiving it immediately. +* You have infrequent operations and don't need continuous state updates. + +Use `objects` mode when: + +* You need the full state immediately on attach. +* You want to receive state updates in realtime without additional REST API calls. +* Your application requires continuous synchronization of state.