Skip to content

[Feature] Path based LiveObjects Implementation#1214

Merged
sacOO7 merged 83 commits into
mainfrom
feature/path-based-liveobjects-implementation
Jul 13, 2026
Merged

[Feature] Path based LiveObjects Implementation#1214
sacOO7 merged 83 commits into
mainfrom
feature/path-based-liveobjects-implementation

Conversation

@sacOO7

@sacOO7 sacOO7 commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

sacOO7 added 6 commits June 8, 2026 18:20
- PathObjectSubscriptionOptions: validate depth fail-fast per RTPO19c1a,
  throwing AblyException with ErrorInfo(400, 40003) when depth <= 0.
  Depth is now a primitive int; the "no depth / infinite depth" state is
  expressed via a new no-arg constructor (mirrors ably-js `{}` options),
  so no null handling is needed
- LiveMapValue: defensively copy binary payloads on creation and access,
  making the RTLMV3d immutability guarantee real for byte[] values
- ObjectData#getBytes: document that the returned array is the underlying
  message payload and must be treated as read-only
- JsonObjectPathObject/JsonArrayPathObject: reword "primitive resolution"
  javadoc for clarity
- LiveMapPathObject#at: fix javadoc equivalence example to compile
  (get() returns base PathObject, so chain via asLiveMap())
…al-public-api

[LiveObjects] Implement path-based LiveObjects public API
@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 233 files, which is 83 over the limit of 150.

To get a review, narrow the scope:
• coderabbit review --type committed # exclude uncommitted changes
• coderabbit review --dir # limit to a subdirectory
• coderabbit review --base # compare against a closer base

Upgrade to a paid plan to raise the limit.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0e6ec95d-537c-41fc-9332-37b6faa3217a

📥 Commits

Reviewing files that changed from the base of the PR and between abcd022 and a44020d.

📒 Files selected for processing (233)
  • .claude/skills/uts-to-kotlin/SKILL.md
  • .claude/skills/uts-to-kotlin/references/objects-mapping.md
  • .claude/skills/uts-to-kotlin/scripts/audit_translation.py
  • .claude/skills/uts-to-kotlin/scripts/resolve_uts.py
  • .claude/skills/uts-to-kotlin/uts-package-mapping.json
  • .github/workflows/check.yml
  • .github/workflows/integration-test.yml
  • android/proguard.txt
  • android/src/main/java/io/ably/lib/realtime/Channel.java
  • examples/src/main/kotlin/com/ably/example/Utils.kt
  • examples/src/main/kotlin/com/ably/example/screen/ColorVotingScreen.kt
  • examples/src/main/kotlin/com/ably/example/screen/ObjectsSyncStatus.kt
  • examples/src/main/kotlin/com/ably/example/screen/TaskManagementScreen.kt
  • java/src/main/java/io/ably/lib/realtime/Channel.java
  • lib/src/main/java/io/ably/lib/liveobjects/LiveObjectsPlugin.java
  • lib/src/main/java/io/ably/lib/liveobjects/RealtimeObject.java
  • lib/src/main/java/io/ably/lib/liveobjects/Subscription.java
  • lib/src/main/java/io/ably/lib/liveobjects/ValueType.java
  • lib/src/main/java/io/ably/lib/liveobjects/adapter/AblyClientAdapter.java
  • lib/src/main/java/io/ably/lib/liveobjects/adapter/Adapter.java
  • lib/src/main/java/io/ably/lib/liveobjects/adapter/package-info.java
  • lib/src/main/java/io/ably/lib/liveobjects/instance/Instance.java
  • lib/src/main/java/io/ably/lib/liveobjects/instance/InstanceListener.java
  • lib/src/main/java/io/ably/lib/liveobjects/instance/InstanceSubscriptionEvent.java
  • lib/src/main/java/io/ably/lib/liveobjects/instance/package-info.java
  • lib/src/main/java/io/ably/lib/liveobjects/instance/types/BinaryInstance.java
  • lib/src/main/java/io/ably/lib/liveobjects/instance/types/BooleanInstance.java
  • lib/src/main/java/io/ably/lib/liveobjects/instance/types/JsonArrayInstance.java
  • lib/src/main/java/io/ably/lib/liveobjects/instance/types/JsonObjectInstance.java
  • lib/src/main/java/io/ably/lib/liveobjects/instance/types/LiveCounterInstance.java
  • lib/src/main/java/io/ably/lib/liveobjects/instance/types/LiveMapInstance.java
  • lib/src/main/java/io/ably/lib/liveobjects/instance/types/NumberInstance.java
  • lib/src/main/java/io/ably/lib/liveobjects/instance/types/StringInstance.java
  • lib/src/main/java/io/ably/lib/liveobjects/instance/types/package-info.java
  • lib/src/main/java/io/ably/lib/liveobjects/message/CounterCreate.java
  • lib/src/main/java/io/ably/lib/liveobjects/message/CounterInc.java
  • lib/src/main/java/io/ably/lib/liveobjects/message/MapClear.java
  • lib/src/main/java/io/ably/lib/liveobjects/message/MapCreate.java
  • lib/src/main/java/io/ably/lib/liveobjects/message/MapRemove.java
  • lib/src/main/java/io/ably/lib/liveobjects/message/MapSet.java
  • lib/src/main/java/io/ably/lib/liveobjects/message/ObjectData.java
  • lib/src/main/java/io/ably/lib/liveobjects/message/ObjectDelete.java
  • lib/src/main/java/io/ably/lib/liveobjects/message/ObjectMessage.java
  • lib/src/main/java/io/ably/lib/liveobjects/message/ObjectOperation.java
  • lib/src/main/java/io/ably/lib/liveobjects/message/ObjectOperationAction.java
  • lib/src/main/java/io/ably/lib/liveobjects/message/ObjectsMapEntry.java
  • lib/src/main/java/io/ably/lib/liveobjects/message/ObjectsMapSemantics.java
  • lib/src/main/java/io/ably/lib/liveobjects/message/package-info.java
  • lib/src/main/java/io/ably/lib/liveobjects/package-info.java
  • lib/src/main/java/io/ably/lib/liveobjects/path/PathObject.java
  • lib/src/main/java/io/ably/lib/liveobjects/path/PathObjectListener.java
  • lib/src/main/java/io/ably/lib/liveobjects/path/PathObjectSubscriptionEvent.java
  • lib/src/main/java/io/ably/lib/liveobjects/path/PathObjectSubscriptionOptions.java
  • lib/src/main/java/io/ably/lib/liveobjects/path/package-info.java
  • lib/src/main/java/io/ably/lib/liveobjects/path/types/BinaryPathObject.java
  • lib/src/main/java/io/ably/lib/liveobjects/path/types/BooleanPathObject.java
  • lib/src/main/java/io/ably/lib/liveobjects/path/types/JsonArrayPathObject.java
  • lib/src/main/java/io/ably/lib/liveobjects/path/types/JsonObjectPathObject.java
  • lib/src/main/java/io/ably/lib/liveobjects/path/types/LiveCounterPathObject.java
  • lib/src/main/java/io/ably/lib/liveobjects/path/types/LiveMapPathObject.java
  • lib/src/main/java/io/ably/lib/liveobjects/path/types/NumberPathObject.java
  • lib/src/main/java/io/ably/lib/liveobjects/path/types/StringPathObject.java
  • lib/src/main/java/io/ably/lib/liveobjects/path/types/package-info.java
  • lib/src/main/java/io/ably/lib/liveobjects/serialization/ObjectJsonSerializer.java
  • lib/src/main/java/io/ably/lib/liveobjects/serialization/ObjectSerializer.java
  • lib/src/main/java/io/ably/lib/liveobjects/state/ObjectStateChange.java
  • lib/src/main/java/io/ably/lib/liveobjects/state/ObjectStateEvent.java
  • lib/src/main/java/io/ably/lib/liveobjects/value/LiveCounter.java
  • lib/src/main/java/io/ably/lib/liveobjects/value/LiveMap.java
  • lib/src/main/java/io/ably/lib/liveobjects/value/LiveMapValue.java
  • lib/src/main/java/io/ably/lib/liveobjects/value/package-info.java
  • lib/src/main/java/io/ably/lib/objects/Adapter.java
  • lib/src/main/java/io/ably/lib/objects/LiveObjectsPlugin.java
  • lib/src/main/java/io/ably/lib/objects/ObjectsCallback.java
  • lib/src/main/java/io/ably/lib/objects/ObjectsHelper.java
  • lib/src/main/java/io/ably/lib/objects/ObjectsSerializer.java
  • lib/src/main/java/io/ably/lib/objects/ObjectsSubscription.java
  • lib/src/main/java/io/ably/lib/objects/RealtimeObjects.java
  • lib/src/main/java/io/ably/lib/objects/type/ObjectLifecycleChange.java
  • lib/src/main/java/io/ably/lib/objects/type/ObjectLifecycleEvent.java
  • lib/src/main/java/io/ably/lib/objects/type/ObjectUpdate.java
  • lib/src/main/java/io/ably/lib/objects/type/counter/LiveCounter.java
  • lib/src/main/java/io/ably/lib/objects/type/counter/LiveCounterChange.java
  • lib/src/main/java/io/ably/lib/objects/type/counter/LiveCounterUpdate.java
  • lib/src/main/java/io/ably/lib/objects/type/map/LiveMap.java
  • lib/src/main/java/io/ably/lib/objects/type/map/LiveMapChange.java
  • lib/src/main/java/io/ably/lib/objects/type/map/LiveMapUpdate.java
  • lib/src/main/java/io/ably/lib/realtime/AblyRealtime.java
  • lib/src/main/java/io/ably/lib/realtime/ChannelBase.java
  • lib/src/main/java/io/ably/lib/realtime/Connection.java
  • lib/src/main/java/io/ably/lib/transport/ConnectionManager.java
  • lib/src/main/java/io/ably/lib/types/ProtocolMessage.java
  • lib/src/main/java/io/ably/lib/types/RecoveryKeyContext.java
  • lib/src/test/java/io/ably/lib/test/realtime/RealtimeChannelTest.java
  • liveobjects/build.gradle.kts
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/DefaultLiveObjectsPlugin.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/DefaultRealtimeObject.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/Errors.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/Helpers.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/ObjectId.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/ObjectsManager.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/ObjectsOperationSource.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/ObjectsPool.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/ObjectsState.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/ObjectsSyncTracker.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/ServerTime.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/Utils.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/DefaultInstance.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/DefaultInstanceSubscriptionEvent.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultBinaryInstance.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultBooleanInstance.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultJsonArrayInstance.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultJsonObjectInstance.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultLiveCounterInstance.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultLiveMapInstance.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultNumberInstance.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultStringInstance.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/message/DefaultObjectMessage.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/message/WireObjectMessage.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/DefaultPathObject.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/DefaultPathObjectSubscriptionEvent.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/PathObjectSubscriptionRegister.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/PathSegments.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultBinaryPathObject.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultBooleanPathObject.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultJsonArrayPathObject.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultJsonObjectPathObject.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultLiveCounterPathObject.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultLiveMapPathObject.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultNumberPathObject.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultStringPathObject.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/serialization/DefaultSerialization.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/serialization/JsonSerialization.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/serialization/MsgpackSerialization.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/BaseRealtimeLiveObject.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/ObjectUpdate.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/ResolvedValue.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livecounter/DefaultLiveCounter.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livecounter/InternalLiveCounter.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livecounter/LiveCounterChangeCoordinator.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livecounter/LiveCounterManager.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livemap/DefaultLiveMap.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livemap/InternalLiveMap.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livemap/LiveMapChangeCoordinator.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livemap/LiveMapEntry.kt
  • liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livemap/LiveMapManager.kt
  • liveobjects/src/main/kotlin/io/ably/lib/objects/ErrorCodes.kt
  • liveobjects/src/main/kotlin/io/ably/lib/objects/Helpers.kt
  • liveobjects/src/main/kotlin/io/ably/lib/objects/ObjectMessage.kt
  • liveobjects/src/main/kotlin/io/ably/lib/objects/ObjectsState.kt
  • liveobjects/src/main/kotlin/io/ably/lib/objects/Utils.kt
  • liveobjects/src/main/kotlin/io/ably/lib/objects/type/BaseRealtimeObject.kt
  • liveobjects/src/main/kotlin/io/ably/lib/objects/type/ObjectLifecycle.kt
  • liveobjects/src/main/kotlin/io/ably/lib/objects/type/livecounter/DefaultLiveCounter.kt
  • liveobjects/src/main/kotlin/io/ably/lib/objects/type/livecounter/LiveCounterManager.kt
  • liveobjects/src/main/kotlin/io/ably/lib/objects/type/livemap/DefaultLiveMap.kt
  • liveobjects/src/main/kotlin/io/ably/lib/objects/type/livemap/LiveMapChangeCoordinator.kt
  • liveobjects/src/main/kotlin/io/ably/lib/objects/type/livemap/LiveMapEntry.kt
  • liveobjects/src/test/kotlin/io/ably/lib/liveobjects/TestUtils.kt
  • liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/DefaultRealtimeObjectTest.kt
  • liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/helpers/PayloadBuilder.kt
  • liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/helpers/RestObjects.kt
  • liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/helpers/fixtures/CounterFixtures.kt
  • liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/helpers/fixtures/DataFixtures.kt
  • liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/helpers/fixtures/MapFixtures.kt
  • liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/setup/IntegrationTest.kt
  • liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/setup/Sandbox.kt
  • liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/DefaultRealtimeObjectAsyncTest.kt
  • liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/HelpersTest.kt
  • liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/ObjectMessageSerializationTest.kt
  • liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/ObjectMessageSizeTest.kt
  • liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/PathSegmentsTest.kt
  • liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/TestHelpers.kt
  • liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/UtilsTest.kt
  • liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/fixtures/ObjectMessageFixtures.kt
  • liveobjects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveCounterTest.kt
  • liveobjects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveMapTest.kt
  • liveobjects/src/test/kotlin/io/ably/lib/objects/integration/DefaultRealtimeObjectsTest.kt
  • liveobjects/src/test/kotlin/io/ably/lib/objects/integration/helpers/Utils.kt
  • liveobjects/src/test/kotlin/io/ably/lib/objects/unit/ObjectIdTest.kt
  • liveobjects/src/test/kotlin/io/ably/lib/objects/unit/ObjectsSyncTrackerTest.kt
  • liveobjects/src/test/kotlin/io/ably/lib/objects/unit/RealtimeObjectsTest.kt
  • liveobjects/src/test/kotlin/io/ably/lib/objects/unit/TestHelpers.kt
  • liveobjects/src/test/kotlin/io/ably/lib/objects/unit/UtilsTest.kt
  • liveobjects/src/test/kotlin/io/ably/lib/objects/unit/objects/DefaultRealtimeObjectsTest.kt
  • liveobjects/src/test/kotlin/io/ably/lib/objects/unit/objects/ObjectsManagerTest.kt
  • liveobjects/src/test/kotlin/io/ably/lib/objects/unit/objects/ObjectsPoolTest.kt
  • liveobjects/src/test/kotlin/io/ably/lib/objects/unit/type/BaseRealtimeObjectTest.kt
  • liveobjects/src/test/kotlin/io/ably/lib/objects/unit/type/livecounter/DefaultLiveCounterTest.kt
  • liveobjects/src/test/kotlin/io/ably/lib/objects/unit/type/livecounter/LiveCounterManagerTest.kt
  • liveobjects/src/test/kotlin/io/ably/lib/objects/unit/type/livemap/DefaultLiveMapTest.kt
  • liveobjects/src/test/kotlin/io/ably/lib/objects/unit/type/livemap/LiveMapManagerTest.kt
  • uts/README.md
  • uts/build.gradle.kts
  • uts/src/test/kotlin/io/ably/lib/deviations.md
  • uts/src/test/kotlin/io/ably/lib/types/Utils.kt
  • uts/src/test/kotlin/io/ably/lib/uts/deviations.md
  • uts/src/test/kotlin/io/ably/lib/uts/infra/Utils.kt
  • uts/src/test/kotlin/io/ably/lib/uts/infra/integration/SandboxApp.kt
  • uts/src/test/kotlin/io/ably/lib/uts/infra/integration/proxy/ProxyManager.kt
  • uts/src/test/kotlin/io/ably/lib/uts/infra/integration/proxy/ProxySession.kt
  • uts/src/test/kotlin/io/ably/lib/uts/infra/unit/ClientFactories.kt
  • uts/src/test/kotlin/io/ably/lib/uts/infra/unit/DefaultPendingConnection.kt
  • uts/src/test/kotlin/io/ably/lib/uts/infra/unit/DefaultPendingRequest.kt
  • uts/src/test/kotlin/io/ably/lib/uts/infra/unit/FakeClock.kt
  • uts/src/test/kotlin/io/ably/lib/uts/infra/unit/MockEvent.kt
  • uts/src/test/kotlin/io/ably/lib/uts/infra/unit/MockHttpClient.kt
  • uts/src/test/kotlin/io/ably/lib/uts/infra/unit/MockHttpEngine.kt
  • uts/src/test/kotlin/io/ably/lib/uts/infra/unit/MockWebSocket.kt
  • uts/src/test/kotlin/io/ably/lib/uts/infra/unit/MockWebSocketEngineFactory.kt
  • uts/src/test/kotlin/io/ably/lib/uts/infra/unit/PendingConnection.kt
  • uts/src/test/kotlin/io/ably/lib/uts/infra/unit/PendingRequest.kt
  • uts/src/test/kotlin/io/ably/lib/uts/infra/unit/Utils.kt
  • uts/src/test/kotlin/io/ably/lib/uts/integration/proxy/liveobjects/ObjectsFaultsTest.kt
  • uts/src/test/kotlin/io/ably/lib/uts/integration/proxy/realtime/AuthReauthTest.kt
  • uts/src/test/kotlin/io/ably/lib/uts/integration/standard/liveobjects/Helpers.kt
  • uts/src/test/kotlin/io/ably/lib/uts/integration/standard/liveobjects/ObjectsLifecycleTest.kt
  • uts/src/test/kotlin/io/ably/lib/uts/integration/standard/liveobjects/ObjectsSyncTest.kt
  • uts/src/test/kotlin/io/ably/lib/uts/integration/standard/realtime/ChannelHistoryTest.kt
  • uts/src/test/kotlin/io/ably/lib/uts/integration/standard/realtime/TokenRequestTest.kt
  • uts/src/test/kotlin/io/ably/lib/uts/private_deviations.md
  • uts/src/test/kotlin/io/ably/lib/uts/unit/liveobjects/Helpers.kt
  • uts/src/test/kotlin/io/ably/lib/uts/unit/liveobjects/InstanceTest.kt
  • uts/src/test/kotlin/io/ably/lib/uts/unit/liveobjects/InternalLiveCounterApiTest.kt
  • uts/src/test/kotlin/io/ably/lib/uts/unit/liveobjects/InternalLiveMapApiTest.kt
  • uts/src/test/kotlin/io/ably/lib/uts/unit/liveobjects/LiveObjectSubscribeTest.kt
  • uts/src/test/kotlin/io/ably/lib/uts/unit/liveobjects/PathObjectMutationsTest.kt
  • uts/src/test/kotlin/io/ably/lib/uts/unit/liveobjects/PathObjectSubscribeTest.kt
  • uts/src/test/kotlin/io/ably/lib/uts/unit/liveobjects/PathObjectTest.kt
  • uts/src/test/kotlin/io/ably/lib/uts/unit/liveobjects/PublicObjectMessageTest.kt
  • uts/src/test/kotlin/io/ably/lib/uts/unit/liveobjects/RealtimeObjectTest.kt
  • uts/src/test/kotlin/io/ably/lib/uts/unit/liveobjects/ValueTypesTest.kt
  • uts/src/test/kotlin/io/ably/lib/uts/unit/realtime/ConnectionRecoveryTest.kt

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/path-based-liveobjects-implementation

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot temporarily deployed to staging/pull/1214/features June 11, 2026 12:42 Inactive
@github-actions github-actions Bot temporarily deployed to staging/pull/1214/javadoc June 11, 2026 12:43 Inactive
sacOO7 and others added 3 commits June 15, 2026 19:34
…ccessor

Introduce the public, strongly-typed, path-based LiveObjects entry point on a
realtime channel, accessed via `channel.object`.

- RealtimeObject: exposes `get()` returning the root LiveMapPathObject, and
  extends ObjectStateChange to subscribe to objects sync-state events
  (on/off/offAll).
- ObjectStateChange / ObjectStateEvent: the SYNCING/SYNCED sync-state
  subscription API surface.
- ChannelBase.object: a public field providing `channel.object` access. When
  the LiveObjects plugin is not installed, the field is assigned
  RealtimeObject.Unavailable - a null-object guard whose methods fail fast with
  a clear plugin-missing error (statusCode 400, code 40019) instead of an NPE,
  keeping the `channel.object.<method>()` syntax consistent in both cases.

The plugin-present branch is intentionally left as a TODO until the LiveObjects
plugin exposes the new io.ably.lib.object.RealtimeObject type (getInstance
currently returns the legacy io.ably.lib.objects.RealtimeObjects).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ture

- Replaced ObjectsSubscription import with Subscription as per requirement
…tion-for-path-based-interfaces

[AIT-928] feat(liveobjects): add path-based RealtimeObject and channel.object accessor
@github-actions github-actions Bot temporarily deployed to staging/pull/1214/features June 16, 2026 12:01 Inactive
@github-actions github-actions Bot temporarily deployed to staging/pull/1214/javadoc June 16, 2026 12:02 Inactive
sacOO7 and others added 16 commits June 16, 2026 23:11
…mplementation' into chore/liveobjects-add-basic-implementation
- Marked PathObject#getValue as nullable when value doesn't exist at given path
- Implemented JsonSerializer annotation for better json handling
Point the JSON and MsgPack serializers in io.ably.lib.object.serialization
at the new WireObjectMessage wire model instead of the legacy
io.ably.lib.objects.ObjectMessage, so the new `object` package has no
dependency on the legacy `objects` package.

- DefaultSerialization: implement the new ObjectSerializer interface and
  (de)serialize WireObjectMessage arrays (reflectively loaded via
  ObjectSerializer.Holder).
- Json/MsgpackSerialization: bind the Wire* types; replace legacy
  objectError with the object package's objectStateError (same 500/92000).
- WireObjectMessage: restore the gson annotations required for wire-format
  fidelity - @SerializedName("object") on objectState and
  @JsonAdapter(WireObjectDataJsonSerializer) on WireObjectData.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fixes checkstyle AvoidStarImport violation on com.google.gson.*.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
sacOO7 added 3 commits July 9, 2026 16:35
…er overloads

The parameterless increment()/decrement() on both DefaultLiveCounterPathObject and
DefaultLiveCounterInstance duplicated the full body of their Number counterparts with
a hardcoded 1. Make them delegate to increment(1)/decrement(1) instead. All spec
checks live in the parameterized overload, and the default-of-1 spec points
(RTPO17a1/RTPO18a1, RTINS14a1/RTINS15a1) are preserved on the delegating methods.
Pure refactor, no behaviour change.
…opagation

Rename the DefaultRealtimeObject async bridges for clarity: asyncApi -> asyncFuture
(generic, value-returning) and asyncVoidApi -> asyncVoidFuture (the Unit->Void adapter
required by the Java write APIs), updating all call sites. Behaviour is unchanged; the
thenApply { null } bridge stays because kotlinx's future builder cannot produce a
CompletableFuture<Void> (its type param is non-null, Void's only value is null).

Add DefaultRealtimeObjectAsyncTest asserting result and exception propagation for both
helpers, and - crucially - that a failed operation does not cancel the shared sequential
scope for subsequent operations, locking in the SupervisorJob failure-isolation guarantee.
[AIT-1008] Translate LiveObjects `objects` UTS test specs to Kotlin tests
@github-actions github-actions Bot temporarily deployed to staging/pull/1214/features July 9, 2026 11:38 Inactive
@github-actions github-actions Bot temporarily deployed to staging/pull/1214/javadoc July 9, 2026 11:40 Inactive
…ntation

[AIT-934] feat(liveobjects): `LiveObjects` implementation to new path-based API (Kotlin)
@github-actions github-actions Bot temporarily deployed to staging/pull/1214/features July 9, 2026 11:50 Inactive
@github-actions github-actions Bot temporarily deployed to staging/pull/1214/javadoc July 9, 2026 11:52 Inactive
sacOO7 added 8 commits July 9, 2026 17:30
getOrPut on a ConcurrentHashMap may invoke its factory on a losing thread during a
concurrent first-time getInstance, constructing a duplicate DefaultRealtimeObject whose
init-started coroutine would then leak. computeIfAbsent runs the factory at most once per
channel, so exactly one instance is created. It needs Java 8 / Android API 24, already
required by this module's CompletableFuture-based public API.
…ync waiters (RTO20e/e1)

Two genuine spec-compliance bugs surfaced by cross-checking the UTS unit
suite against ably-js (the reference implementation) — both confirmed at
source level against objects-features.md, with ably-js compliant on each.

RTO23e — get() threw 90001 on a DETACHED channel instead of re-attaching:
get() ran the full access-config check (which gates on channel state)
before getRootAsync's ensure-active-channel could run. It now uses a
mode-only check (throwIfMissingObjectSubscribeMode, RTO23a) and delegates
channel state to ensureAttached (RTO23e/RTL33): DETACHED re-attaches and
resolves, only FAILED rejects with 90001. The full check remains on the
access methods on/off/offAll (RTO25b).

RTO20e/RTO20e1 — orphaned sync waiter could hang publishAndApply forever:
the shared syncCompletionWaiter field was overwritten by every
startNewSync, so a write awaiting SYNCED across the ordinary
ATTACHED(HAS_OBJECTS) -> OBJECT_SYNC re-sync pair awaited a deferred
nobody would ever complete (hang), and a DETACHED racing the ACK nulled
the field instead of failing the wait with 92008. Replaced with an
event-driven waiter set: awaitSyncCompletion() registers a tracked
deferred + one-shot once(SYNCED) listener (whichever sync completes
resolves it), and failSyncWaiters(error) rejects all pending waiters on
DETACHED/SUSPENDED/FAILED. Mirrors ably-js publishAndApply's
once(synced) + reject-on-channel-state pattern, including symmetric
listener cleanup; ensureSynced gets the same off()-in-finally hygiene.

UTS suite: un-gate the now-passing RTO23e/RTO20e/RTO20e1 tests; adopt the
canonical serial helpers (POOL_SERIAL/ackSerial/remoteSerial/
belowAckSerial) from the spec's new Canonical Constants; align counter
fixtures with the corrected spec (SI-1: count 0 + createOp initial);
single-object RTPO19e2 sync fixture (root retained per RTO5c2a); fix an
RTO24c1 test race (seed's own update leaking into the depth-2 listener);
rename LiveMapApiTest/LiveCounterApiTest to Internal* to match the
renamed spec files.

deviations.md: restructure into four actionability groups (open bugs /
shared gap / expected typed-SDK adaptations / intentional), remove the
fixed RTO23e + RTO20e/e1 entries, reframe RTO18d as an intentional
deviation (spec point questioned), and reconcile every cited test name,
UTS id and spec point against the suite (audited programmatically).

Verified: :uts:runUtsUnitTests liveobjects 183/0, runLiveObjectUnitTests
green, checkWithCodenarc/checkstyleMain/checkstyleTest clean.
…Serial; doc typo

- objectsClient emitted ATTACHED with the caller's attachedSerial but
  always followed with an OBJECT_SYNC for "sync1:"; a caller overriding
  the serial (e.g. "sync2:cursor") would get mismatched sync ids that
  register as a second new sync (RTO5a2). The sync id is now derived
  from attachedSerial. No current caller hits the mismatch — latent
  footgun only; all 183 liveobjects UTS tests unchanged and green.
- Fix the dangling ";." in throwIfMissingObjectSubscribeMode's doc.
fix(uts): wait for outbound publish before injecting ACK in RTO20 test

The ack-after-echo test raced: increment() dispatches its publish on
sequentialScope, so the manually injected ACK for msgSerial 0 could
reach ConnectionManager before the publish was pending, where
PendingMessages.ack discards it - incFuture never completed and the
test hung with UncompletedCoroutinesError (flaky on CI, e.g. runs
29081250922 and 29236093941).
…in-implementation

[AIT-1019] feat(liveobjects): implement remaining path-based API — parent references, event bubbling etc
@github-actions github-actions Bot temporarily deployed to staging/pull/1214/features July 13, 2026 09:11 Inactive
@github-actions github-actions Bot temporarily deployed to staging/pull/1214/javadoc July 13, 2026 09:12 Inactive
[AIT-1103] fix(liveobjects): Fix UTS unit tests
@sacOO7 sacOO7 marked this pull request as ready for review July 13, 2026 09:16
@github-actions github-actions Bot temporarily deployed to staging/pull/1214/features July 13, 2026 09:17 Inactive
@github-actions github-actions Bot temporarily deployed to staging/pull/1214/javadoc July 13, 2026 09:18 Inactive
@sacOO7 sacOO7 requested a review from ttypic July 13, 2026 09:21

@ttypic ttypic left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

…overhead

of updating the same, going forward it's better to grab context from README.md
or generate `index.html` doc file from `README.md`
@sacOO7 sacOO7 merged commit b03edbf into main Jul 13, 2026
15 checks passed
@sacOO7 sacOO7 deleted the feature/path-based-liveobjects-implementation branch July 13, 2026 09:57
@sacOO7 sacOO7 mentioned this pull request Jul 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants