Repository navigation
Conversation
ttypic
force-pushed
the
AIT-468/liveobjects-rest-spec-uts
branch
from
November 4, 2026 11:45
af03d95 to
51095e7
Compare
ttypic
marked this pull request as ready for review
November 4, 2026 13:52
ttypic
added a commit
to ably/ably-pubsub-java
that referenced
this pull request
Nov 4, 2026
Implement RestObject (RSL16, RSO1-RSO16 in ably/specification#569) as HttpObject, following ably-js's Rest -> Http naming. It is built into the HTTP client in lib, needs no plugin, and follows the HTTP channel's async convention: blocking methods plus ...Async(..., Callback) variants. - get: compact results are returned as plain Java values; full results decode into HttpLiveMap, HttpLiveCounter, HttpObjectData leaves, or a plain HttpLiveObject for unrecognised types. - publish: operations are built with factories, so each has exactly one body. No operation ids are generated (RSO3f), so a publish goes to the current host only and is never retried on a fallback host, which could apply a batch twice. - generateObjectId: derives the ID locally (RTO14) from per-client server time; concurrent first callers share one /time request. JSON leaf values go on the wire in the OD2g `json` field rather than the OD4d5 `string` + `encoding: "json"` form: the sandbox accepts the latter but drops `encoding` on storage, so JSON would read back as a string. Translate the UTS specs with the uts-to-kotlin skill into :core (uts/unit/objects, uts/integration/standard/objects). The realtime-write REST-read interop test stays in :liveobjects, as it needs the realtime plugin. HttpObjectEdgeCasesTest covers async callbacks, error handling, the no-fallback publish and the shared server-time request. Deviations are recorded in deviations.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ttypic
added a commit
to ably/ably-pubsub-java
that referenced
this pull request
Nov 4, 2026
Implement RestObject (RSL16, RSO1-RSO16 in ably/specification#569) as HttpObject, following ably-js's Rest -> Http naming. It is built into the HTTP client in lib, needs no plugin, and follows the HTTP channel's async convention: blocking methods plus ...Async(..., Callback) variants. - get: compact results are returned as plain Java values; full results decode into HttpLiveMap, HttpLiveCounter, HttpObjectData leaves, or a plain HttpLiveObject for unrecognised types. - publish: operations are built with factories, so each has exactly one body. No operation ids are generated (RSO3f), so a publish goes to the current host only and is never retried on a fallback host, which could apply a batch twice. - generateObjectId: derives the ID locally (RTO14) from per-client server time; concurrent first callers share one /time request. JSON leaf values go on the wire in the OD2g `json` field rather than the OD4d5 `string` + `encoding: "json"` form: the sandbox accepts the latter but drops `encoding` on storage, so JSON would read back as a string. Translate the UTS specs with the uts-to-kotlin skill into :core (uts/unit/objects, uts/integration/standard/objects). The realtime-write REST-read interop test stays in :liveobjects, as it needs the realtime plugin. HttpObjectEdgeCasesTest covers async callbacks, error handling, the no-fallback publish and the shared server-time request. Deviations are recorded in deviations.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The REST counterpart of LiveObjects shipped in ably-js in [1]. This spec PR adds an RSO* section under objects-features so other SDKs have a contract to implement against. Decisions worth recording: - Same Objects plugin, both transports. Rather than introducing a separate PluginType for REST, PC5 now covers both RealtimeObjects and RestObject. This matches the ably-js packaging and keeps a single plugin concept for users. - RestObjectOperation as a flat discriminated union. Common targeting fields plus exactly-one body field, mirroring the wire format and the existing "set exactly one field" patterns (OD2, OOP3, PublishObjectData). A class hierarchy was considered but rejected: consistency with the rest of the Objects spec and the 1:1 mapping to the wire format won, and languages without sum types (Go, Python, PHP) gain little from inheritance either. - Paths are opaque to the SDK. RSO6 explicitly forbids client-side parsing or normalization. Path syntax (wildcards, escaping) is server-defined and can evolve without coupling SDK releases to it. - Full-mode leaves reuse ObjectData. Rather than introducing a parallel RestObjectData type, RSO9c defers to OD5 with explicit guarantees about which fields are unset post-decode. Avoids type duplication. - Client-side object IDs via generateObjectId. Realtime always generates IDs locally (RTO14); REST normally delegates to the server but supports local generation for batches where one operation needs to reference another newly-created object by ID. RSO5j documents this asymmetry so implementers understand why both Create and CreateWithObjectId variants exist. [1] ably/ably-pubsub-js#2109
ttypic
force-pushed
the
AIT-468/liveobjects-rest-spec-uts
branch
from
November 4, 2026 18:21
51095e7 to
2681e40
Compare
ttypic
force-pushed
the
AIT-468/liveobjects-rest-spec
branch
from
November 4, 2026 18:22
e066285 to
6f1518c
Compare
ttypic
added a commit
to ably/ably-pubsub-java
that referenced
this pull request
Nov 4, 2026
Implement RestObject (RSL16, RSO1-RSO16 in ably/specification#569) as HttpObject, following ably-js's Rest -> Http naming. It is built into the HTTP client in lib, needs no plugin, and follows the HTTP channel's async convention: blocking methods plus ...Async(..., Callback) variants. - get: compact results are returned as plain Java values; full results decode into HttpLiveMap, HttpLiveCounter, HttpObjectData leaves, or a plain HttpLiveObject for unrecognised types. - publish: operations are built with factories, so each has exactly one body. No operation ids are generated (RSO3f), so a publish goes to the current host only and is never retried on a fallback host, which could apply a batch twice. - generateObjectId: derives the ID locally (RTO14) from per-client server time; concurrent first callers share one /time request. JSON leaf values go on the wire in the OD2g `json` field rather than the OD4d5 `string` + `encoding: "json"` form: the sandbox accepts the latter but drops `encoding` on storage, so JSON would read back as a string. Translate the UTS specs with the uts-to-kotlin skill into :core (uts/unit/objects, uts/integration/standard/objects). The realtime-write REST-read interop test stays in :liveobjects, as it needs the realtime plugin. HttpObjectEdgeCasesTest covers async callbacks, error handling, the no-fallback publish and the shared server-time request. Deviations are recorded in deviations.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ttypic
added a commit
to ably/ably-pubsub-java
that referenced
this pull request
Nov 5, 2026
Implement RestObject (RSL16, RSO1-RSO16 in ably/specification#569) as HttpObject, following ably-js's Rest -> Http naming. It is built into the HTTP client in lib, needs no plugin, and follows the HTTP channel's async convention: blocking methods plus ...Async(..., Callback) variants. - get: compact results are returned as plain Java values; full results decode into HttpLiveMap, HttpLiveCounter, HttpObjectData leaves, or a plain HttpLiveObject for unrecognised types. - publish: operations are built with factories, so each has exactly one body. No operation ids are generated (RSO3f), so a publish goes to the current host only and is never retried on a fallback host, which could apply a batch twice. - generateObjectId: derives the ID locally (RTO14) from per-client server time; concurrent first callers share one /time request. JSON leaf values go on the wire in the OD2g `json` field rather than the OD4d5 `string` + `encoding: "json"` form: the sandbox accepts the latter but drops `encoding` on storage, so JSON would read back as a string. Translate the UTS specs with the uts-to-kotlin skill into :core (uts/unit/objects, uts/integration/standard/objects). The realtime-write REST-read interop test stays in :liveobjects, as it needs the realtime plugin. HttpObjectEdgeCasesTest covers async callbacks, error handling, the no-fallback publish and the shared server-time request. Deviations are recorded in deviations.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ttypic
added a commit
to ably/ably-pubsub-java
that referenced
this pull request
Nov 5, 2026
Implement RestObject (RSL16, RSO1-RSO16 in ably/specification#569) as HttpObject, following ably-js's Rest -> Http naming. It is built into the HTTP client in lib, needs no plugin, and follows the HTTP channel's async convention: blocking methods plus ...Async(..., Callback) variants. - get: compact results are returned as plain Java values; full results decode into HttpLiveMap, HttpLiveCounter, HttpObjectData leaves, or a plain HttpLiveObject for unrecognised types. - publish: operations are built with factories, so each has exactly one body. No operation ids are generated (RSO3f), so a publish goes to the current host only and is never retried on a fallback host, which could apply a batch twice. - generateObjectId: derives the ID locally (RTO14) from per-client server time; concurrent first callers share one /time request. JSON leaf values go on the wire in the OD2g `json` field rather than the OD4d5 `string` + `encoding: "json"` form: the sandbox accepts the latter but drops `encoding` on storage, so JSON would read back as a string. Translate the UTS specs with the uts-to-kotlin skill into :core (uts/unit/objects, uts/integration/standard/objects). The realtime-write REST-read interop test stays in :liveobjects, as it needs the realtime plugin. HttpObjectEdgeCasesTest covers async callbacks, error handling, the no-fallback publish and the shared server-time request. Deviations are recorded in deviations.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
VeskeR
reviewed
Nov 12, 2026
Contributor
There was a problem hiding this comment.
to your "Points for reviewers" in the PR descrpition:
- JSON leaf encoding - I think it's fixed in yours 2681e40 ? the only suggestion is to move to its own separate PR
- semantics - "full" get responses from the server return
LWW(uppercase). In realtime on wire we use integers -0for this. I think this is something for me to fix in #476 or in a follow-up, I wouldn't block this PR on this. I think you correctly mocked returning uppercaseLWWfor full get responses. generateObjectIddoes need server time, need to clarify #476 or in a follow up- not sure about the impact/where (if) this is an issue
- specify what exactly? I think generally specifying server's formatting is outside the spec and we don't do that?
- not sure what this means. I believe the non-UTS tests in ably-js had tests for these?
I think due to some potential changes to #476 I described above some UTS tests will be slighlty altered here. I'm happy to address 1-3 in a follow-up PR and fix UTS spec in tandem
ttypic
force-pushed
the
AIT-468/liveobjects-rest-spec-uts
branch
from
November 12, 2026 16:28
2681e40 to
034aa18
Compare
Unit specs (mocked HTTP) for RestChannel#object, RestObject#get, RestObject#publish and RestObject#generateObjectId, plus a sandbox integration spec covering end-to-end round-trips in both JSON and msgpack protocol variants. Update the completion-status matrix with RSL16 and the RSO section. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ttypic
force-pushed
the
AIT-468/liveobjects-rest-spec-uts
branch
from
November 12, 2026 16:46
034aa18 to
0d76150
Compare
VeskeR
approved these changes
Nov 13, 2026
VeskeR
left a comment
Contributor
There was a problem hiding this comment.
LGTM.
Agreed in private re #569 (review) - points 1-3 we will address in the follow-up PR to clear out spec inconsistencies, points 4-6 we most likely won't do
ttypic
enabled auto-merge (rebase)
November 13, 2026 16:47
This branch was successfully deployed
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.
Based on #476
Adds UTS test specs for the LiveObjects REST API (
RSL16,RSO1–RSO16) specified in the base PR (AIT-468/liveobjects-rest-spec). Assertions are based on that spec, with the behaviour list in the earlierREST-OBJECTS-PROPOSAL.md(branchuts-liveobjects-rest) used as a checklist for the integration tests.What's added
uts/objects/unit/rest_object_get.mdRestChannel#object(one instance per channel; error 40019 without the plugin),getendpoint and percent-encodedobjectIdsegment,path/compactquery params, paths passed through verbatim (RSO6), compact results returned verbatim (JSON and msgpack), full-mode decoding intoRestLiveMap/RestLiveCounter/ObjectDataleaves (including empty maps and empty or falsy leaves), unrecognised shapes passed through, server errors surfaceduts/objects/unit/rest_object_publish.mdactionfield,id/objectId/pathpreserved verbatim,semanticsand leaf-value encoding per OMP2/OD4, no auto-generatedideven withidempotentRestPublishing, 40003 for zero or multiple body fields, targeting not validated client-side,RestObjectPublishResultdecodinguts/objects/unit/rest_object_generate_id.mdinitialValue,nonceand server time,initialValuecontents, JSON encoding even on a msgpack client, unrecognised semantics / missing body → 40003, nonce of 16+ characters, unique per call, deterministicinitialValue, generated values sent unchanged in*WithObjectIdoperationsuts/objects/integration/rest_object_test.md0,false, ±(2^53 − 1)), counter create/increment, standalonecounterCreate, standalone and path-targetedmapCreate,mapRemove, wildcard path withmapSet,mapRemoveandcounterInc, realtime-written state read via REST, client-generated IDs accepted in one batch, idempotentid, error surfacing for unresolvable targetsuts/docs/completion-status.mdgains anRSL16row and a RestObject (RSO) section.Test IDs use the
objects/unit/...andobjects/integration/...categories, matching the LiveObjects tests already onmain. This branch was cut beforeuts/objects/landed onmain, but the new file names don't clash with it.Points for reviewers
These tests depend on spec wording that is ambiguous or may not match the service:
string+encoding: "json".mainadds an OD2gjsonfield, which suggests the real wire format may differ.semanticson the wire. Requests and mocked full-mode responses use the OMP2 integer (0=LWW). If the server actually returns"lww", the mocked responses need updating.generateObjectIdand server time. RSO4b says the function does no I/O, but RSO4g requires server time per RTO16, which means aGET /timeon a fresh client. The unit tests follow RSO4g: they mock/timeand assert the exact objectId timestamp. If local time is intended, RSO4g should change and so should these tests.objectIdpath encoding. Tests useencode_uri_component, which escapes:and@. RFC 3986 allows both unescaped in a path segment.items.*) and idempotent-idtests, and the compact-map assertions, assume server behaviour that hasn't been checked against the sandbox yet.