Skip to content

Conversation

@VeskeR
Copy link
Contributor

@VeskeR VeskeR commented Jul 23, 2025

Adds spec for:

  • RealtimeObjects.createMap
  • RealtimeObjects.createCounter

Related DRs: LLODR-027: OBJECT_ID semantic preserving client-side generated IDs (Object ID generation), LODR-018: High level write API overview

Resolves PUB-1829

@VeskeR VeskeR added the live-objects Related to LiveObjects functionality. label Jul 23, 2025
@VeskeR VeskeR changed the title Add object-level write API spec for RealtimeObjects [PUB-1829] Add object-level write API spec for RealtimeObjects Jul 23, 2025
@github-actions github-actions bot temporarily deployed to staging/pull/353 July 23, 2025 15:05 Inactive
@VeskeR VeskeR force-pushed the PUB-1829/object-write-API branch from e60fdf2 to 2553181 Compare July 23, 2025 15:45
@github-actions github-actions bot temporarily deployed to staging/pull/353 July 23, 2025 15:45 Inactive
@VeskeR VeskeR force-pushed the PUB-1829/object-write-API branch from 2553181 to baee12a Compare July 23, 2025 15:49
@github-actions github-actions bot temporarily deployed to staging/pull/353 July 23, 2025 15:49 Inactive
lawrence-forooghian added a commit to ably/ably-liveobjects-swift-plugin that referenced this pull request Jul 24, 2025
There isn't a spec PR for this yet, but it's needed in order to
implement the write spec [1]. Asked about it in [2]. It's implemented in
JS in [3].

Got Cursor to do this.

[1] ably/specification#353
[2] https://github.com/ably/specification/pull/353/files#r2228017382
[3] ably/ably-js#2065
@github-actions github-actions bot temporarily deployed to staging/pull/353 July 25, 2025 03:41 Inactive
@VeskeR VeskeR marked this pull request as ready for review July 25, 2025 03:45
** @(RTO11b)@ The return type is a @LiveMap@, which is returned once the required I/O has successfully completed
** @(RTO11c)@ Requires the @OBJECT_PUBLISH@ channel mode to be granted per "RTO2":#RTO2
** @(RTO11d)@ If the channel is in the @DETACHED@, @FAILED@ or @SUSPENDED@ state, the library should throw an @ErrorInfo@ error with @statusCode@ 400 and @code@ 90001
** @(RTO11e)@ If "@echoMessages@":../features#TO3h client option is @false@, the library should throw an @ErrorInfo@ error with @statusCode@ 400 and @code@ 40000, indicating that @echoMessages@ must be enabled for this operation
Copy link
Collaborator

@sacOO7 sacOO7 Jul 29, 2025

Choose a reason for hiding this comment

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

Since the connection can be shared across PubSub, Chat, and Objects, echoMessages might limit the ability to do so. We need to assess the potential impact across various product offerings

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've opened a separate issue for this #365, and this can be discussed in future LiveObjects plugin discussions.
As of now, LiveObjects does not support applying operations locally first and instead relies on receiving echoed operations.

*** @(RTO11f5)@ Create an initial value JSON string as described in "RTO13":#RTO13, passing in the partial @ObjectOperation@ from "RTO11f4":#RTO11f4
*** @(RTO11f6)@ Create a unique nonce as a random string
*** @(RTO11f7)@ Get the current server time as described in "RTO16":#RTO16
*** @(RTO11f8)@ Create an @objectId@ for the new @LiveMap@ object as described in "RTO14":#RTO14, passing in @map@ string as the @type@, the initial value JSON string from "RTO11f5":#RTO11f5, the nonce from "RTO11f6":#RTO11f6, and the server time from "RTO11f7":#RTO11f7
Copy link
Collaborator

@sacOO7 sacOO7 Jul 29, 2025

Choose a reason for hiding this comment

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

In the case of REST APIs, objectId is optional and is automatically generated by the server.
Applying the same approach for realtime could reduce round-trip time for getting current server time —something particularly valuable when customers are using RealtimeObjects.
Although we're using the local offset to save round-trip time for subsequent requests, there's still a risk that the local clock may drift out of sync.
So, we can keep objectId generation optional in realtime as well, wdyt

Copy link
Collaborator

Choose a reason for hiding this comment

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

Why Clock Drift Happens

  • Hardware limitations: Even in modern servers, clock crystals have a natural drift—often ±20 parts per million (ppm) or better—leading to seconds or even minutes of drift over long periods if completely unsynchronized.
  • Virtualization effects: Virtual machines (VMs) are affected by host clock changes, hypervisor scheduling, and pausing (such as during suspension or migration). This can lead to sudden jumps or drift in the OS-reported time.
  • Synchronization interruptions: Network Time Protocol (NTP), Precision Time Protocol (PTP), and cloud-provider time sync services are used to keep clocks accurate. Any network issue, misconfiguration, or system trouble that prevents time sync can allow drift to accumulate, sometimes rapidly.
  • System events: Actions such as rebooting, resuming from suspension, or falling back to OS instead of the hardware clock can cause higher drift or a temporary loss of sync

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In Realtime, developers can obtain a reference to an object before the corresponding *_CREATE operation has been processed by the server and an ID has been generated for it. In such cases, it is crucial that the Realtime client is still able to send mutation operations for that object or reference it within other collection types. Without knowing the object ID, this becomes impossible and would require implementing a queuing mechanism, which would quickly become complex and difficult to manage.

The need for client-generated object IDs is further emphasized by the new path-based API and the proposed object creation changes here. Object creation is no longer an async method but instead a simple call like LiveCounter.create(), which returns a value type describing the structure of the object.

Furthermore, the end goal of the LiveObjects plugin is to provide a local-first, offline-first API, where changes can be made entirely offline on the client side and later synced via Realtime across all other clients. This is only possible if the client is able to generate object IDs.

For the REST API, all of the above is not relevant, so we can rely on the server to generate object IDs.

lawrence-forooghian added a commit to ably/ably-liveobjects-swift-plugin that referenced this pull request Jul 29, 2025
There isn't a spec PR for this yet, but it's needed in order to
implement the write spec [1]. Asked about it in [2]. It's implemented in
JS in [3].

Got Cursor to do this.

[1] ably/specification#353
[2] https://github.com/ably/specification/pull/353/files#r2228017382
[3] ably/ably-js#2065
lawrence-forooghian added a commit to ably/ably-liveobjects-swift-plugin that referenced this pull request Jul 30, 2025
There isn't a spec PR for this yet, but it's needed in order to
implement the write spec [1]. Asked about it in [2]. It's implemented in
JS in [3].

Got Cursor to do this.

[1] ably/specification#353
[2] https://github.com/ably/specification/pull/353/files#r2228017382
[3] ably/ably-js#2065
lawrence-forooghian added a commit to ably/ably-liveobjects-swift-plugin that referenced this pull request Jul 30, 2025
haven't done mode checking of RTLC12b

Based on [1] at cb11ba8.

TODO add support for JSON values here and in create — noticed that this
snuck in

[1] ably/specification#353
lawrence-forooghian added a commit to ably/ably-liveobjects-swift-plugin that referenced this pull request Jul 30, 2025
haven't done mode checking of RTLC12b

Based on [1] at cb11ba8.

TODO add support for JSON values here and in create — noticed that this
snuck in

[1] ably/specification#353
lawrence-forooghian added a commit to ably/ably-liveobjects-swift-plugin that referenced this pull request Jul 30, 2025
haven't done mode checking of RTLC12b

Based on [1] at cb11ba8.

TODO add support for JSON values here and in create — noticed that this
snuck in

[1] ably/specification#353
lawrence-forooghian added a commit to ably/ably-liveobjects-swift-plugin that referenced this pull request Jul 30, 2025
We need a type that represents (when considering [1] at cb11ba8) RTO13's
"partial ObjectOperation"; namely an ObjectOperation without an objectId
property. This is something that is easy to represent in TypeScript but
a bit of a faff in Swift; we have to create a new type for it.

Code largely generated by Cursor at my instruction.

[1] ably/specification#353
lawrence-forooghian added a commit to ably/ably-liveobjects-swift-plugin that referenced this pull request Jul 30, 2025
Based on [1] at cb11ba8. Implementation deferred to #47.

[1] ably/specification#353
lawrence-forooghian added a commit to ably/ably-liveobjects-swift-plugin that referenced this pull request Jul 30, 2025
haven't done mode checking of RTLC12b

Based on [1] at cb11ba8.

[1] ably/specification#353
lawrence-forooghian added a commit to ably/ably-liveobjects-swift-plugin that referenced this pull request Jul 30, 2025
We need a type that represents (when considering [1] at cb11ba8) RTO13's
"partial ObjectOperation"; namely an ObjectOperation without an objectId
property. This is something that is easy to represent in TypeScript but
a bit of a faff in Swift; we have to create a new type for it.

Code largely generated by Cursor at my instruction.

[1] ably/specification#353
lawrence-forooghian added a commit to ably/ably-liveobjects-swift-plugin that referenced this pull request Jul 30, 2025
Based on [1] at cb11ba8. Implementation deferred to #47.

[1] ably/specification#353
lawrence-forooghian added a commit to ably/ably-liveobjects-swift-plugin that referenced this pull request Aug 1, 2025
Based on [1] at cb11ba8. Internal interfaces by me, implementation and
tests by Cursor (both with some tweaking by me).

TODO tests for createCounter — copy from map
TODO Unit tests for find-or-create (TODO what)

Haven't implemented:

- the RTO11e etc echoMessages check — deferred to #49
- the RTO11c etc channel mode checking - same reason as 392fae3
- using server time for generating object ID — deferred to #50

[1] ably/specification#353
lawrence-forooghian added a commit to ably/ably-liveobjects-swift-plugin that referenced this pull request Aug 1, 2025
Based on [1] at cb11ba8. Code by me, tests by Cursor and tidied up by
me.

Channel mode checking and echoMessages check omitted as in e65643a.

[1] ably/specification#353
lawrence-forooghian added a commit to ably/ably-liveobjects-swift-plugin that referenced this pull request Aug 1, 2025
Based on [1] at cb11ba8. Internal interfaces by me, implementation and
tests by Cursor (both with some tweaking by me).

Haven't implemented:

- the RTO11e etc echoMessages check — deferred to #49
- the RTO11c etc channel mode checking - same reason as 392fae3
- using server time for generating object ID — deferred to #50

[1] ably/specification#353
lawrence-forooghian added a commit to ably/ably-liveobjects-swift-plugin that referenced this pull request Aug 1, 2025
Based on [1] at cb11ba8. Code by me, tests by Cursor and tidied up by
me.

Channel mode checking and echoMessages check omitted as in e65643a.

[1] ably/specification#353
lawrence-forooghian added a commit to ably/ably-liveobjects-swift-plugin that referenced this pull request Aug 1, 2025
Based on [1] at cb11ba8. Internal interfaces by me, implementation and
tests by Cursor (both with some tweaking by me).

Haven't implemented:

- the RTO11e etc echoMessages check — deferred to #49
- the RTO11c etc channel mode checking - same reason as 392fae3
- using server time for generating object ID — deferred to #50

[1] ably/specification#353
lawrence-forooghian added a commit to ably/ably-liveobjects-swift-plugin that referenced this pull request Aug 1, 2025
Based on [1] at cb11ba8. Code by me, tests by Cursor and tidied up by
me.

Channel mode checking and echoMessages check omitted as in e65643a.

[1] ably/specification#353
lawrence-forooghian added a commit to ably/ably-liveobjects-swift-plugin that referenced this pull request Aug 1, 2025
Based on [1] at cb11ba8. Internal interfaces by me, implementation and
tests by Cursor (both with some tweaking by me).

Haven't implemented:

- the RTO11e etc echoMessages check — deferred to #49
- the RTO11c etc channel mode checking - same reason as 392fae3
- using server time for generating object ID — deferred to #50

[1] ably/specification#353
lawrence-forooghian added a commit to ably/ably-liveobjects-swift-plugin that referenced this pull request Aug 1, 2025
Based on [1] at cb11ba8. Code by me, tests by Cursor and tidied up by
me.

Channel mode checking and echoMessages check omitted as in e65643a.

[1] ably/specification#353
lawrence-forooghian added a commit to ably/ably-liveobjects-swift-plugin that referenced this pull request Aug 1, 2025
Based on [1] at cb11ba8. Internal interfaces by me, implementation and
tests by Cursor (both with some tweaking by me).

Haven't implemented:

- the RTO11e etc echoMessages check — deferred to #49
- the RTO11c etc channel mode checking - same reason as 392fae3
- using server time for generating object ID — deferred to #50

[1] ably/specification#353
lawrence-forooghian added a commit to ably/ably-liveobjects-swift-plugin that referenced this pull request Aug 1, 2025
Based on [1] at cb11ba8. Code by me, tests by Cursor and tidied up by
me.

Channel mode checking and echoMessages check omitted as in e65643a.

[1] ably/specification#353
*** @(RTO11f7)@ Get the current server time as described in "RTO16":#RTO16
*** @(RTO11f8)@ Create an @objectId@ for the new @LiveMap@ object as described in "RTO14":#RTO14, passing in @map@ string as the @type@, the initial value JSON string from "RTO11f5":#RTO11f5, the nonce from "RTO11f6":#RTO11f6, and the server time from "RTO11f7":#RTO11f7
*** @(RTO11f9)@ Set @ObjectMessage.operation.action@ to @ObjectOperationAction.MAP_CREATE@
*** @(RTO11f10)@ Set @ObjectMessage.operation.objectId@ to the @objectId@ created in "RTO11f8":#RTO11f8
Copy link
Collaborator

@sacOO7 sacOO7 Aug 4, 2025

Choose a reason for hiding this comment

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

We can make RTO11f10, RTO11f11.. etc as subpoints of RTO11f9, since we are constructing ObjectMessage for MapCreateOperation right

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think the current structure is correct. The parent RTO11f specifies that an ObjectMessage for a MAP_CREATE action can be created by following its sub-items. You then simply follow these sub-items in sequence to construct the correct ObjectMessage.
It makes sense for RTO11f10 and the following items to be at the same level as RTO11f9 and the other RTO11f* entries, as they all describe the steps required to create the ObjectMessage.

@VeskeR VeskeR force-pushed the PUB-1828/tombstones-and-object-deletes branch from a1c9a6a to 7149569 Compare September 5, 2025 09:05
@VeskeR VeskeR force-pushed the PUB-1829/object-write-API branch from ffed7d7 to 79ad8d9 Compare September 5, 2025 09:11
Copy link
Collaborator

@sacOO7 sacOO7 left a comment

Choose a reason for hiding this comment

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

lgtm

@VeskeR VeskeR force-pushed the PUB-1828/tombstones-and-object-deletes branch from 7149569 to b696a9b Compare September 8, 2025 08:37
Base automatically changed from PUB-1828/tombstones-and-object-deletes to main September 8, 2025 08:38
Adds spec for:
- `RealtimeObjects.createMap`
- `RealtimeObjects.createCounter`

Resolves PUB-1829
Adds spec for:
- `LiveCounter.increment`
- `LiveCounter.decrement`
- `LiveMap.set`
- `LiveMap.remove`

Resolves PUB-1829
@VeskeR VeskeR force-pushed the PUB-1829/object-write-API branch from 79ad8d9 to 3517453 Compare September 8, 2025 08:43
@VeskeR VeskeR merged commit d936ca2 into main Sep 8, 2025
2 checks passed
@VeskeR VeskeR deleted the PUB-1829/object-write-API branch September 8, 2025 08:44
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.

4 participants