[AIT-30] BatchContext and batch API on PathObject and Instance#471
Open
lawrence-forooghian wants to merge 1 commit into
Open
[AIT-30] BatchContext and batch API on PathObject and Instance#471lawrence-forooghian wants to merge 1 commit into
lawrence-forooghian wants to merge 1 commit into
Conversation
035aef9 to
babc296
Compare
sacOO7
reviewed
May 13, 2026
| - `(RTPO21b)` Returns a stream or iterable that yields `PathObjectSubscriptionEvent` objects, using the idiomatic construct for the language (e.g. async iterators, channels, flows, or async sequences) | ||
| - `(RTPO21c)` Internally wraps `PathObject#subscribe` ([RTPO19](#RTPO19)), converting the callback-based subscription into the appropriate streaming or iterable pattern | ||
| - `(RTPO22)` `PathObject#batch` function: | ||
| - `(RTPO22a)` Expects a synchronous function `fn` that receives a `BatchContext` as its argument |
Collaborator
There was a problem hiding this comment.
Suggested change
| - `(RTPO22a)` Expects a synchronous function `fn` that receives a `BatchContext` as its argument | |
| - `(RTPO22a)` Accepts a synchronous anonymous function as a argument. This anonymous function is called with `BatchContext` as its argument internally. |
Collaborator
There was a problem hiding this comment.
https://ably.com/docs/liveobjects/concepts/path-object#batch-multiple-updates
Similarly, other spec points might not be explicit, will do a full review soon
There was a problem hiding this comment.
Pull request overview
This PR extends the LiveObjects path-based API specification by introducing a batching mechanism for object mutations, enabling multiple map/counter operations to be queued and then published atomically as a single channel message.
Changes:
- Adds
PathObject#batchandInstance#batchspec points, describing lifecycle and permission requirements. - Introduces the
BatchContext/ internalRootBatchContextspecification for queuing and flushing batched operations. - Reserves the new
RTBCspec point prefix in the main features index.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| specifications/objects-features.md | Specifies batch APIs for PathObject/Instance and defines BatchContext + internal batching flush mechanics. |
| specifications/features.md | Updates reserved spec point prefixes to include RTBC. |
Comments suppressed due to low confidence (1)
specifications/objects-features.md:1004
- RTINS19 similarly specifies flush/close only after
fnreturns. Please define behavior whenfnthrows (and, where applicable, when an async function is passed): queued operations should not be flushed/published, but the RootBatchContext should still be closed so the BatchContext and any children become unusable and consistently throw the “batch is closed” error.
- `(RTINS19d)` Creates a `RootBatchContext` ([RTBC16](#RTBC16)) wrapping this `Instance`
- `(RTINS19e)` Executes `fn`, passing the `BatchContext` as argument
- `(RTINS19f)` After `fn` returns, flushes the `RootBatchContext` ([RTBC16d](#RTBC16d)) to publish all queued operations atomically
- `(RTINS19g)` The `RootBatchContext` is closed after flush completes, regardless of success or failure
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| - `(RTPO22)` `PathObject#batch` function: | ||
| - `(RTPO22a)` Expects a synchronous function `fn` that receives a `BatchContext` as its argument | ||
| - `(RTPO22b)` Requires the `OBJECT_PUBLISH` channel mode to be granted per [RTO2](#RTO2) | ||
| - `(RTPO22c)` Resolves the path to a `LiveObject` using the internal path resolution procedure. If the path does not resolve to a `LiveObject`, the library must throw an `ErrorInfo` error with `statusCode` 400 and `code` 92007 |
Comment on lines
+921
to
+922
| - `(RTPO22f)` After `fn` returns, flushes the `RootBatchContext` ([RTBC16d](#RTBC16d)) to publish all queued operations atomically | ||
| - `(RTPO22g)` The `RootBatchContext` is closed after flush completes, regardless of success or failure |
| - `(RTBC4)` `BatchContext#get` function: | ||
| - `(RTBC4a)` Expects a `key` `String` argument | ||
| - `(RTBC4b)` If the batch is closed, the library must throw an `ErrorInfo` error with `statusCode` 400 and `code` 40000 | ||
| - `(RTBC4c)` Delegates to `Instance#get` ([RTINS5](#RTINS5)) on the underlying `Instance`. If the result is undefined, returns undefined |
| - `(RTBC14a1)` `amount` `Number` (optional) - the amount by which to increment the counter value. Defaults to 1 | ||
| - `(RTBC14b)` If the batch is closed, the library must throw an `ErrorInfo` error with `statusCode` 400 and `code` 40000 | ||
| - `(RTBC14c)` If the wrapped value is not a `LiveCounter`, the library must throw an `ErrorInfo` error with `statusCode` 400 and `code` 92007 | ||
| - `(RTBC14d)` Queues a message constructor on the `RootBatchContext` that, when executed, creates an `ObjectMessage` for a `COUNTER_INC` operation in the same manner as `LiveCounter#increment` ([RTLC12](#RTLC12)) |
| - `(RTBC16a)` Maintains an internal `wrappedInstances` map that memoizes `BatchContext` wrappers by `objectId` | ||
| - `(RTBC16b)` Maintains an internal `queuedMessageConstructors` list of deferred message constructor functions. Some `ObjectMessages` require asynchronous I/O during construction (e.g. generating an `objectId` for nested value types), so message constructors are queued during synchronous batch method calls and executed on flush | ||
| - `(RTBC16c)` `wrapInstance` function: wraps an `Instance` in a `BatchContext`. If the `Instance` has an `objectId` and a wrapper for that `objectId` already exists in `wrappedInstances`, the existing wrapper is returned. Otherwise, a new `BatchContext` is created and stored in `wrappedInstances` | ||
| - `(RTBC16d)` `flush` function: closes the batch context, executes all queued message constructors, flattens the resulting `ObjectMessages` into a single array, and publishes them using `RealtimeObject#publish` ([RTO15](#RTO15)). If there are no queued messages, no publish is performed |
| - `(RTBC15a1)` `amount` `Number` (optional) - the amount by which to decrement the counter value. Defaults to 1 | ||
| - `(RTBC15b)` If the batch is closed, the library must throw an `ErrorInfo` error with `statusCode` 400 and `code` 40000 | ||
| - `(RTBC15c)` If the wrapped value is not a `LiveCounter`, the library must throw an `ErrorInfo` error with `statusCode` 400 and `code` 92007 | ||
| - `(RTBC15d)` Delegates to `BatchContext#increment` ([RTBC14](#RTBC14)) with the negated `amount` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Note: This PR is based on #427.
Split from #427 to reduce the review burden of that PR (since we don't need to do the batch API for the initial implementation of the path-based API).