[AIT-30] LiveObjects Path-based API spec#427
Conversation
13dee45 to
1e518c6
Compare
1fa3eeb to
46261f4
Compare
49f0364 to
47a9d51
Compare
46261f4 to
3608895
Compare
3608895 to
b4ad764
Compare
7738c92 to
fa2a54e
Compare
b4ad764 to
1eb4dd8
Compare
1eb4dd8 to
035aef9
Compare
035aef9 to
babc296
Compare
|
I've rebased this on I've also split it up a bit:
|
There was a problem hiding this comment.
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 withPathObject, and specify path resolution, navigation, and path-based subscriptions. - Introduce immutable “value types” (
LiveMapValueType,LiveCounterValueType) created viaLiveMap.create/LiveCounter.create, consumed by mutation operations to emit the required*_CREATEmessages. - Add a shared
Subscriptiontype tofeatures.mdand 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
PathObjectSubscriptionEventthat includes theObjectMessagethat caused the change, but the trigger described in RTO24b is aLiveObjectUpdateemission (RTLO4b4), which doesn’t carry anObjectMessage. Please clarify how theObjectMessageis 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.noopis an internal property, but the IDL no longer marks it as internal. Either marknoopas 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
LiveMapasinternal, but the spec introducesLiveMap.create(RTLMV3) as the public factory forLiveMapValueType. IfLiveMapis internal, users can’t callLiveMap.create, so eitherLiveMapneeds 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.
| - `(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 |
Note: This PR is based on #470; please review that one first.
Resolves AIT-30.