Skip to content

[AIT-30] LiveObjects Path-based API spec#427

Open
VeskeR wants to merge 3 commits into
integration/liveobjects-path-based-apifrom
AIT-30/liveobjects-path-based-api-spec
Open

[AIT-30] LiveObjects Path-based API spec#427
VeskeR wants to merge 3 commits into
integration/liveobjects-path-based-apifrom
AIT-30/liveobjects-path-based-api-spec

Conversation

@VeskeR
Copy link
Copy Markdown
Contributor

@VeskeR VeskeR commented Feb 24, 2026

Note: This PR is based on #470; please review that one first.

Resolves AIT-30.

@VeskeR VeskeR force-pushed the AIT-30/liveobjects-path-based-api-spec branch from 13dee45 to 1e518c6 Compare February 24, 2026 13:46
@VeskeR VeskeR force-pushed the AIT-30/liveobjects-path-based-api-spec branch from 1fa3eeb to 46261f4 Compare February 24, 2026 15:52
@VeskeR VeskeR force-pushed the AIT-313/protocol-v6-state-message branch 3 times, most recently from 49f0364 to 47a9d51 Compare February 27, 2026 15:52
Base automatically changed from AIT-313/protocol-v6-state-message to main February 27, 2026 15:53
@ttypic ttypic force-pushed the AIT-30/liveobjects-path-based-api-spec branch from 46261f4 to 3608895 Compare March 9, 2026 10:54
@github-actions github-actions Bot temporarily deployed to staging/pull/427 March 9, 2026 10:55 Inactive
@lawrence-forooghian lawrence-forooghian force-pushed the AIT-30/liveobjects-path-based-api-spec branch from 3608895 to b4ad764 Compare May 12, 2026 18:41
@github-actions github-actions Bot temporarily deployed to staging/pull/427 May 12, 2026 18:41 Inactive
@lawrence-forooghian lawrence-forooghian added live-objects Related to LiveObjects functionality. labels May 12, 2026
@lawrence-forooghian lawrence-forooghian changed the base branch from main to rename-channel-objects-to-object May 12, 2026 19:37
@lawrence-forooghian lawrence-forooghian force-pushed the rename-channel-objects-to-object branch 2 times, most recently from 7738c92 to fa2a54e Compare May 12, 2026 19:45
@lawrence-forooghian
Copy link
Copy Markdown
Collaborator

lawrence-forooghian commented May 12, 2026

I've rebased this on main (main issues were some conflicts left over from the Markdown migration, and the "The client library must retain…" clauses of RTO11f18 and RTO12f16, which have been moved to RTLCV4g5 and RTLMV4j5).

I've also split it up a bit:

  1. Implicit attach on channel.objects.getRoot() call #472 — now into main since the behaviour is not related to the path-based API
  2. [AIT-30] Rename LiveObjects entrypoint and class name from "objects" to "object" #470 — simple rename targeting integration/liveobjects-path-based-api will approve and merge imminently
  3. this PR, which now contains the core path-based API stuff — I intend to review shortly
  4. [AIT-30] BatchContext and batch API on PathObject and Instance #471 — batch stuff, we can review this later since I don't think we need to ship a batch API as part of the initial path-based API release for Swift / Kotlin (given we don't yet have a batch API in those libraries and never treated it as a priority)

Base automatically changed from rename-channel-objects-to-object to integration/liveobjects-path-based-api May 12, 2026 20:23
@sacOO7 sacOO7 requested a review from Copilot May 13, 2026 11:59
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the LiveObjects specification to introduce a path-based API surface (PathObject) and value-type factories (LiveMapValueType, LiveCounterValueType) to support nested object creation and path-scoped subscriptions, superseding the previous RealtimeObject#createMap/createCounter style.

Changes:

  • Replace RealtimeObject#get() return type with PathObject, and specify path resolution, navigation, and path-based subscriptions.
  • Introduce immutable “value types” (LiveMapValueType, LiveCounterValueType) created via LiveMap.create / LiveCounter.create, consumed by mutation operations to emit the required *_CREATE messages.
  • Add a shared Subscription type to features.md and update reserved spec point prefixes / message-size retention references to the new clauses.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
specifications/objects-features.md Specifies the new path-based API (PathObject, Instance), value-type creation/consumption, and subscription dispatch rules; updates the IDL accordingly.
specifications/features.md Extends reserved spec point prefixes, updates retention references, and defines a shared Subscription type in the core feature spec/IDL.
Comments suppressed due to low confidence (3)

specifications/objects-features.md:298

  • RTO24b4 requires dispatching a PathObjectSubscriptionEvent that includes the ObjectMessage that caused the change, but the trigger described in RTO24b is a LiveObjectUpdate emission (RTLO4b4), which doesn’t carry an ObjectMessage. Please clarify how the ObjectMessage is made available at dispatch time (e.g. include it in the emitted update, or define PathObjectSubscriptionRegister as being driven directly by operation application).
  - `(RTO24b)` When a `LiveObject` in the `ObjectsPool` emits a `LiveObjectUpdate` (per [RTLO4b4](#RTLO4b4)), the `PathObjectSubscriptionRegister` must determine which subscriptions should be notified:
    - `(RTO24b1)` Determine the paths in the LiveObjects tree at which the updated `LiveObject` is located
    - `(RTO24b2)` For each registered subscription, check whether the event path starts with (or equals) the subscription's path
    - `(RTO24b3)` If the event path matches, apply depth filtering: the event is dispatched to the subscription if the number of path segments from the subscription path to the event path plus 1 does not exceed the subscription's `depth` option (or if `depth` is undefined). Formally, the event is dispatched if `eventPath.length - subscriptionPath.length + 1 <= depth`
    - `(RTO24b4)` Create a `PathObjectSubscriptionEvent` with a `PathObject` pointing to the event path and the `ObjectMessage` that caused the change, and call the subscription's listener
    - `(RTO24b5)` If a listener throws an error, the error must be caught and logged without affecting the dispatch to other subscriptions

specifications/objects-features.md:1032

  • RTLO4b4b explicitly states that LiveObjectUpdate.noop is an internal property, but the IDL no longer marks it as internal. Either mark noop as internal in the IDL (or make the surrounding text consistent if it’s intended to be public).
    interface LiveObjectUpdate: // RTLO4b4
      update: Object // RTLO4b4a
      noop: Boolean // RTLO4b4b

specifications/objects-features.md:1052

  • The IDL marks LiveMap as internal, but the spec introduces LiveMap.create (RTLMV3) as the public factory for LiveMapValueType. If LiveMap is internal, users can’t call LiveMap.create, so either LiveMap needs to be public (with only instance methods internal), or the factory should live on a public type (e.g. LiveMapValueType.create).
    class LiveMap extends LiveObject: // RTLM*, RTLM1, internal
      clearTimeserial: String? // RTLM25, internal
      get(key: String) -> (Boolean | Binary | Number | String | JsonArray | JsonObject | LiveCounter | LiveMap)? // RTLM5, internal
      size() -> Number // RTLM10, internal
      entries() -> [String, (Boolean | Binary | Number | String | JsonArray | JsonObject | LiveCounter | LiveMap)?][] // RTLM11, internal
      keys() -> String[] // RTLM12, internal
      values() -> (Boolean | Binary | Number | String | JsonArray | JsonObject | LiveCounter | LiveMap)?[] // RTLM13, internal
      set(String key, (Boolean | Binary | Number | String | JsonArray | JsonObject | LiveCounterValueType | LiveMapValueType) value) => io // RTLM20, internal
      remove(String key) => io // RTLM21, internal
      static create(Dict<String, Boolean | Binary | Number | String | JsonArray | JsonObject | LiveCounterValueType | LiveMapValueType> entries?) -> LiveMapValueType // RTLMV3


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +294 to +297
- `(RTO24b1)` Determine the paths in the LiveObjects tree at which the updated `LiveObject` is located
- `(RTO24b2)` For each registered subscription, check whether the event path starts with (or equals) the subscription's path
- `(RTO24b3)` If the event path matches, apply depth filtering: the event is dispatched to the subscription if the number of path segments from the subscription path to the event path plus 1 does not exceed the subscription's `depth` option (or if `depth` is undefined). Formally, the event is dispatched if `eventPath.length - subscriptionPath.length + 1 <= depth`
- `(RTO24b4)` Create a `PathObjectSubscriptionEvent` with a `PathObject` pointing to the event path and the `ObjectMessage` that caused the change, and call the subscription's listener
noop: Boolean // RTLO4b4b, internal
noop: Boolean // RTLO4b4b

class LiveCounter extends LiveObject: // RTLC*, RTLC1

- `(SUB1)` A `Subscription` represents a registration for receiving events from a subscribe operation
- `(SUB2)` The `Subscription` object has the following method:
- `(SUB2a)` `unsubscribe` - deregisters the listener that was registered by the corresponding `subscribe` call. Once `unsubscribe` called, the listener must not be called for any subsequent events
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

live-objects Related to LiveObjects functionality.

Development

Successfully merging this pull request may close these issues.

3 participants