Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
6d37df9
Add LiveObjects product to site navigation
VeskeR Mar 5, 2025
fab36af
Live objects: Add REST API docs
zknill Mar 24, 2025
ffc792f
Merge pull request #2464 from ably/liveobjects-navigation
VeskeR Apr 2, 2025
a22eae2
Merge pull request #2490 from ably/zak/pub-1040/rest-api-reference-docs
zknill Apr 2, 2025
3801415
liveobjects: add occupancy metrics
mschristensen Mar 31, 2025
630c522
liveobjects: add capabilities
mschristensen Mar 31, 2025
b5bcea6
liveobjects: max objects limit
mschristensen Mar 31, 2025
f8f95d9
stats: rename state -> objects
mschristensen Mar 31, 2025
4ed1083
liveobjects: objects message excluded from storage
mschristensen Mar 31, 2025
0c431af
liveobjects: add object modes
mschristensen Mar 31, 2025
268c098
channels/options: channel modes docs
mschristensen Apr 2, 2025
cc575fd
Add LiveObjects index docs
VeskeR Mar 5, 2025
9545871
Add `channels.objects` property to realtime api docs
VeskeR Mar 5, 2025
70e751f
Add LiveObjects Quickstart docs
VeskeR Mar 6, 2025
5a41d6e
Add LiveObjects LiveCounter docs
VeskeR Mar 6, 2025
35cd419
Add LiveObjects LiveMap docs
VeskeR Mar 6, 2025
1cae8e9
Add LiveObjects Batch Operations docs
VeskeR Mar 6, 2025
b4b4a6f
Add LiveObjects Lifecycle events docs
VeskeR Mar 7, 2025
5a0dd9d
Add LiveObjects Typings docs
VeskeR Mar 7, 2025
6532e7f
Use sentence case in navigation
VeskeR Apr 11, 2025
1220eaf
Add Advanced section for some of the LiveObjects navigation items
VeskeR Apr 11, 2025
770b56e
Add LiveObjects section to platform/index
VeskeR Apr 11, 2025
8743764
Merge pull request #2525 from ably/liveobjects/add-liveobjects-to-pla…
VeskeR Apr 11, 2025
25822ce
Add comment explaining reusing the assetTracking badge color for live…
VeskeR Apr 11, 2025
5a1b591
Merge pull request #2526 from ably/liveobjects/comment-badge-color
VeskeR Apr 11, 2025
a4889c0
Merge pull request #2463 from ably/PUB-773/liveobjects-product-docs
VeskeR Apr 17, 2025
0cd5dcd
Merge pull request #2522 from ably/PUB-1588/improve-liveobjects-navig…
VeskeR Apr 17, 2025
edcfcf0
Add LiveObjects image for docs homepage
VeskeR Apr 17, 2025
f511667
Remove references to example app from LiveObjects docs
VeskeR Apr 17, 2025
5f2b178
Update language data for JavaScript SDK to 2.8
VeskeR Apr 17, 2025
4453ba9
Merge pull request #2547 from ably/PUB-1589/liveobjects-docs-homepage…
VeskeR Apr 22, 2025
e12182b
Merge pull request #2548 from ably/liveobjects/remove-examples-links
VeskeR Apr 22, 2025
9c2348b
Merge pull request #2550 from ably/liveobjects/update-js-language-dat…
VeskeR Apr 22, 2025
60c5585
Migrated LiveObjects rest API from the current implementation to OpenAPI
GregHolmes Apr 8, 2025
fc026f1
Update Liveobjects REST API to have http responses
GregHolmes Apr 22, 2025
263f80a
fixup! Update Liveobjects REST API to have http responses
GregHolmes Apr 29, 2025
c4a1b07
Merge pull request #2513 from ably/EDU-1882-Migrate-LiveObjects-Rest-…
GregHolmes Apr 30, 2025
25d63ca
nav/liveobjects: object types section
mschristensen Apr 22, 2025
543543f
nav/liveobjects: rename to getting started
mschristensen Apr 22, 2025
a8ddbdb
liveobjects: add objects concepts docs
mschristensen Apr 23, 2025
6dddcc8
liveobjects: add operations concepts docs
mschristensen Apr 23, 2025
2d4e91e
liveobjects: rest api usage
mschristensen Apr 24, 2025
cb62a2f
liveobjects: add synchronization concepts docs
mschristensen Apr 28, 2025
faa8cac
liveobjects: update links to root object docs
mschristensen Apr 30, 2025
c57fc91
liveobjects: remove link trailing punctuation
mschristensen Apr 30, 2025
339b272
liveobjects: add inband objects docs
mschristensen Apr 29, 2025
4fd6550
Merge branch 'main' into liveobjects/merge-main-2025-05-08
VeskeR May 8, 2025
f50860a
Merge pull request #2581 from ably/liveobjects/merge-main-2025-05-08
VeskeR May 8, 2025
7432797
Add experimental flag to LiveObjects docs
m-hulbert May 8, 2025
879fa49
Merge pull request #2582 from ably/edu-1936-experiemental-liveobjects
m-hulbert May 8, 2025
3e83679
Update language data for ably-js to v2.9
VeskeR May 8, 2025
9b41d84
Merge pull request #2584 from ably/liveobjects/language-version-2.9
VeskeR May 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions content/api/realtime-sdk/channels.textile
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,11 @@ h6(#push).

Provides access to the "PushChannel":/docs/api/realtime-sdk/push#push-channel object for this channel which can be used to access members present on the channel, or participate in presence.

h6(#objects).
default: objects

Provides access to the "Objects":/docs/liveobjects object for this channel which can be used to read, modify and subscribe to LiveObjects on a channel.

h3. Methods

h6(#publish).
Expand Down
2 changes: 2 additions & 0 deletions content/auth/capabilities.textile
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ The following capability operations are available for API keys and issued tokens
- subscribe := can subscribe to messages and presence state change messages on channels, and get the presence set of a channel
- publish := can publish messages to channels
- presence := can register presence on a channel (enter, update and leave)
- object-subscribe := can subscribe to updates to objects on a channel
- object-publish := can update objects on a channel
- history := can retrieve message and presence state history on channels
- stats := can retrieve current and historical usage statistics for an app
- push-subscribe := can subscribe devices for push notifications
Expand Down
49 changes: 40 additions & 9 deletions content/channels/options/index.textile
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ await channel.setOptions(channelOptions);

h2(#params). Params

The @params@ property can be used to enable additional features on a channel-by-channel basis. These features include using @rewind@ to replay messages published prior to a client attaching to a channel, @delta@ so that message payloads only contain the difference between the current and previous message, and @occupancy@ to subscribe to metrics about the clients attached to a channel.
The @params@ property can be used to enable additional features on a channel-by-channel basis.

h3(#rewind). Rewind

Expand Down Expand Up @@ -380,7 +380,9 @@ The following is an example of an occupancy metric event:
subscribers: 1,
presenceConnections: 1,
presenceMembers: 0,
presenceSubscribers: 1
presenceSubscribers: 1,
objectPublishers: 1,
objectSubscribers: 1
}
},
encoding: null,
Expand All @@ -402,17 +404,46 @@ Occupancy events have a payload in the @data@ property with a value of @occupanc
}
```

h3(#objects). Inband Objects

"Inband objects":/docs/liveobjects/inband-objects allows clients to subscribe to changes to "LiveObjects":/docs/liveobjects channel objects as regular channel messages.

When using inband objects, the client receives messages with the special name @[meta]objects@ that describe the current set of objects on a channel.

<aside class="note">
<p>This feature enables clients to subscribe to LiveObjects updates in realtime even on platforms that don't yet have a dedicated LiveObjects Realtime client implementation. If you're using LiveObjects from JavaScript/TypeScript, use the LiveObjects "plugin":/docs/liveobjects/quickstart?lang=javascript which has dedicated support for all LiveObjects features.</p>
</aside>

For more information see the "inband objects":/docs/liveobjects/inband-objects documentation.

h2(#modes). Modes

The @modes@ property can be used to set channel mode flags. Channel mode flags enable a client to specify a subset of the "capabilities":/docs/auth/capabilities granted by their token or API key. Channel mode flags offer the ability for clients to use different capabilities for different channels, however, as they are flags and not permissions they cannot be enforced by an authentication server.
Channel mode flags enable a client to specify which functionality they will use on the channel.

A client can explicitly request a set of modes using the @modes@ property. If the @modes@ property is not provided, the default modes will be used.

The available set of channel mode flags are:

|_. Flag |_. Description |_. Default? |
| @SUBSCRIBE@ | Can subscribe to receive messages on the channel. | Yes |
| @PUBLISH@ | Can publish messages to the channel. | Yes |
| @PRESENCE_SUBSCRIBE@ | Can subscribe to receive presence events on the channel. | Yes |
| @PRESENCE@ | Can register presence on the channel. | Yes |
| @OBJECT_PUBLISH@ | Can update objects on the channel. | No |
| @OBJECT_SUBSCRIBE@ | Can subscribe to receive updates to objects on the channel. | No |

The set of modes available to a client is determined by the set of "capabilities":/docs/auth/capabilities granted by their token or API key.

The modes granted by each capability are:

The channel mode flags available are:
|_. Capability |_. Granted Modes |
| @subscribe@ | @SUBSCRIBE@, @PRESENCE_SUBSCRIBE@, @OBJECT_SUBSCRIBE@ |
| @publish@ | @PUBLISH@ |
| @presence@ | @PRESENCE@ |
| @object-subscribe@ | @OBJECT_SUBSCRIBE@ |
| @object-publish@ | @OBJECT_PUBLISH@ |

|_. Flag |_. Description |
| SUBSCRIBE | Can subscribe to receive messages on the channel. |
| PUBLISH | Can publish messages to the channel. |
| PRESENCE_SUBSCRIBE | Can subscribe to receive presence events on the channel. |
| PRESENCE | Can register presence on the channel. |
The actual modes assigned to a client will be the **intersection** of the requested @modes@ and the modes available to the client according to its capabilities. For example, a client with the @subscribe@ capability which explicitly requests @SUBSCRIBE@ and @PUBLISH@ modes will be assigned only the @SUBSCRIBE@ mode.

The following is an example of setting channel mode flags:

Expand Down
2 changes: 1 addition & 1 deletion content/channels/options/rewind.textile
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ If the attachment is successful, and one or more messages exist on the channel p
Any @rewind@ value that cannot be parsed either as a number or a time specifier will cause the attachment request to fail and return an error.

<aside data-type='note'>
<p>If you have enabled the "persist last message":/docs/storage-history/storage#persist-last-message channel rule on a channel, you can attach with @rewind=1@ to retrieve the last message. Only the last message published can be stored for up to a year, and persist last message doesn't apply to presence messages.</p>
<p>If you have enabled the "persist last message":/docs/storage-history/storage#persist-last-message channel rule on a channel, you can attach with @rewind=1@ to retrieve the last message. Only the last message published can be stored for up to a year, and persist last message doesn't apply to presence or object messages.</p>
</aside>

The following example subscribes to a channel and retrieves the most recent message sent on it, if available:
Expand Down
4 changes: 3 additions & 1 deletion content/integrations/webhooks/index.textile
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,9 @@ The following is an example of a batched @channel lifecycle@ payload:
"subscribers": 1,
"presenceConnections": 1,
"presenceMembers": 0,
"presenceSubscribers": 1
"presenceSubscribers": 1,
"objectPublishers": 1,
"objectSubscribers": 1
}
}
}
Expand Down
152 changes: 152 additions & 0 deletions content/liveobjects/batch.textile
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
---
title: Batch operations
meta_description: "Group multiple objects operations into a single channel message to apply grouped operations atomically and improve performance."
product: liveobjects
languages:
- javascript
---

<aside data-type='experimental'>
<p>LiveObjects is currently Experimental. Its features are still in development and subject to rapid change.</p>
</aside>

The Batching API in LiveObjects enables multiple updates to be grouped into a single channel message and applied atomically. It ensures that all operations in a batch either succeed together or are discarded entirely. Batching operations is essential when multiple related updates to channel objects must be applied as a single atomic unit, for example, when application logic depends on multiple objects being updated simultaneously. Without batching, if one operation succeeds while another fails, your application state could become inconsistent.

Note that this differs from "Message batching":/docs/messages/batch, the native Pub/Sub messages feature. The LiveObjects Batching API is a separate API specifically designed to enable you to group object operations into a single channel message, ensuring that the Ably system guarantees the atomicity of the applied changes.

h2(#create). Create batch context

blang[javascript].

To batch object operations together, use the @channel.objects.batch()@ method. This method accepts a callback function, which is provided with a batch context object. The batch context object provides a synchronous API to work with objects on a channel that stores operations inside the batch instead of applying them immediately.

Using the batch context ensures that operations are grouped and sent in a single channel message after the batch callback function has run. This guarantees that all changes are applied atomically by both the server and all clients.

<aside data-type='important'>
<p>
The batch callback function must be synchronous because the batch method sends the grouped operations as soon as the callback function completes. If you need to perform asynchronous operations (such as fetching data to do operations inside a batch), do so outside the callback function before calling @channel.objects.batch()@.
</p>
</aside>

blang[javascript].

```[javascript]
await channel.objects.batch((ctx) => {
const root = ctx.getRoot();

root.set('foo', 'bar');
root.set('baz', 42);

const counter = root.get('counter');
counter.increment(5);

// Batched operations are sent to the Ably system when the batch callback has run.
});
```

If an error occurs within the batch, all operations are discarded, preventing partial updates and ensuring atomicity.

h3(#context). Batch context object

blang[javascript].

The batch context provides a synchronous API for objects operations inside the batch callback. It mirrors the asynchronous API found on @channel.objects@, including "LiveCounter":/docs/liveobjects/counter and "LiveMap":/docs/liveobjects/map.

To access the batch API, call @BatchContext.getRoot()@, which synchronously returns a wrapper around the "root":/docs/liveobjects/concepts/objects#root-object object instance. This wrapper enables you to access and modify objects within a batch.

<aside data-type='note'>
<p>
Although the batch context provides a synchronous API, updates to objects are only applied _after_ the batch callback function has run and changes have been echoed back to the client, just like regular mutation operations.
</p>
</aside>

blang[javascript].

```[javascript]
await channel.objects.batch((ctx) => {
// Note: .getRoot() call on a batch context is synchronous.
// The returned root object is a special wrapper around a regular LiveMap instance,
// providing a synchronous mutation API.
const root = ctx.getRoot();

// Mutation operations like LiveMap.set and LiveCounter.increment
// are synchronous inside the batch and queue operations instead of applying them immediately.
root.set('foo', 'bar');
root.remove('baz');

// Access other objects through the root object from the BatchContext.getRoot() method.
const counter = root.get('counter');
counter.increment(5);
});
```

You cannot create new objects using the batch context. If you need to create new objects and add them to the channel as part of an atomic batch operation to guarantee atomicity, you must first create them using the regular @channel.objects@ API. Once the objects have been created, you can then assign them to the object tree inside a batch function.

blang[javascript].

```[javascript]
// First, create new objects outside the batch context
const counter = await channel.objects.createCounter();
const map = await channel.objects.createMap();

// Then, use a batch to assign them atomically to the channel objects
await channel.objects.batch((ctx) => {
const root = ctx.getRoot();
root.set('counter', counter);
root.set('map', map);
});
```

h3(#use-cases). When to batch operations

Usually, you don't need to use batching for objects operations. It is only useful in situations where a group of operations must be applied together to maintain consistency in application state, or when there are multiple mutation operations that you might want to apply at the same time to improve the UI experience.

For example, in a task dashboard application, you might want to remove all tasks on a board in a single operation to prevent excessive UI updates that the user would otherwise experience.

blang[javascript].

```[javascript]
await channel.objects.batch((ctx) => {
const root = ctx.getRoot();
const tasks = root.get('tasks');

for (const key of reactions.keys()) {
reactions.remove(key);
}
});
```

h3(#cancel). Cancel batch operation

To explicitly cancel a batch before it is applied, throw an error inside the batch function. This prevents any queued operations from being applied.

blang[javascript].

```[javascript]
await channel.objects.batch((ctx) => {
const root = ctx.getRoot();
root.set('foo', 'bar');

// Throwing an error prevents any queued operations from being applied.
throw new Error('Cancel batch');
});
```

blang[javascript].

h3(#closed). Batch API cannot be used outside the callback function

The Batch API provided by the batch context object cannot be used outside the callback function. Attempting to do so results in an error. This applies both to @BatchContext.getRoot()@ and any object instances retrieved from it.

blang[javascript].

```[javascript]
let root;
await channel.objects.batch((ctx) => {
root = ctx.getRoot();
});

// Calling any Batch API methods outside the batch callback
// will throw an Error: Batch is closed.
root.set('foo', 'bar');
```
Loading