Skip to content

[ECO-5482][LiveObjects] Implement realtime write API#1141

Merged
sacOO7 merged 10 commits intomainfrom
feature/liveobjects-realtime-write-api-refactored
Aug 8, 2025
Merged

[ECO-5482][LiveObjects] Implement realtime write API#1141
sacOO7 merged 10 commits intomainfrom
feature/liveobjects-realtime-write-api-refactored

Conversation

@sacOO7
Copy link
Collaborator

@sacOO7 sacOO7 commented Aug 6, 2025

      Map<String, LiveMapValue> entries = Map.of(
          "string", LiveMapValue.of("Hello"),
          "number", LiveMapValue.of(42),
          "boolean", LiveMapValue.of(true),
          "binary", LiveMapValue.of(new byte[]{1, 2, 3}),
          "array", LiveMapValue.of(new JsonArray()),
          "object", LiveMapValue.of(new JsonObject()),
          "counter", LiveMapValue.of(liveObjects.createCounter()),
          "nested", LiveMapValue.of(liveObjects.createMap())
      );
      
      LiveMap map = liveObjects.createMap(entries);

Reason to choose

  1. Type Safety: Compile-time type checking
  2. Immutability: of() methods return immutable objects
  3. Readability: Clear intent
  4. Consistency: Standardized across different libraries
// Optional.of() - creates Optional with non-null value
Optional<String> name = Optional.of("John");
Optional<Integer> age = Optional.of(25);

JsonPrimitive stringValue = JsonPrimitive.of("hello");
JsonPrimitive numberValue = JsonPrimitive.of(42);
JsonPrimitive booleanValue = JsonPrimitive.of(true);

// List.of() - creates immutable lists, same goes for Set and Map
List<String> names = List.of("Alice", "Bob", "Charlie");
List<Integer> numbers = List.of(1, 2, 3, 4, 5);

  1. Method Overloading: Multiple overloads for different numbers of parameters

Summary by CodeRabbit

  • New Features

    • Introduced type-safe value handling for live maps and counters using a new LiveMapValue abstraction.
    • Added support for creating and updating live maps and counters directly via the realtime API.
    • Enabled incrementing and decrementing counters by arbitrary amounts, with both synchronous and asynchronous methods.
    • Implemented server time retrieval and nonce generation for object creation.
    • Extended adapter interface to expose client options, connection management, and server time.
  • Improvements

    • Enhanced API safety by replacing generic value types with explicit, type-checked accessors for map and counter values.
    • Improved error handling and validation for input parameters and API configuration.
    • Updated documentation and method signatures for clarity and type safety.
    • Refined internal object ID generation with secure hashing and base64 encoding.
  • Bug Fixes

    • Corrected error message pluralization for object message size validation.
  • Tests

    • Added comprehensive tests for realtime map and counter operations, type-safe value access, nonce generation, and object ID creation.
    • Refactored tests to use safe accessors and improved type safety.
  • Chores

    • Renamed error codes for clarity and removed unused imports.

sacOO7 added 9 commits July 29, 2025 16:45
- Enhanced LiveObjects interface with realtime write operations and spec annotations
- Extended Adapter and LiveObjectsAdapter with realtime write support
- Implemented foundational API structure for realtime object modifications
…perations

- Updated LiveCounter interface with realtime write methods and spec references
- Modified LiveMap interface to support realtime write capabilities
- Added comprehensive API documentation for realtime operations
…me operations

- Implemented comprehensive LiveMapValue class for map value handling
- Added ServerTime utility for server timestamp management
- Provided foundational support classes for realtime write operations
- Enhanced DefaultLiveObjects with realtime write operation implementations
- Updated Helpers with realtime write support utilities
- Modified Utils to support realtime operation context and validation
- Updated ObjectId with realtime operation support
- Modified ErrorCodes for realtime write error handling
- Enhanced MsgpackSerialization for realtime operation serialization
- Updated BaseLiveObject with realtime write base functionality
…r and DefaultLiveMap

- Added runBlocking synchronous wrappers for increment/decrement in DefaultLiveCounter
- Updated DefaultLiveMap.get() to return LiveMapValue instead of Any?
- Integrated asyncScope for coroutine-based realtime operations
- Added kotlinx.coroutines.runBlocking import for synchronous API support
… operations

- Added imports for LiveCounter, LiveMap, LiveMapValue types
- Extended imports for BaseLiveObject and ObjectType support
- Updated LiveMapEntry to support enhanced type system for realtime write operations
- Updated DefaultLiveCounterTest with realtime write test scenarios
- Enhanced DefaultLiveMapTest with comprehensive realtime operation tests
- Added LiveMapValue import and removed unused type imports
- Expanded test coverage for realtime increment/decrement and map operations
- Removed unused imports from DefaultLiveObjectsTest (JsonArray, JsonObject, Binary)
- Updated PayloadBuilder helper for realtime write operation support
- Streamlined import statements for better code organization
@coderabbitai
Copy link

coderabbitai bot commented Aug 6, 2025

Walkthrough

This update implements the realtime write API for LiveObjects, including LiveMap and LiveCounter. It introduces type-safe value handling with a new LiveMapValue abstraction, completes the implementation of synchronous and asynchronous creation and mutation methods, and adds server time and nonce utilities. Test suites are updated for type safety and new behaviors.

Changes

Cohort / File(s) Change Summary
LiveObjects Write API Implementation
live-objects/src/main/kotlin/io/ably/lib/objects/DefaultLiveObjects.kt, live-objects/src/main/kotlin/io/ably/lib/objects/Helpers.kt, live-objects/src/main/kotlin/io/ably/lib/objects/Utils.kt, live-objects/src/main/kotlin/io/ably/lib/objects/ObjectId.kt, live-objects/src/main/kotlin/io/ably/lib/objects/ServerTime.kt
Implements synchronous and asynchronous realtime write methods for creating and mutating LiveMap and LiveCounter. Adds input validation, message publishing, nonce and server time utilities, and error helpers.
Type Safety and Value Abstraction
lib/src/main/java/io/ably/lib/objects/type/map/LiveMapValue.java, lib/src/main/java/io/ably/lib/objects/type/map/LiveMap.java, live-objects/src/main/kotlin/io/ably/lib/objects/type/livemap/DefaultLiveMap.kt, live-objects/src/main/kotlin/io/ably/lib/objects/type/livemap/LiveMapEntry.kt
Introduces LiveMapValue as a union type for map values, updates interfaces and implementations to use this type, and ensures all map value accesses and mutations are type-safe.
LiveCounter Enhancements
lib/src/main/java/io/ably/lib/objects/type/counter/LiveCounter.java, live-objects/src/main/kotlin/io/ably/lib/objects/type/livecounter/DefaultLiveCounter.kt
Updates increment/decrement methods to accept arbitrary amounts, generalizes value types, and implements the actual mutation logic for counters.
API and Interface Extensions
lib/src/main/java/io/ably/lib/objects/LiveObjectsAdapter.java, lib/src/main/java/io/ably/lib/objects/Adapter.java, lib/src/main/java/io/ably/lib/objects/LiveObjects.java
Adds methods for accessing client options, connection manager, and server time. Refactors LiveObjects interface for type safety and generalization.
Error Handling and Codes
live-objects/src/main/kotlin/io/ably/lib/objects/ErrorCodes.kt
Renames error code for invalid input parameters.
Visibility and Internal Refactoring
live-objects/src/main/kotlin/io/ably/lib/objects/type/BaseLiveObject.kt
Changes objectType property visibility from private to internal.
Serialization and Imports
live-objects/src/main/kotlin/io/ably/lib/objects/serialization/MsgpackSerialization.kt, live-objects/src/test/kotlin/io/ably/lib/objects/integration/helpers/PayloadBuilder.kt
Removes unused imports and switches nonce generation to new utility.
Test Suite Updates
live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveCounterTest.kt, live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveMapTest.kt, live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveObjectsTest.kt, live-objects/src/test/kotlin/io/ably/lib/objects/unit/ObjectIdTest.kt, live-objects/src/test/kotlin/io/ably/lib/objects/unit/ObjectMessageSizeTest.kt, live-objects/src/test/kotlin/io/ably/lib/objects/unit/UtilsTest.kt
Refactors tests to use type-safe accessors, adds new tests for realtime API usage, and verifies nonce and object ID generation.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant LiveObjects
    participant Adapter
    participant AblyRealtime

    Client->>LiveObjects: createMap()/createCounter()
    LiveObjects->>Adapter: getClientOptions(), getConnectionManager(), getTime()
    Adapter->>AblyRealtime: (delegates)
    LiveObjects->>AblyRealtime: Publish ObjectMessage (MapCreate/CounterCreate)
    AblyRealtime-->>LiveObjects: Ack/Result
    LiveObjects-->>Client: Return LiveMap/LiveCounter instance

    Client->>LiveMap/LiveCounter: set()/increment()/decrement()
    LiveMap/LiveCounter->>LiveObjects: Publish mutation ObjectMessage
    LiveObjects->>AblyRealtime: Publish mutation
    AblyRealtime-->>LiveObjects: Ack/Result
    LiveObjects-->>Client: Operation result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Assessment against linked issues

Objective Addressed Explanation
Implement write API for objects, livemap, and livecounter (#1133, ECO-5482)
ObjectMessage should be sent over realtime connection using core SDK (#1133, ECO-5482)

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
None found All observed changes are directly related to the implementation and testing of the realtime write API for LiveObjects, LiveMap, and LiveCounter, or necessary refactoring for type safety and supporting utilities.

Suggested reviewers

  • ttypic

Poem

A rabbit hopped through fields of code,
With type-safe values now bestowed.
Maps and counters, live and bright,
Can write in realtime, day or night.
Nonces and hashes, tests anew—
The warren’s work is nearly through!
🐇✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/liveobjects-realtime-write-api-refactored

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions bot temporarily deployed to staging/pull/1141/features August 6, 2025 12:32 Inactive
@sacOO7 sacOO7 changed the title Feature/liveobjects realtime write api refactored [ECO-5482][LiveObjects] Implement realtime write API Aug 6, 2025
@sacOO7 sacOO7 force-pushed the feature/liveobjects-realtime-write-api-refactored branch from 1d6add2 to b32c283 Compare August 6, 2025 12:34
@github-actions github-actions bot temporarily deployed to staging/pull/1141/features August 6, 2025 12:35 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1141/javadoc August 6, 2025 12:36 Inactive
@sacOO7 sacOO7 marked this pull request as ready for review August 7, 2025 07:10
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
live-objects/src/main/kotlin/io/ably/lib/objects/Utils.kt (1)

114-117: Consider using cryptographically secure random for nonce generation.

The current implementation uses Kotlin's random() which relies on java.util.Random, which is not cryptographically secure. For object creation nonces that may be used in security-sensitive contexts, consider using SecureRandom.

-/**
- * Generates a random nonce string for object creation.
- */
-internal fun generateNonce(): String {
-  val chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" // avoid calculation using range
-  return (1..16).map { chars.random() }.joinToString("")
-}
+/**
+ * Generates a random nonce string for object creation.
+ */
+internal fun generateNonce(): String {
+  val chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+  val secureRandom = java.security.SecureRandom()
+  return (1..16).map { chars[secureRandom.nextInt(chars.length)] }.joinToString("")
+}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between efe730e and b32c283.

📒 Files selected for processing (24)
  • lib/src/main/java/io/ably/lib/objects/Adapter.java (2 hunks)
  • lib/src/main/java/io/ably/lib/objects/LiveObjects.java (5 hunks)
  • lib/src/main/java/io/ably/lib/objects/LiveObjectsAdapter.java (2 hunks)
  • lib/src/main/java/io/ably/lib/objects/type/counter/LiveCounter.java (1 hunks)
  • lib/src/main/java/io/ably/lib/objects/type/map/LiveMap.java (4 hunks)
  • lib/src/main/java/io/ably/lib/objects/type/map/LiveMapValue.java (1 hunks)
  • live-objects/src/main/kotlin/io/ably/lib/objects/DefaultLiveObjects.kt (3 hunks)
  • live-objects/src/main/kotlin/io/ably/lib/objects/ErrorCodes.kt (1 hunks)
  • live-objects/src/main/kotlin/io/ably/lib/objects/Helpers.kt (5 hunks)
  • live-objects/src/main/kotlin/io/ably/lib/objects/ObjectId.kt (2 hunks)
  • live-objects/src/main/kotlin/io/ably/lib/objects/ServerTime.kt (1 hunks)
  • live-objects/src/main/kotlin/io/ably/lib/objects/Utils.kt (3 hunks)
  • live-objects/src/main/kotlin/io/ably/lib/objects/serialization/MsgpackSerialization.kt (0 hunks)
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/BaseLiveObject.kt (1 hunks)
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/livecounter/DefaultLiveCounter.kt (4 hunks)
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/livemap/DefaultLiveMap.kt (7 hunks)
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/livemap/LiveMapEntry.kt (3 hunks)
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveCounterTest.kt (5 hunks)
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveMapTest.kt (10 hunks)
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveObjectsTest.kt (4 hunks)
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/helpers/PayloadBuilder.kt (3 hunks)
  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/ObjectIdTest.kt (1 hunks)
  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/ObjectMessageSizeTest.kt (1 hunks)
  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/UtilsTest.kt (1 hunks)
💤 Files with no reviewable changes (1)
  • live-objects/src/main/kotlin/io/ably/lib/objects/serialization/MsgpackSerialization.kt
🧰 Additional context used
🧠 Learnings (18)
📓 Common learnings
Learnt from: sacOO7
PR: ably/ably-java#1106
File: live-objects/src/main/kotlin/io/ably/lib/objects/serialization/Serialization.kt:25-29
Timestamp: 2025-06-23T14:18:25.315Z
Learning: In the ably-java codebase, the DefaultLiveObjectSerializer class methods like writeMsgpackArray will have their type signatures updated to be non-nullable since the calling sites ensure objects are never null when passed to these methods.
Learnt from: sacOO7
PR: ably/ably-java#1106
File: live-objects/src/main/kotlin/io/ably/lib/objects/serialization/Serialization.kt:38-46
Timestamp: 2025-06-23T14:14:17.847Z
Learning: In the ably-java codebase, the DefaultLiveObjectSerializer class uses intentional unsafe casting (`objects as Array<ObjectMessage>`) without type validation in both writeMsgpackArray and asJsonArray methods. This is a deliberate design decision to keep the dynamically-loaded class simple and let ClassCastException occur naturally for type mismatches.
Learnt from: sacOO7
PR: ably/ably-java#1087
File: lib/src/main/java/io/ably/lib/objects/LiveObjectsAdapter.java:32-34
Timestamp: 2025-05-27T12:11:25.084Z
Learning: In LiveObjects implementation (lib/src/main/java/io/ably/lib/objects/LiveObjectsAdapter.java), the send method intentionally hardcodes queueEvents to true rather than respecting ably.options.queueMessages. This is because LiveObjects requires reliable message delivery to ensure proper state synchronization and acknowledgment, unlike other realtime components that may allow configurable queuing behavior.
Learnt from: sacOO7
PR: ably/ably-java#1092
File: live-objects/src/test/kotlin/io/ably/lib/objects/TestUtils.kt:21-32
Timestamp: 2025-06-03T09:15:15.338Z
Learning: In test utility code for the Ably Java Live Objects module, the team prefers to keep reflection-based field access utilities simple without additional error handling, allowing tests to fail fast if incorrect field names are used.
Learnt from: sacOO7
PR: ably/ably-java#1130
File: live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveMapTest.kt:241-241
Timestamp: 2025-08-01T10:30:27.049Z
Learning: In DefaultLiveMapTest.kt integration tests, operations are performed sequentially one after another, and subscription callback list updates happen one at a time, so thread-safe collections are not needed for collecting updates in test scenarios.
Learnt from: sacOO7
PR: ably/ably-java#1120
File: live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveObjectsTest.kt:0-0
Timestamp: 2025-08-01T09:53:16.730Z
Learning: In the ably-java LiveObjects test code, extension properties with capital letter names (like `State`, `ObjectId`) are defined in live-objects/src/test/kotlin/io/ably/lib/objects/integration/helpers/Utils.kt to provide access to internal fields of concrete implementations through their public interfaces. For example, `LiveObjects.State` casts to `DefaultLiveObjects` to access the internal `state` field for testing purposes.
Learnt from: sacOO7
PR: ably/ably-java#1113
File: live-objects/src/test/kotlin/io/ably/lib/objects/unit/type/livemap/LiveMapManagerTest.kt:16-16
Timestamp: 2025-08-01T05:50:33.039Z
Learning: In LiveMapManagerTest.kt, the private field `livemapManager` is used extensively in the `shouldCalculateMapDifferenceCorrectly` test method to test the `calculateUpdateFromDataDiff` functionality across multiple test scenarios, so it should not be removed as unused.
Learnt from: sacOO7
PR: ably/ably-java#1120
File: live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveObjectsTest.kt:0-0
Timestamp: 2025-08-01T09:53:16.730Z
Learning: In the ably-java LiveObjects test code, an extension property `State` (capital S) is defined on the `LiveObjects` interface in live-objects/src/test/kotlin/io/ably/lib/objects/integration/helpers/Utils.kt to provide access to the internal `state` field by casting to `DefaultLiveObjects`. This allows tests to access internal state for verification purposes.
Learnt from: sacOO7
PR: ably/ably-java#1085
File: lib/src/main/java/io/ably/lib/objects/LiveObjects.java:0-0
Timestamp: 2025-05-20T13:12:19.013Z
Learning: The LiveObjects interface does not currently include public API methods for resource management (dispose) or change listeners, as these features are not yet implemented.
Learnt from: sacOO7
PR: ably/ably-java#1113
File: live-objects/src/test/kotlin/io/ably/lib/objects/unit/type/livemap/LiveMapManagerTest.kt:16-16
Timestamp: 2025-08-01T05:50:33.039Z
Learning: In LiveMapManagerTest.kt, the private field `livemapManager` is used in the `shouldCalculateMapDifferenceCorrectly` test method to test the `calculateUpdateFromDataDiff` functionality, so it should not be removed as unused.
Learnt from: sacOO7
PR: ably/ably-java#1092
File: live-objects/src/test/kotlin/io/ably/lib/objects/TestUtils.kt:48-61
Timestamp: 2025-06-03T09:15:18.827Z
Learning: User sacOO7 prefers simple test utilities without extensive error handling, believing tests should fail fast if incorrect field/method names are used rather than having defensive programming.
📚 Learning: in the ably-java liveobjects test code, extension properties with capital letter names (like `state`...
Learnt from: sacOO7
PR: ably/ably-java#1120
File: live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveObjectsTest.kt:0-0
Timestamp: 2025-08-01T09:53:16.730Z
Learning: In the ably-java LiveObjects test code, extension properties with capital letter names (like `State`, `ObjectId`) are defined in live-objects/src/test/kotlin/io/ably/lib/objects/integration/helpers/Utils.kt to provide access to internal fields of concrete implementations through their public interfaces. For example, `LiveObjects.State` casts to `DefaultLiveObjects` to access the internal `state` field for testing purposes.

Applied to files:

  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/UtilsTest.kt
  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/ObjectIdTest.kt
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveObjectsTest.kt
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveCounterTest.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/Helpers.kt
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveMapTest.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/ObjectId.kt
  • lib/src/main/java/io/ably/lib/objects/LiveObjectsAdapter.java
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/livecounter/DefaultLiveCounter.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/livemap/DefaultLiveMap.kt
  • lib/src/main/java/io/ably/lib/objects/type/map/LiveMapValue.java
  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/ObjectMessageSizeTest.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/ServerTime.kt
  • lib/src/main/java/io/ably/lib/objects/LiveObjects.java
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/BaseLiveObject.kt
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/helpers/PayloadBuilder.kt
  • lib/src/main/java/io/ably/lib/objects/type/map/LiveMap.java
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/livemap/LiveMapEntry.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/Utils.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/DefaultLiveObjects.kt
📚 Learning: in livemapmanagertest.kt, the private field `livemapmanager` is used in the `shouldcalculatemapdiffe...
Learnt from: sacOO7
PR: ably/ably-java#1113
File: live-objects/src/test/kotlin/io/ably/lib/objects/unit/type/livemap/LiveMapManagerTest.kt:16-16
Timestamp: 2025-08-01T05:50:33.039Z
Learning: In LiveMapManagerTest.kt, the private field `livemapManager` is used in the `shouldCalculateMapDifferenceCorrectly` test method to test the `calculateUpdateFromDataDiff` functionality, so it should not be removed as unused.

Applied to files:

  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/ObjectIdTest.kt
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveObjectsTest.kt
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveCounterTest.kt
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveMapTest.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/livemap/DefaultLiveMap.kt
  • lib/src/main/java/io/ably/lib/objects/LiveObjects.java
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/helpers/PayloadBuilder.kt
  • lib/src/main/java/io/ably/lib/objects/type/map/LiveMap.java
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/livemap/LiveMapEntry.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/DefaultLiveObjects.kt
📚 Learning: in livemapmanagertest.kt, the private field `livemapmanager` is used extensively in the `shouldcalcu...
Learnt from: sacOO7
PR: ably/ably-java#1113
File: live-objects/src/test/kotlin/io/ably/lib/objects/unit/type/livemap/LiveMapManagerTest.kt:16-16
Timestamp: 2025-08-01T05:50:33.039Z
Learning: In LiveMapManagerTest.kt, the private field `livemapManager` is used extensively in the `shouldCalculateMapDifferenceCorrectly` test method to test the `calculateUpdateFromDataDiff` functionality across multiple test scenarios, so it should not be removed as unused.

Applied to files:

  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/ObjectIdTest.kt
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveObjectsTest.kt
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveCounterTest.kt
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveMapTest.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/livemap/DefaultLiveMap.kt
  • lib/src/main/java/io/ably/lib/objects/LiveObjects.java
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/helpers/PayloadBuilder.kt
  • lib/src/main/java/io/ably/lib/objects/type/map/LiveMap.java
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/livemap/LiveMapEntry.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/DefaultLiveObjects.kt
📚 Learning: in the ably-java liveobjects test code, an extension property `state` (capital s) is defined on the ...
Learnt from: sacOO7
PR: ably/ably-java#1120
File: live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveObjectsTest.kt:0-0
Timestamp: 2025-08-01T09:53:16.730Z
Learning: In the ably-java LiveObjects test code, an extension property `State` (capital S) is defined on the `LiveObjects` interface in live-objects/src/test/kotlin/io/ably/lib/objects/integration/helpers/Utils.kt to provide access to the internal `state` field by casting to `DefaultLiveObjects`. This allows tests to access internal state for verification purposes.

Applied to files:

  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/ObjectIdTest.kt
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveObjectsTest.kt
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveCounterTest.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/Helpers.kt
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveMapTest.kt
  • lib/src/main/java/io/ably/lib/objects/LiveObjectsAdapter.java
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/livecounter/DefaultLiveCounter.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/livemap/DefaultLiveMap.kt
  • lib/src/main/java/io/ably/lib/objects/type/map/LiveMapValue.java
  • lib/src/main/java/io/ably/lib/objects/LiveObjects.java
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/BaseLiveObject.kt
  • lib/src/main/java/io/ably/lib/objects/type/map/LiveMap.java
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/livemap/LiveMapEntry.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/DefaultLiveObjects.kt
📚 Learning: in the ably-java codebase, the defaultliveobjectserializer class methods like writemsgpackarray will...
Learnt from: sacOO7
PR: ably/ably-java#1106
File: live-objects/src/main/kotlin/io/ably/lib/objects/serialization/Serialization.kt:25-29
Timestamp: 2025-06-23T14:18:25.315Z
Learning: In the ably-java codebase, the DefaultLiveObjectSerializer class methods like writeMsgpackArray will have their type signatures updated to be non-nullable since the calling sites ensure objects are never null when passed to these methods.

Applied to files:

  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/ObjectIdTest.kt
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveObjectsTest.kt
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveCounterTest.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/Helpers.kt
  • lib/src/main/java/io/ably/lib/objects/Adapter.java
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveMapTest.kt
  • lib/src/main/java/io/ably/lib/objects/LiveObjectsAdapter.java
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/livecounter/DefaultLiveCounter.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/livemap/DefaultLiveMap.kt
  • lib/src/main/java/io/ably/lib/objects/type/map/LiveMapValue.java
  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/ObjectMessageSizeTest.kt
  • lib/src/main/java/io/ably/lib/objects/LiveObjects.java
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/helpers/PayloadBuilder.kt
  • lib/src/main/java/io/ably/lib/objects/type/map/LiveMap.java
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/livemap/LiveMapEntry.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/Utils.kt
  • lib/src/main/java/io/ably/lib/objects/type/counter/LiveCounter.java
  • live-objects/src/main/kotlin/io/ably/lib/objects/DefaultLiveObjects.kt
📚 Learning: in defaultlivemaptest.kt integration tests, operations are performed sequentially one after another,...
Learnt from: sacOO7
PR: ably/ably-java#1130
File: live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveMapTest.kt:241-241
Timestamp: 2025-08-01T10:30:27.049Z
Learning: In DefaultLiveMapTest.kt integration tests, operations are performed sequentially one after another, and subscription callback list updates happen one at a time, so thread-safe collections are not needed for collecting updates in test scenarios.

Applied to files:

  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveObjectsTest.kt
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveCounterTest.kt
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveMapTest.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/livecounter/DefaultLiveCounter.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/livemap/DefaultLiveMap.kt
  • lib/src/main/java/io/ably/lib/objects/LiveObjects.java
  • lib/src/main/java/io/ably/lib/objects/type/map/LiveMap.java
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/livemap/LiveMapEntry.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/DefaultLiveObjects.kt
📚 Learning: in test utility code for the ably java live objects module, the team prefers to keep reflection-base...
Learnt from: sacOO7
PR: ably/ably-java#1092
File: live-objects/src/test/kotlin/io/ably/lib/objects/TestUtils.kt:21-32
Timestamp: 2025-06-03T09:15:15.338Z
Learning: In test utility code for the Ably Java Live Objects module, the team prefers to keep reflection-based field access utilities simple without additional error handling, allowing tests to fail fast if incorrect field names are used.

Applied to files:

  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveObjectsTest.kt
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveCounterTest.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/Helpers.kt
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveMapTest.kt
  • lib/src/main/java/io/ably/lib/objects/LiveObjectsAdapter.java
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/livemap/DefaultLiveMap.kt
  • lib/src/main/java/io/ably/lib/objects/type/map/LiveMapValue.java
  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/ObjectMessageSizeTest.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/ServerTime.kt
  • lib/src/main/java/io/ably/lib/objects/LiveObjects.java
  • lib/src/main/java/io/ably/lib/objects/type/map/LiveMap.java
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/livemap/LiveMapEntry.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/Utils.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/DefaultLiveObjects.kt
📚 Learning: in the ably-java codebase, the defaultliveobjectserializer class uses intentional unsafe casting (`o...
Learnt from: sacOO7
PR: ably/ably-java#1106
File: live-objects/src/main/kotlin/io/ably/lib/objects/serialization/Serialization.kt:38-46
Timestamp: 2025-06-23T14:14:17.847Z
Learning: In the ably-java codebase, the DefaultLiveObjectSerializer class uses intentional unsafe casting (`objects as Array<ObjectMessage>`) without type validation in both writeMsgpackArray and asJsonArray methods. This is a deliberate design decision to keep the dynamically-loaded class simple and let ClassCastException occur naturally for type mismatches.

Applied to files:

  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveObjectsTest.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/Helpers.kt
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveMapTest.kt
  • lib/src/main/java/io/ably/lib/objects/type/map/LiveMapValue.java
  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/ObjectMessageSizeTest.kt
  • lib/src/main/java/io/ably/lib/objects/LiveObjects.java
  • live-objects/src/main/kotlin/io/ably/lib/objects/DefaultLiveObjects.kt
📚 Learning: in the ably-java codebase test files, junit's assert.assertequals method is used which has the signa...
Learnt from: sacOO7
PR: ably/ably-java#1113
File: live-objects/src/test/kotlin/io/ably/lib/objects/unit/type/livemap/LiveMapManagerTest.kt:640-640
Timestamp: 2025-08-01T05:54:07.024Z
Learning: In the ably-java codebase test files, JUnit's Assert.assertEquals method is used which has the signature assertEquals(String message, Object expected, Object actual) where the message parameter comes first, not last like in Kotlin test's assertEquals method.

Applied to files:

  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveObjectsTest.kt
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveCounterTest.kt
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveMapTest.kt
  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/ObjectMessageSizeTest.kt
📚 Learning: in defaultliveobjects.kt, the object creation pattern using objectspool.get() followed by withcontex...
Learnt from: sacOO7
PR: ably/ably-java#1135
File: live-objects/src/main/kotlin/io/ably/lib/objects/DefaultLiveObjects.kt:100-134
Timestamp: 2025-08-06T09:22:40.964Z
Learning: In DefaultLiveObjects.kt, the object creation pattern using objectsPool.get() followed by withContext(sequentialScope.coroutineContext) { objectsPool.createZeroValueObjectIfNotExists() } is thread-safe because sequentialScope uses limitedParallelism(1) ensuring sequential execution, and createZeroValueObjectIfNotExists() performs an internal get() check before creating, preventing duplicate object creation even when multiple coroutines initially see null from the first get() call.

Applied to files:

  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveObjectsTest.kt
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveCounterTest.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/livecounter/DefaultLiveCounter.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/livemap/DefaultLiveMap.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/ServerTime.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/livemap/LiveMapEntry.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/Utils.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/DefaultLiveObjects.kt
📚 Learning: the sandbox.kt file in ably-java live-objects module already has comprehensive http retry mechanism ...
Learnt from: sacOO7
PR: ably/ably-java#1095
File: live-objects/src/test/kotlin/io/ably/lib/objects/integration/setup/IntegrationTest.kt:87-89
Timestamp: 2025-06-06T09:28:12.298Z
Learning: The Sandbox.kt file in ably-java live-objects module already has comprehensive HTTP retry mechanism using HttpRequestRetry with 5 retries, exponential backoff, and automatic retry on non-success responses and timeout exceptions.

Applied to files:

  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveObjectsTest.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/Helpers.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/ServerTime.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/Utils.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/DefaultLiveObjects.kt
📚 Learning: in liveobjects implementation (lib/src/main/java/io/ably/lib/objects/liveobjectsadapter.java), the s...
Learnt from: sacOO7
PR: ably/ably-java#1087
File: lib/src/main/java/io/ably/lib/objects/LiveObjectsAdapter.java:32-34
Timestamp: 2025-05-27T12:11:25.084Z
Learning: In LiveObjects implementation (lib/src/main/java/io/ably/lib/objects/LiveObjectsAdapter.java), the send method intentionally hardcodes queueEvents to true rather than respecting ably.options.queueMessages. This is because LiveObjects requires reliable message delivery to ensure proper state synchronization and acknowledgment, unlike other realtime components that may allow configurable queuing behavior.

Applied to files:

  • live-objects/src/main/kotlin/io/ably/lib/objects/Helpers.kt
  • lib/src/main/java/io/ably/lib/objects/Adapter.java
  • lib/src/main/java/io/ably/lib/objects/LiveObjectsAdapter.java
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/livemap/DefaultLiveMap.kt
  • lib/src/main/java/io/ably/lib/objects/LiveObjects.java
  • live-objects/src/main/kotlin/io/ably/lib/objects/DefaultLiveObjects.kt
📚 Learning: in the ably java liveobjects messagepack deserialization code, the `action` field in objectoperation...
Learnt from: sacOO7
PR: ably/ably-java#1106
File: live-objects/src/main/kotlin/io/ably/lib/objects/serialization/MsgpackSerialization.kt:207-211
Timestamp: 2025-06-23T14:28:23.301Z
Learning: In the Ably Java LiveObjects MessagePack deserialization code, the `action` field in ObjectOperation is guaranteed to always be present in the protocol, so using a default value during deserialization is acceptable and won't mask real protocol errors.

Applied to files:

  • live-objects/src/main/kotlin/io/ably/lib/objects/Helpers.kt
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/helpers/PayloadBuilder.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/DefaultLiveObjects.kt
📚 Learning: user sacoo7 prefers simple test utilities without extensive error handling, believing tests should f...
Learnt from: sacOO7
PR: ably/ably-java#1092
File: live-objects/src/test/kotlin/io/ably/lib/objects/TestUtils.kt:48-61
Timestamp: 2025-06-03T09:15:18.827Z
Learning: User sacOO7 prefers simple test utilities without extensive error handling, believing tests should fail fast if incorrect field/method names are used rather than having defensive programming.

Applied to files:

  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveMapTest.kt
📚 Learning: the liveobjects interface does not currently include public api methods for resource management (dis...
Learnt from: sacOO7
PR: ably/ably-java#1085
File: lib/src/main/java/io/ably/lib/objects/LiveObjects.java:0-0
Timestamp: 2025-05-20T13:12:19.013Z
Learning: The LiveObjects interface does not currently include public API methods for resource management (dispose) or change listeners, as these features are not yet implemented.

Applied to files:

  • lib/src/main/java/io/ably/lib/objects/LiveObjectsAdapter.java
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/livecounter/DefaultLiveCounter.kt
  • lib/src/main/java/io/ably/lib/objects/LiveObjects.java
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/livemap/LiveMapEntry.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/DefaultLiveObjects.kt
📚 Learning: in kotlin/java codebases, when referencing types (classes, enums, interfaces) that are defined in th...
Learnt from: sacOO7
PR: ably/ably-java#1087
File: live-objects/src/main/kotlin/io/ably/lib/objects/ObjectMessage.kt:198-198
Timestamp: 2025-05-27T12:12:10.782Z
Learning: In Kotlin/Java codebases, when referencing types (classes, enums, interfaces) that are defined in the same package, no import statement is required as they are automatically accessible due to package-private visibility.

Applied to files:

  • live-objects/src/main/kotlin/io/ably/lib/objects/type/BaseLiveObject.kt
📚 Learning: in kotlin, functions, classes, and other declarations within the same package are automatically acce...
Learnt from: sacOO7
PR: ably/ably-java#1095
File: live-objects/src/test/kotlin/io/ably/lib/objects/unit/LiveObjectTest.kt:1-6
Timestamp: 2025-06-05T10:24:28.789Z
Learning: In Kotlin, functions, classes, and other declarations within the same package are automatically accessible without explicit import statements. Do not suggest adding imports for functions/classes that are already in the same package.

Applied to files:

  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/helpers/PayloadBuilder.kt
🧬 Code Graph Analysis (7)
live-objects/src/test/kotlin/io/ably/lib/objects/unit/UtilsTest.kt (1)
live-objects/src/main/kotlin/io/ably/lib/objects/Utils.kt (1)
  • generateNonce (114-117)
live-objects/src/main/kotlin/io/ably/lib/objects/Helpers.kt (1)
live-objects/src/main/kotlin/io/ably/lib/objects/Utils.kt (3)
  • ablyException (10-18)
  • ablyException (20-23)
  • clientError (37-37)
live-objects/src/main/kotlin/io/ably/lib/objects/type/livecounter/DefaultLiveCounter.kt (1)
live-objects/src/main/kotlin/io/ably/lib/objects/Utils.kt (1)
  • invalidInputError (45-47)
live-objects/src/main/kotlin/io/ably/lib/objects/type/livemap/DefaultLiveMap.kt (1)
live-objects/src/main/kotlin/io/ably/lib/objects/Utils.kt (1)
  • invalidInputError (45-47)
live-objects/src/test/kotlin/io/ably/lib/objects/integration/helpers/PayloadBuilder.kt (1)
live-objects/src/main/kotlin/io/ably/lib/objects/Utils.kt (1)
  • generateNonce (114-117)
lib/src/main/java/io/ably/lib/objects/type/map/LiveMap.java (1)
live-objects/src/main/kotlin/io/ably/lib/objects/type/livemap/DefaultLiveMap.kt (2)
  • entries (60-71)
  • values (82-89)
lib/src/main/java/io/ably/lib/objects/type/counter/LiveCounter.java (2)
live-objects/src/main/kotlin/io/ably/lib/objects/type/livecounter/DefaultLiveCounter.kt (3)
  • increment (44-44)
  • decrement (46-46)
  • decrementAsync (52-54)
live-objects/src/main/kotlin/io/ably/lib/objects/ObjectMessage.kt (1)
  • amount (90-96)
🔇 Additional comments (61)
lib/src/main/java/io/ably/lib/objects/type/counter/LiveCounter.java (5)

17-27: LGTM! Well-documented method signature change.

The increment method now properly accepts a Number parameter with clear documentation about the operation behavior and spec reference.


29-37: LGTM! Consistent decrement method design.

The decrement method correctly mirrors the increment signature and clearly documents that it's an alias for negative increment, which aligns with the implementation in DefaultLiveCounter.kt.


40-51: LGTM! Proper async method signature.

The asynchronous increment method maintains consistency with the synchronous version while properly handling the callback pattern.


54-62: LGTM! Consistent async decrement method.

The asynchronous decrement method properly mirrors the increment async method with clear documentation about being an alias.


67-71: LGTM! Appropriate return type change.

Changing the return type from Long to Double is consistent with the internal representation and the ObjectCounterOp.amount field being Double. The @Contract(pure = true) annotation correctly indicates this method doesn't modify object state.

live-objects/src/test/kotlin/io/ably/lib/objects/unit/ObjectMessageSizeTest.kt (1)

171-171: LGTM! Correct pluralization in error message.

The change from "ObjectMessage" to "ObjectMessages" properly reflects that the error occurs when multiple messages collectively exceed the size limit, aligning with the implementation in Helpers.kt.

live-objects/src/main/kotlin/io/ably/lib/objects/ErrorCodes.kt (1)

9-9: LGTM! Improved error code naming.

Renaming MapKeyShouldBeString to InvalidInputParams makes the error code more generic and reusable for various input validation scenarios while maintaining the same code value.

live-objects/src/main/kotlin/io/ably/lib/objects/type/BaseLiveObject.kt (1)

30-30: LGTM! Appropriate visibility change.

Changing objectType from private to internal enables module-level access needed for type-safe operations like LiveMapValue wrapping and object ID generation while maintaining encapsulation outside the module.

live-objects/src/test/kotlin/io/ably/lib/objects/unit/UtilsTest.kt (1)

15-31: LGTM! Comprehensive test coverage for generateNonce.

The test thoroughly validates the generateNonce() function by checking:

  • Correct length (16 characters)
  • Randomness (different nonces generated)
  • Character set compliance (only alphanumeric characters)

The test structure is well-organized and covers all important aspects of the nonce generation functionality.

live-objects/src/test/kotlin/io/ably/lib/objects/integration/helpers/PayloadBuilder.kt (1)

6-6: LGTM! Good refactoring to use centralized nonce generation.

The replacement of the local nonce() function with the centralized generateNonce() utility improves code consistency and eliminates duplication. The new function generates a 16-character alphanumeric string instead of UUID-based nonces, which aligns with the deterministic object ID generation requirements.

Also applies to: 44-44, 111-111

live-objects/src/test/kotlin/io/ably/lib/objects/unit/ObjectIdTest.kt (1)

56-74: LGTM! Comprehensive test coverage for the new factory method.

The test properly validates the fromInitialValue method by checking:

  • String format compliance (type:hash@timestamp)
  • Deterministic hash generation with expected output
  • Proper timestamp handling

The use of fixed inputs with pre-calculated expected hash ensures test repeatability and validates the SHA-256 + Base64 URL-safe encoding implementation.

live-objects/src/main/kotlin/io/ably/lib/objects/ObjectId.kt (2)

26-33: LGTM! Correct implementation of RTO14 specification.

The fromInitialValue method properly implements the specification requirements:

  • Concatenates initial value and nonce with colon separator
  • Uses SHA-256 for cryptographic hashing (RTO14b)
  • Applies Base64 URL-safe encoding without padding, suitable for identifiers
  • Returns deterministic object IDs for given inputs

The implementation is secure and follows cryptographic best practices.


38-38: LGTM! Appropriate visibility change to internal.

Making fromString internal is consistent with the codebase patterns and properly restricts access to this parsing method.

live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveObjectsTest.kt (1)

76-76: Excellent type safety improvements with nullable accessors.

The refactoring from unsafe casts (as Type) to safe nullable property accessors (?.asType) significantly improves code safety by:

  • Eliminating ClassCastException risks
  • Making null handling explicit with assertNotNull checks
  • Aligning with the new LiveMapValue type system

This change properly reflects the API evolution toward type-safe live object handling.

Also applies to: 81-81, 86-86, 92-92, 97-97, 100-100, 105-105, 110-111, 114-115, 119-122, 124-131, 134-135, 139-140, 147-148, 150-150, 173-173, 190-190, 211-211

live-objects/src/main/kotlin/io/ably/lib/objects/Utils.kt (2)

45-47: LGTM!

The invalidInputError function follows the established pattern of other error creation functions and correctly uses the updated ErrorCode.InvalidInputParams.


55-55: LGTM!

The change from Charsets.UTF_8 to StandardCharsets.UTF_8 is correct and aligns with the import statement. Both are functionally equivalent.

lib/src/main/java/io/ably/lib/objects/Adapter.java (3)

71-74: LGTM!

The implementation correctly delegates to the underlying AblyRealtime instance's options property.


76-79: LGTM!

The implementation correctly delegates to the connection manager from the AblyRealtime instance.


81-84: LGTM!

The implementation correctly delegates to the AblyRealtime's time() method and properly declares the AblyException in the throws clause.

live-objects/src/main/kotlin/io/ably/lib/objects/type/livemap/LiveMapEntry.kt (3)

45-59: LGTM!

The updated getResolvedValue function correctly implements type-safe conversion from internal representations to LiveMapValue. The logic flow is preserved while adding proper type safety.


69-78: LGTM!

The fromObjectValue function comprehensively handles all ObjectValue subtypes and correctly maps them to corresponding LiveMapValue instances.


80-85: LGTM!

The fromLiveObject function correctly handles the conversion of BaseLiveObject instances to LiveMapValue with proper type casting based on ObjectType.

lib/src/main/java/io/ably/lib/objects/LiveObjectsAdapter.java (3)

60-67: LGTM!

The getClientOptions() method declaration is well-documented and correctly annotated with @NotNull.


69-76: LGTM!

The getConnectionManager() method declaration is well-documented and correctly annotated with @NotNull.


78-83: LGTM!

The getTime() method declaration is properly documented with spec reference (RTO16), correctly annotated with @Blocking, and properly declares the AblyException.

live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveCounterTest.kt (3)

31-31: LGTM!

The updates to use safe nullable accessors (?.asLiveCounter and ?.asLiveMap) improve type safety and prevent potential ClassCastExceptions. This aligns with the broader type safety improvements in the PR.

Also applies to: 37-37, 42-42, 47-47, 52-52, 57-57, 62-62, 67-67, 73-73, 78-78, 83-83, 88-88, 132-132, 203-206


208-297: LGTM!

The new test testLiveCounterOperationsUsingRealtime provides comprehensive coverage of the realtime API for counter operations. The test properly:

  • Creates counters using the realtime API
  • Tests increment/decrement operations with proper waiting
  • Verifies values after each operation
  • Uses proper async testing patterns with assertWaiter

308-312: LGTM!

The safe accessor pattern is consistently applied throughout the test, improving robustness and type safety.

live-objects/src/main/kotlin/io/ably/lib/objects/Helpers.kt (6)

12-29: LGTM!

The sendAsync implementation correctly wraps the adapter's callback-based send method into a suspend function using proper coroutine patterns.


31-41: Good grammar fix!

The error message correctly uses plural "ObjectMessages" since the function validates an array of messages.


56-60: LGTM!

The validation function properly enforces all requirements for write operations: echo messages enabled, correct channel mode, and valid channel state.


62-67: LGTM!

Proper validation of connection and channel states before publishing, with appropriate error information from the connection manager.


85-89: LGTM!

Clear validation that echo messages must be enabled, with an appropriate client error message.


107-113: LGTM!

Well-structured data classes for encapsulating creation payloads for counters and maps.

lib/src/main/java/io/ably/lib/objects/type/map/LiveMap.java (1)

33-33: Excellent type safety improvements!

The migration from generic Object to the specific LiveMapValue type throughout the interface provides:

  • Compile-time type safety
  • Better API clarity
  • Consistent typing across all map operations

The added specification references (RTLM20, RTLM21) properly document the requirements.

Also applies to: 43-43, 63-63, 71-77, 85-85, 108-115, 123-123

live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveMapTest.kt (4)

34-98: Great type safety improvements in tests!

The consistent use of safe nullable access (?.) followed by explicit type conversions (.asLiveMap, .asLiveCounter, .asString, etc.) makes the tests more robust and clearer about expected types.


126-216: LGTM!

Consistent application of type-safe accessors throughout the test. The value extraction at lines 214-215 correctly handles the LiveMapValue wrapper for set comparison.


218-333: Excellent addition of realtime API test coverage!

The new testLiveMapOperationsUsingRealtime test effectively validates the realtime write API implementation. It properly:

  • Uses LiveMapValue.of() factory methods for type-safe value creation
  • Tests both set() and remove() operations via the realtime API
  • Maintains consistency with the REST API test for comparison
  • Follows the same type-safe accessor patterns

345-411: LGTM!

The subscription test correctly uses type-safe accessors, maintaining consistency with the rest of the test suite.

live-objects/src/main/kotlin/io/ably/lib/objects/type/livecounter/DefaultLiveCounter.kt (3)

42-54: Well-structured implementation!

Good application of DRY principle by delegating all increment/decrement operations to a single incrementAsync function. The use of negative amounts for decrement operations is clean and correct.


72-92: Robust implementation with proper validation!

The incrementAsync implementation correctly:

  • Validates write API configuration before operations
  • Rejects invalid numeric values (NaN, Infinite)
  • Constructs the ObjectMessage with appropriate operation details
  • Delegates publishing to the liveObjects instance

All specification requirements (RTLC12b-f) are properly addressed.


128-136: LGTM!

Clean factory method for creating initial counter payloads, properly converting the Number parameter to Double.

live-objects/src/main/kotlin/io/ably/lib/objects/DefaultLiveObjects.kt (5)

55-55: LGTM!

The public API methods are well-structured:

  • Proper delegation pattern from sync to async methods
  • Reasonable defaults (empty map, zero counter)
  • Consistent use of asyncScope for callback-based operations

Also applies to: 63-85


100-134: Well-implemented map creation with proper synchronization!

The implementation correctly:

  • Validates input (no empty keys)
  • Generates unique object IDs with nonce and server timestamp
  • Constructs the MAP_CREATE operation message properly
  • Ensures thread-safe object creation using the sequential scope

The pattern of checking the pool first, then creating in sequential scope, is thread-safe as confirmed by the single-threaded execution context.


136-170: Consistent implementation with map creation!

The counter creation properly:

  • Validates numeric input (rejects NaN/Infinite)
  • Follows the same ID generation pattern as maps
  • Constructs the COUNTER_CREATE operation correctly
  • Uses the same thread-safe object pool pattern

175-179: LGTM!

Clean helper method that properly encapsulates object ID generation with server timestamp and nonce.


184-193: Well-structured publish implementation!

The method properly enforces all requirements:

  • Channel/connection state validation (RTO15b, RTL6c)
  • Message size limit enforcement (RTO15d)
  • Correct ProtocolMessage construction (RTO15e)
  • Asynchronous sending with proper error propagation
lib/src/main/java/io/ably/lib/objects/type/map/LiveMapValue.java (5)

13-21: Well-designed abstract base class

The abstract class structure with the abstract getValue() method provides a solid foundation for the union type implementation. The @NotNull annotation correctly indicates that all implementations must return non-null values.


27-81: Type checking methods follow good design pattern

The default implementations returning false with subclasses overriding only the relevant method is an elegant approach that follows the template method pattern well.


87-172: Getter methods correctly implement fail-fast behavior

The default implementations throwing IllegalStateException with clear error messages ensure type safety at runtime. The @NotNull annotations are appropriate since valid type conversions should never return null.


178-264: Factory methods provide clean, type-safe API

The static factory methods follow the factory method pattern effectively, providing a clean API for creating type-safe LiveMapValue instances. The @NotNull annotations on both parameters and return types ensure null safety.


268-442: Implementation classes are well-structured and thread-safe

The private static final implementation classes with final fields ensure immutability and thread safety. Each class correctly overrides only the relevant type checking and getter methods, maintaining a clean separation of concerns.

live-objects/src/main/kotlin/io/ably/lib/objects/type/livemap/DefaultLiveMap.kt (6)

49-58: get() method correctly implements type-safe value retrieval

The method properly validates access configuration, checks for tombstoned state, and converts the internal representation to LiveMapValue using getResolvedValue(). The nullable return type appropriately handles missing keys.


60-89: Collection methods efficiently handle type conversion

The use of sequences for lazy evaluation is efficient. Filtering out null values from getResolvedValue() correctly excludes tombstoned entries. The updated return types properly integrate with the LiveMapValue type system.


96-98: Synchronous methods correctly delegate to async implementations

Using runBlocking to implement synchronous versions ensures consistency between sync and async behavior. This is a standard pattern in Kotlin for bridging coroutine and blocking APIs.


100-106: Async callback methods properly integrate with coroutine scope

The methods correctly use asyncScope.launchWithVoidCallback to execute suspend functions and handle callbacks, maintaining consistency with the async patterns in the codebase.


119-164: Write operations correctly implement spec requirements

The implementations properly validate write API configuration (RTLM20b-d, RTLM21b-d), check for empty keys, construct appropriate ObjectMessage instances with MAP_SET/MAP_REMOVE operations (RTLM20e, RTLM21e), and publish them (RTLM20f, RTLM21f). The error handling for empty keys is appropriate.


200-248: Companion object functions correctly handle type conversion

The initialValue function properly creates the payload structure for map creation. The fromLiveMapValue function (RTLM20e5) exhaustively handles all LiveMapValue types with appropriate conversions. The IllegalArgumentException in the else clause ensures fail-fast behavior if new types are added without updating this conversion logic.

lib/src/main/java/io/ably/lib/objects/LiveObjects.java (3)

36-76: Type-safe map creation API with excellent documentation

The transition from Map<String, Object> to Map<String, LiveMapValue> enforces compile-time type safety, preventing runtime errors. The comprehensive example (lines 57-69) clearly demonstrates all supported value types, making the API easy to understand and use. The parameterless createMap() provides a convenient way to create empty maps.


79-103: Counter creation API properly generalized

Changing the initial value parameter from Long to Number provides greater flexibility, allowing various numeric types (Integer, Double, etc.). The parameterless createCounter() with a default value of 0 offers a convenient option for the common use case.


117-165: Async methods maintain API consistency

The asynchronous methods perfectly mirror their synchronous counterparts, maintaining API consistency. The use of ObjectsCallback for result handling follows established patterns in the codebase.

@sacOO7 sacOO7 force-pushed the feature/liveobjects-realtime-write-api-refactored branch from b32c283 to e6cf876 Compare August 7, 2025 07:41
@github-actions github-actions bot temporarily deployed to staging/pull/1141/features August 7, 2025 07:42 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1141/javadoc August 7, 2025 07:44 Inactive
- Enhanced ObjectIdTest with testFromInitialValue test for object initialization
- Added new test methods to UtilsTest for realtime operation utilities
- Updated ObjectMessageSizeTest with realtime write operation size calculations
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
live-objects/src/test/kotlin/io/ably/lib/objects/unit/type/BaseLiveObjectTest.kt (1)

150-150: Update variable name to match object type.

The object creation was correctly changed from DefaultLiveMap to DefaultLiveCounter with appropriate object ID prefix, but the variable name liveMap is now misleading since it contains a LiveCounter instance.

-    val liveMap: BaseLiveObject = DefaultLiveCounter.zeroValue("counter:testObject@1", defaultLiveObjects)
+    val liveCounter: BaseLiveObject = DefaultLiveCounter.zeroValue("counter:testObject@1", defaultLiveObjects)

And update the subsequent variable references throughout the test method.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e6cf876 and c4f1f1c.

📒 Files selected for processing (6)
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/livecounter/DefaultLiveCounter.kt (4 hunks)
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveObjectsTest.kt (5 hunks)
  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/ObjectIdTest.kt (1 hunks)
  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/ObjectMessageSizeTest.kt (1 hunks)
  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/UtilsTest.kt (1 hunks)
  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/type/BaseLiveObjectTest.kt (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/ObjectMessageSizeTest.kt
🚧 Files skipped from review as they are similar to previous changes (4)
  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/ObjectIdTest.kt
  • live-objects/src/main/kotlin/io/ably/lib/objects/type/livecounter/DefaultLiveCounter.kt
  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/UtilsTest.kt
  • live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveObjectsTest.kt
🧰 Additional context used
🧠 Learnings (11)
📓 Common learnings
Learnt from: sacOO7
PR: ably/ably-java#1106
File: live-objects/src/main/kotlin/io/ably/lib/objects/serialization/Serialization.kt:25-29
Timestamp: 2025-06-23T14:18:25.315Z
Learning: In the ably-java codebase, the DefaultLiveObjectSerializer class methods like writeMsgpackArray will have their type signatures updated to be non-nullable since the calling sites ensure objects are never null when passed to these methods.
Learnt from: sacOO7
PR: ably/ably-java#1106
File: live-objects/src/main/kotlin/io/ably/lib/objects/serialization/Serialization.kt:38-46
Timestamp: 2025-06-23T14:14:17.847Z
Learning: In the ably-java codebase, the DefaultLiveObjectSerializer class uses intentional unsafe casting (`objects as Array<ObjectMessage>`) without type validation in both writeMsgpackArray and asJsonArray methods. This is a deliberate design decision to keep the dynamically-loaded class simple and let ClassCastException occur naturally for type mismatches.
Learnt from: sacOO7
PR: ably/ably-java#1087
File: lib/src/main/java/io/ably/lib/objects/LiveObjectsAdapter.java:32-34
Timestamp: 2025-05-27T12:11:25.084Z
Learning: In LiveObjects implementation (lib/src/main/java/io/ably/lib/objects/LiveObjectsAdapter.java), the send method intentionally hardcodes queueEvents to true rather than respecting ably.options.queueMessages. This is because LiveObjects requires reliable message delivery to ensure proper state synchronization and acknowledgment, unlike other realtime components that may allow configurable queuing behavior.
Learnt from: sacOO7
PR: ably/ably-java#1092
File: live-objects/src/test/kotlin/io/ably/lib/objects/TestUtils.kt:21-32
Timestamp: 2025-06-03T09:15:15.338Z
Learning: In test utility code for the Ably Java Live Objects module, the team prefers to keep reflection-based field access utilities simple without additional error handling, allowing tests to fail fast if incorrect field names are used.
Learnt from: sacOO7
PR: ably/ably-java#1130
File: live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveMapTest.kt:241-241
Timestamp: 2025-08-01T10:30:27.049Z
Learning: In DefaultLiveMapTest.kt integration tests, operations are performed sequentially one after another, and subscription callback list updates happen one at a time, so thread-safe collections are not needed for collecting updates in test scenarios.
Learnt from: sacOO7
PR: ably/ably-java#1139
File: live-objects/src/main/kotlin/io/ably/lib/objects/type/livecounter/DefaultLiveCounter.kt:86-92
Timestamp: 2025-08-07T07:19:59.951Z
Learning: In DefaultLiveCounter.notifyUpdated method, sacOO7 prefers to keep the unchecked cast `update as LiveCounterUpdate` without type safety checks, as they are confident the type system guarantees the correct type will always be passed.
Learnt from: sacOO7
PR: ably/ably-java#1120
File: live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveObjectsTest.kt:0-0
Timestamp: 2025-08-01T09:53:16.730Z
Learning: In the ably-java LiveObjects test code, extension properties with capital letter names (like `State`, `ObjectId`) are defined in live-objects/src/test/kotlin/io/ably/lib/objects/integration/helpers/Utils.kt to provide access to internal fields of concrete implementations through their public interfaces. For example, `LiveObjects.State` casts to `DefaultLiveObjects` to access the internal `state` field for testing purposes.
Learnt from: sacOO7
PR: ably/ably-java#1113
File: live-objects/src/test/kotlin/io/ably/lib/objects/unit/type/livemap/LiveMapManagerTest.kt:16-16
Timestamp: 2025-08-01T05:50:33.039Z
Learning: In LiveMapManagerTest.kt, the private field `livemapManager` is used extensively in the `shouldCalculateMapDifferenceCorrectly` test method to test the `calculateUpdateFromDataDiff` functionality across multiple test scenarios, so it should not be removed as unused.
Learnt from: sacOO7
PR: ably/ably-java#1120
File: live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveObjectsTest.kt:0-0
Timestamp: 2025-08-01T09:53:16.730Z
Learning: In the ably-java LiveObjects test code, an extension property `State` (capital S) is defined on the `LiveObjects` interface in live-objects/src/test/kotlin/io/ably/lib/objects/integration/helpers/Utils.kt to provide access to the internal `state` field by casting to `DefaultLiveObjects`. This allows tests to access internal state for verification purposes.
Learnt from: sacOO7
PR: ably/ably-java#1085
File: lib/src/main/java/io/ably/lib/objects/LiveObjects.java:0-0
Timestamp: 2025-05-20T13:12:19.013Z
Learning: The LiveObjects interface does not currently include public API methods for resource management (dispose) or change listeners, as these features are not yet implemented.
Learnt from: sacOO7
PR: ably/ably-java#1137
File: live-objects/src/test/kotlin/io/ably/lib/objects/unit/type/livemap/LiveMapManagerTest.kt:6-6
Timestamp: 2025-08-07T07:17:33.286Z
Learning: In the ably-java LiveObjects test code, there are extension properties defined in TestHelpers.kt that provide access to private fields of classes for testing purposes. For example, `internal var DefaultLiveMap.LiveMapManager: LiveMapManager` allows tests to access the private `liveMapManager` field. These extension imports (like `import io.ably.lib.objects.unit.LiveMapManager`) should not be removed as they are necessary for test functionality and are not conflicting imports.
Learnt from: sacOO7
PR: ably/ably-java#1113
File: live-objects/src/test/kotlin/io/ably/lib/objects/unit/type/livemap/LiveMapManagerTest.kt:16-16
Timestamp: 2025-08-01T05:50:33.039Z
Learning: In LiveMapManagerTest.kt, the private field `livemapManager` is used in the `shouldCalculateMapDifferenceCorrectly` test method to test the `calculateUpdateFromDataDiff` functionality, so it should not be removed as unused.
Learnt from: sacOO7
PR: ably/ably-java#1092
File: live-objects/src/test/kotlin/io/ably/lib/objects/TestUtils.kt:48-61
Timestamp: 2025-06-03T09:15:18.827Z
Learning: User sacOO7 prefers simple test utilities without extensive error handling, believing tests should fail fast if incorrect field/method names are used rather than having defensive programming.
📚 Learning: in the ably-java liveobjects test code, there are extension properties defined in testhelpers.kt tha...
Learnt from: sacOO7
PR: ably/ably-java#1137
File: live-objects/src/test/kotlin/io/ably/lib/objects/unit/type/livemap/LiveMapManagerTest.kt:6-6
Timestamp: 2025-08-07T07:17:33.286Z
Learning: In the ably-java LiveObjects test code, there are extension properties defined in TestHelpers.kt that provide access to private fields of classes for testing purposes. For example, `internal var DefaultLiveMap.LiveMapManager: LiveMapManager` allows tests to access the private `liveMapManager` field. These extension imports (like `import io.ably.lib.objects.unit.LiveMapManager`) should not be removed as they are necessary for test functionality and are not conflicting imports.

Applied to files:

  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/type/BaseLiveObjectTest.kt
📚 Learning: in the ably-java liveobjects test code, extension properties with capital letter names (like `state`...
Learnt from: sacOO7
PR: ably/ably-java#1120
File: live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveObjectsTest.kt:0-0
Timestamp: 2025-08-01T09:53:16.730Z
Learning: In the ably-java LiveObjects test code, extension properties with capital letter names (like `State`, `ObjectId`) are defined in live-objects/src/test/kotlin/io/ably/lib/objects/integration/helpers/Utils.kt to provide access to internal fields of concrete implementations through their public interfaces. For example, `LiveObjects.State` casts to `DefaultLiveObjects` to access the internal `state` field for testing purposes.

Applied to files:

  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/type/BaseLiveObjectTest.kt
📚 Learning: in the ably-java codebase, the defaultliveobjectserializer class methods like writemsgpackarray will...
Learnt from: sacOO7
PR: ably/ably-java#1106
File: live-objects/src/main/kotlin/io/ably/lib/objects/serialization/Serialization.kt:25-29
Timestamp: 2025-06-23T14:18:25.315Z
Learning: In the ably-java codebase, the DefaultLiveObjectSerializer class methods like writeMsgpackArray will have their type signatures updated to be non-nullable since the calling sites ensure objects are never null when passed to these methods.

Applied to files:

  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/type/BaseLiveObjectTest.kt
📚 Learning: in defaultlivemaptest.kt integration tests, operations are performed sequentially one after another,...
Learnt from: sacOO7
PR: ably/ably-java#1130
File: live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveMapTest.kt:241-241
Timestamp: 2025-08-01T10:30:27.049Z
Learning: In DefaultLiveMapTest.kt integration tests, operations are performed sequentially one after another, and subscription callback list updates happen one at a time, so thread-safe collections are not needed for collecting updates in test scenarios.

Applied to files:

  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/type/BaseLiveObjectTest.kt
📚 Learning: in the ably-java liveobjects test code, an extension property `state` (capital s) is defined on the ...
Learnt from: sacOO7
PR: ably/ably-java#1120
File: live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveObjectsTest.kt:0-0
Timestamp: 2025-08-01T09:53:16.730Z
Learning: In the ably-java LiveObjects test code, an extension property `State` (capital S) is defined on the `LiveObjects` interface in live-objects/src/test/kotlin/io/ably/lib/objects/integration/helpers/Utils.kt to provide access to the internal `state` field by casting to `DefaultLiveObjects`. This allows tests to access internal state for verification purposes.

Applied to files:

  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/type/BaseLiveObjectTest.kt
📚 Learning: in the ably-java liveobjects test code, there is a `findmethod` extension function defined on `class...
Learnt from: sacOO7
PR: ably/ably-java#1137
File: live-objects/src/test/kotlin/io/ably/lib/objects/unit/type/BaseLiveObjectTest.kt:48-67
Timestamp: 2025-08-07T07:14:23.327Z
Learning: In the ably-java LiveObjects test code, there is a `findMethod` extension function defined on `Class<*>` in TestUtils.kt that searches the class's public methods for one whose name contains the given substring and returns it. This extension method should not be replaced with standard reflection methods like `getDeclaredMethod()` when used in tests.

Applied to files:

  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/type/BaseLiveObjectTest.kt
📚 Learning: in the ably-java codebase test files, junit's assert.assertequals method is used which has the signa...
Learnt from: sacOO7
PR: ably/ably-java#1113
File: live-objects/src/test/kotlin/io/ably/lib/objects/unit/type/livemap/LiveMapManagerTest.kt:640-640
Timestamp: 2025-08-01T05:54:07.024Z
Learning: In the ably-java codebase test files, JUnit's Assert.assertEquals method is used which has the signature assertEquals(String message, Object expected, Object actual) where the message parameter comes first, not last like in Kotlin test's assertEquals method.

Applied to files:

  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/type/BaseLiveObjectTest.kt
📚 Learning: in livemapmanagertest.kt, the private field `livemapmanager` is used in the `shouldcalculatemapdiffe...
Learnt from: sacOO7
PR: ably/ably-java#1113
File: live-objects/src/test/kotlin/io/ably/lib/objects/unit/type/livemap/LiveMapManagerTest.kt:16-16
Timestamp: 2025-08-01T05:50:33.039Z
Learning: In LiveMapManagerTest.kt, the private field `livemapManager` is used in the `shouldCalculateMapDifferenceCorrectly` test method to test the `calculateUpdateFromDataDiff` functionality, so it should not be removed as unused.

Applied to files:

  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/type/BaseLiveObjectTest.kt
📚 Learning: in test utility code for the ably java live objects module, the team prefers to keep reflection-base...
Learnt from: sacOO7
PR: ably/ably-java#1092
File: live-objects/src/test/kotlin/io/ably/lib/objects/TestUtils.kt:21-32
Timestamp: 2025-06-03T09:15:15.338Z
Learning: In test utility code for the Ably Java Live Objects module, the team prefers to keep reflection-based field access utilities simple without additional error handling, allowing tests to fail fast if incorrect field names are used.

Applied to files:

  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/type/BaseLiveObjectTest.kt
📚 Learning: in livemapmanagertest.kt, the private field `livemapmanager` is used extensively in the `shouldcalcu...
Learnt from: sacOO7
PR: ably/ably-java#1113
File: live-objects/src/test/kotlin/io/ably/lib/objects/unit/type/livemap/LiveMapManagerTest.kt:16-16
Timestamp: 2025-08-01T05:50:33.039Z
Learning: In LiveMapManagerTest.kt, the private field `livemapManager` is used extensively in the `shouldCalculateMapDifferenceCorrectly` test method to test the `calculateUpdateFromDataDiff` functionality across multiple test scenarios, so it should not be removed as unused.

Applied to files:

  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/type/BaseLiveObjectTest.kt
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: build
  • GitHub Check: check-realtime-okhttp
  • GitHub Check: check-liveobjects
  • GitHub Check: check-rest-okhttp
  • GitHub Check: check (21)
  • GitHub Check: check (24)
  • GitHub Check: check (29)
  • GitHub Check: check (19)
  • GitHub Check: check-realtime
  • GitHub Check: check-rest
  • GitHub Check: check

Copy link
Contributor

@ttypic ttypic left a comment

Choose a reason for hiding this comment

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

LGTM

Base automatically changed from feature/server-provided-tombstone-serial-refactored to main August 8, 2025 14:24
@sacOO7 sacOO7 merged commit 8ec259d into main Aug 8, 2025
13 checks passed
@sacOO7 sacOO7 deleted the feature/liveobjects-realtime-write-api-refactored branch August 8, 2025 14:24
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.

LiveObject: Implement realtime write API

2 participants

Comments