Skip to content

Conversation

@sacOO7
Copy link
Collaborator

@sacOO7 sacOO7 commented Aug 6, 2025

Summary by CodeRabbit

  • New Features

    • Added support for querying channel modes and states.
    • Introduced event subscription APIs for synchronization state changes.
    • Added new error codes for channel mode and state validation.
    • Implemented new callback and subscription interfaces for asynchronous operations and event handling.
  • Bug Fixes

    • Implemented missing methods for map and counter objects, improving value retrieval and validation.
  • Refactor

    • Standardized callback types for asynchronous operations.
    • Improved coroutine and state management for live objects.
    • Enhanced error handling and disposal mechanisms.
  • Tests

    • Added comprehensive integration and unit tests for live objects, maps, and counters.
    • Introduced new test fixtures and helpers for REST operations and data setup.
  • Documentation

    • Improved inline documentation for disposal methods and event APIs.

sacOO7 added 14 commits July 16, 2025 14:45
- Added ObjectsStateEvent enum for SYNCING and SYNCED states
- Created ObjectsStateChange interface with listener pattern for state changes
- Implemented ObjectsSubscription interface for subscription management
- Added ObjectsState enum and coordination system with internal/external event emitters
- Created HandlesObjectsStateChange interface for state management coordination
- Added getChannelModes and getChannelState methods to LiveObjectsAdapter interface
- Implemented channel mode retrieval with fallback from channel options (RTO2a, RTO2b)
- Enhanced LiveObjectsPlugin interface with disposal lifecycle documentation
- Fixed DefaultLiveObjectsPlugin to use clientError for proper exception handling
- Updated Adapter class with channel state and mode management functionality
…h lifecycle tied to given objects instance

- Added channel mode and state validation error codes (ChannelModeRequired, ChannelStateError)
- Implemented throwIfInvalidAccessApiConfiguration with channel mode validation (RTO2)
- Created ObjectsAsyncScope for channel-specific async operations with proper error handling
- Added launchWithCallback and launchWithVoidCallback methods for safe async execution
- Enhanced validation helpers for channel state and mode requirements
…andle exceptions

- Updated ObjectsManager to extend ObjectsStateCoordinator for state management
- Fixed state enum references from SYNCED/SYNCING to Synced/Syncing
- Added stateChange method with proper state transition logging (RTO2)
- Integrated state change event emission through ObjectsStateCoordinator
- Enhanced disposal process to include state listener cleanup
- Removed unused import from BaseLiveObject
- Updated LiveCounter#data type to AtomicLong to make it thread safe
- Replaced generic Callback with ObjectsCallback in async methods
- Implemented value() method with channel configuration validation
- Added proper adapter validation using throwIfInvalidAccessApiConfiguration
- Maintained thread-safe access to counter data through AtomicReference
…ctor param

- Added channel state checks for detached and failed
- Implemented LiveMap accessor methods: get, entries, keys, values and size
- Updated LiveMap data field to be ConcurrentMap for thread safety
- Added proper channel configuration validation for all accessor methods
- Implemented sequence-based iteration for entries, keys, and values with tombstone filtering
- Replaced generic Callback with ObjectsCallback in async methods
- Added getChannelModes and getChannelState methods to adapter
- Implemented getRoot method with blocking and async variants using ObjectsAsyncScope
- Moved ObjectsState enum to separate file and updated state references
- Added proper disposal handling with AblyException instead of string reason
- Enhanced async scope management for callback operations
- Updated all async method signatures to use ObjectsCallback instead of Callback
- Added getOptions() method to ChannelBase for accessing channel options
- Initialize LiveObjects instance on channel creation to process sync messages
- Enhanced channel integration with LiveObjects plugin lifecycle management
- Fixed channel mode fallback logic by exposing channel options
…ionality

- Added UtilsTest with 283 lines of comprehensive utility function tests
- Enhanced DefaultLiveObjectsTest with updated state management tests
- Updated ObjectsManagerTest with improved sync sequence and state handling tests
- Created test coverage for ObjectId validation, state transitions, and error handling
- Added tests for ObjectsAsyncScope callback execution and error scenarios
…und async ops

- Enhanced IntegrationTest setup with improved test configuration
- Updated Sandbox configuration for integration test environment
- Improved test infrastructure for Live Objects integration testing
- Added better error handling and setup validation for integration tests
- Created PayloadBuilder for constructing test payloads with 135 lines of functionality
- Added RestObjects helper with 119 lines for REST API integration testing
- Implemented CounterFixtures with test data for LiveCounter integration tests
- Created DataFixtures with 84 lines of common test data structures
- Added MapFixtures with 157 lines for LiveMap integration test scenarios
- Enhanced integration test utilities with comprehensive helper functions
…ad of checking type at runtime

- Added DefaultLiveCounterTest with 205 lines of comprehensive integration tests
- Created DefaultLiveMapTest with 213 lines covering LiveMap integration scenarios
- Implemented test coverage for LiveCounter and LiveMap accessor methods
- Added integration tests for object state validation and error handling
- Enhanced test suite with real-time synchronization and state change validation
- Added ObjectsCallback interface replacing generic Callback for Live Objects operations
- Updated LiveObjects interface to extend ObjectsStateChange and use ObjectsCallback
- Refactored LiveCounter and LiveMap async methods to use ObjectsCallback instead of Callback
- Added comprehensive Javadoc for ObjectsCallback with operation-specific guidance
@coderabbitai
Copy link

coderabbitai bot commented Aug 6, 2025

Walkthrough

This update introduces and implements core LiveObjects API features, including the getRoot method, public LiveMap API methods, and a robust objects state change subscription system. It refactors asynchronous error handling for consistency, adds new error codes, and provides extensive integration and unit tests. Supporting helpers and fixtures for testing are also included.

Changes

Cohort / File(s) Change Summary
LiveObjects API: getRoot and State Change
live-objects/src/main/kotlin/io/ably/lib/objects/DefaultLiveObjects.kt, lib/src/main/java/io/ably/lib/objects/LiveObjects.java, lib/src/main/java/io/ably/lib/objects/state/ObjectsStateChange.java, lib/src/main/java/io/ably/lib/objects/state/ObjectsStateEvent.java, live-objects/src/main/kotlin/io/ably/lib/objects/ObjectsState.kt, live-objects/src/main/kotlin/io/ably/lib/objects/ObjectsManager.kt
Implements getRoot (sync/async) in LiveObjects, adds state change subscription/unsubscription APIs, introduces internal state coordination, and aligns state enums and event emission.
LiveMap API Implementation
live-objects/src/main/kotlin/io/ably/lib/objects/type/livemap/DefaultLiveMap.kt, lib/src/main/java/io/ably/lib/objects/LiveMap.java
Implements core LiveMap methods (get, entries, keys, values, size) and updates async method signatures to use ObjectsCallback.
LiveCounter API Implementation
live-objects/src/main/kotlin/io/ably/lib/objects/type/livecounter/DefaultLiveCounter.kt, lib/src/main/java/io/ably/lib/objects/LiveCounter.java
Implements value() in DefaultLiveCounter, updates async method signatures to use ObjectsCallback.
Asynchronous Callback Refactor
lib/src/main/java/io/ably/lib/objects/ObjectsCallback.java, live-objects/src/main/kotlin/io/ably/lib/objects/Utils.kt, live-objects/src/main/kotlin/io/ably/lib/objects/DefaultLiveObjects.kt, lib/src/main/java/io/ably/lib/objects/LiveObjects.java, lib/src/main/java/io/ably/lib/objects/LiveMap.java, lib/src/main/java/io/ably/lib/objects/LiveCounter.java
Introduces ObjectsCallback<T>, refactors all async methods to use it, and adds coroutine-based async scope for callback execution and error handling.
Channel Metadata Access
lib/src/main/java/io/ably/lib/objects/Adapter.java, lib/src/main/java/io/ably/lib/objects/LiveObjectsAdapter.java, lib/src/main/java/io/ably/lib/realtime/ChannelBase.java
Adds methods to retrieve channel modes and state, and exposes channel options via a new getter.
Channel Access and State Validation
live-objects/src/main/kotlin/io/ably/lib/objects/Helpers.kt, live-objects/src/main/kotlin/io/ably/lib/objects/ErrorCodes.kt
Adds internal helpers to enforce channel mode/state requirements, introduces new error codes for validation failures.
LiveObjects Plugin and Disposal
lib/src/main/java/io/ably/lib/objects/LiveObjectsPlugin.java, live-objects/src/main/kotlin/io/ably/lib/objects/DefaultLiveObjectsPlugin.kt
Adds documentation to disposal methods and changes error handling to use structured errors.
Objects Subscription Interface
lib/src/main/java/io/ably/lib/objects/ObjectsSubscription.java
Introduces an interface for unsubscribing from object state events.
Test Fixtures & Helpers
live-objects/src/test/kotlin/io/ably/lib/objects/integration/helpers/*, live-objects/src/test/kotlin/io/ably/lib/objects/integration/helpers/fixtures/*, live-objects/src/test/kotlin/io/ably/lib/objects/integration/setup/IntegrationTest.kt, live-objects/src/test/kotlin/io/ably/lib/objects/integration/setup/Sandbox.kt
Adds helpers for REST-based object creation, payload building, state access, and test data fixtures for integration tests.
Integration Tests
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
Adds comprehensive integration tests for LiveCounter, LiveMap, and LiveObjects APIs, covering sync, operations, and state changes.
Unit Tests and Test Refactoring
live-objects/src/test/kotlin/io/ably/lib/objects/unit/UtilsTest.kt, live-objects/src/test/kotlin/io/ably/lib/objects/unit/objects/DefaultLiveObjectsTest.kt, live-objects/src/test/kotlin/io/ably/lib/objects/unit/objects/ObjectsManagerTest.kt, live-objects/src/test/kotlin/io/ably/lib/objects/unit/RealtimeObjectsTest.kt, live-objects/src/test/kotlin/io/ably/lib/objects/unit/LiveObjectTest.kt
Adds unit tests for utility and async scope logic, updates enum casing in tests, renames and removes redundant test classes.
Miscellaneous
live-objects/src/main/kotlin/io/ably/lib/objects/type/BaseLiveObject.kt
Removes unused import.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant LiveObjects
    participant ObjectsManager
    participant ObjectsAsyncScope
    participant Callback

    User->>LiveObjects: getRootAsync(callback)
    LiveObjects->>ObjectsAsyncScope: launchWithCallback(callback, suspend getRootAsync)
    ObjectsAsyncScope->>LiveObjects: suspend getRootAsync()
    LiveObjects->>ObjectsManager: ensureSynced()
    ObjectsManager-->>LiveObjects: (returns when synced)
    LiveObjects-->>ObjectsAsyncScope: return root LiveMap
    ObjectsAsyncScope->>Callback: onSuccess(root LiveMap)
Loading
sequenceDiagram
    participant User
    participant LiveMap
    participant LiveObjectsAdapter

    User->>LiveMap: get(key)
    LiveMap->>LiveObjectsAdapter: throwIfInvalidAccessApiConfiguration(channelName)
    LiveObjectsAdapter-->>LiveMap: (returns if valid)
    LiveMap-->>User: value or null
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Assessment against linked issues

Objective Addressed Explanation
Implement objects#getRoot method (#1122, ECO-5076)
Implement LiveMap public API methods (#1124)
Implement Objects State Change subscription/unsubscription (#1129)
Consistent error handling in async methods (#1136)

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
Addition of extensive test helpers and fixtures (e.g., live-objects/src/test/kotlin/io/ably/lib/objects/integration/helpers/PayloadBuilder.kt, RestObjects.kt, DataFixtures.kt, etc.) While these support integration tests, their breadth and depth go beyond the minimal requirements of the objectives, which focus on API and error handling, not test infrastructure.
Implementation of channel metadata access methods in Java adapter (lib/src/main/java/io/ably/lib/objects/Adapter.java, LiveObjectsAdapter.java) Direct channel mode/state querying is not explicitly required by the listed objectives.
Addition of new error codes for channel mode/state validation (live-objects/src/main/kotlin/io/ably/lib/objects/ErrorCodes.kt) The objectives do not mention extending error codes for channel validation.

Suggested reviewers

  • ttypic

Poem

In the warren of code, where objects now thrive,
The root can be fetched, and the maps are alive!
With callbacks that sing and states you can track,
Errors are handled—no bugs at your back.
Tests hop in abundance, all fixtures in tow—
A rabbit’s delight as the features now grow!
🐇✨

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/objects-getroot-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/1138/features August 6, 2025 11:29 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1138/javadoc August 6, 2025 11:31 Inactive
@sacOO7 sacOO7 force-pushed the feature/objects-getroot-refactored branch from 72a8ebb to b5d0b45 Compare August 6, 2025 11:32
@github-actions github-actions bot temporarily deployed to staging/pull/1138/features August 6, 2025 11:33 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1138/javadoc August 6, 2025 11:34 Inactive
…alue union type

- Added DefaultLiveObjectsTest with 187 lines of comprehensive Live Objects integration tests
- Implemented complete integration test suite covering getRoot functionality
- Enhanced test coverage for Objects state management and synchronization
- Added integration tests for ObjectsCallback interface and async operations
- Completed comprehensive test coverage for all Live Objects core functionality
@sacOO7 sacOO7 force-pushed the feature/objects-getroot-refactored branch from b5d0b45 to b1c9e47 Compare August 6, 2025 11:39
@sacOO7 sacOO7 changed the title Feature/objects getroot refactored [ECO-5076][LiveObjects] Implement getters for objects, map and counter Aug 6, 2025
@sacOO7 sacOO7 force-pushed the feature/object-sync-refactored branch 2 times, most recently from 0476f23 to 34449c7 Compare August 6, 2025 12:42
@sacOO7 sacOO7 marked this pull request as ready for review August 6, 2025 13:18
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

🔭 Outside diff range comments (1)
lib/src/main/java/io/ably/lib/objects/LiveCounter.java (1)

60-60: Fix inconsistent return type

The value() method returns Double but the JavaDoc on line 56 states it returns "the current value of the counter as a Long". Counter values are typically integers, so this should be Long for consistency.

-    Double value();
+    Long value();
♻️ Duplicate comments (5)
live-objects/src/test/kotlin/io/ably/lib/objects/unit/objects/DefaultLiveObjectsTest.kt (1)

62-63: Same observation as above on polling

Polling for ObjectsState.Synced repeats the potential flakiness; the suggestion above applies here as well.

live-objects/src/test/kotlin/io/ably/lib/objects/unit/objects/ObjectsManagerTest.kt (4)

75-77: Keep assertion messages in sync with enum renames

Same wording mismatch (SYNCED vs Synced) – adjust to reflect the new enum naming for consistency.


100-103: Direct state mutations—same concern as in DefaultLiveObjectsTest

Assigning defaultLiveObjects.state = ObjectsState.Synced sidesteps production pathways. Provide a helper that triggers the real transition to guard against future logic changes.


169-170: Assertion message mismatch for enum rename

Update “INITIALIZED” → “Initialized” here as well.


180-183: State mutation concern repeated

The same recommendation about avoiding direct state assignment applies.

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

7-14: Rename the test for brevity and intent clarity

testChannelObjectGetterTest repeats the word Test and does not convey the behaviour being asserted. A concise name such as channelObjectsGetter_returnsInstance() improves readability and keeps CI reports succinct.

-  fun testChannelObjectGetterTest() = runTest {
+  fun channelObjectsGetter_returnsInstance() = runTest {
lib/src/main/java/io/ably/lib/objects/LiveObjectsPlugin.java (2)

49-53: Align Javadoc with public API names

The note references ablyRealtimeClient.channels.release(channelName) but the public class is AblyRealtime. Consider using the exact type name (AblyRealtime) to avoid confusion for API consumers and future searches.


57-59: Clarify disposal semantics

The comment says “AblyClient has been closed using client.close()”. The public class is AblyRealtime, not AblyClient. Updating this wording keeps the documentation consistent and discoverable.

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

37-38: Potential flakiness due to busy-wait polling

assertWaiter { defaultLiveObjects.state == ObjectsState.Syncing } relies on polling every 100 ms for up to 10 s.
If the coroutine advancing the state is slow under heavy CI load the test may still pass but with a long delay, increasing build time.
Consider emitting a MutableStateFlow or using a CountDownLatch so the test can suspend until the exact signal is emitted instead of polling.

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

20-22: Message text still refers to legacy constant names

The assertion message says “state should be INITIALIZED” but the enum name is now Initialized. Updating messages avoids confusion when reading test failures.

- "Initial state should be INITIALIZED"
+ "Initial state should be Initialized"
live-objects/src/main/kotlin/io/ably/lib/objects/type/livemap/DefaultLiveMap.kt (2)

65-72: Consider direct implementation for keys() method.

The current implementation delegates to entries() which may be less efficient since it resolves all values just to extract keys.

Consider a more direct implementation:

 override fun keys(): Iterable<String> {
-  val iterableEntries = entries()
-  return sequence {
-    for (entry in iterableEntries) {
-      yield(entry.key) // RTLM12b
-    }
-  }.asIterable()
+  adapter.throwIfInvalidAccessApiConfiguration(channelName)
+  return sequence {
+    for ((key, entry) in data.entries) {
+      if (!entry.isEntryOrRefTombstoned(objectsPool)) {
+        yield(key)
+      }
+    }
+  }.asIterable()
 }

74-81: Consider direct implementation for values() method.

Similar to keys(), this could be more efficient with direct implementation rather than delegating to entries().

Consider a more direct implementation:

 override fun values(): Iterable<Any> {
-  val iterableEntries = entries()
-  return sequence {
-    for (entry in iterableEntries) {
-      yield(entry.value) // RTLM13b
-    }
-  }.asIterable()
+  adapter.throwIfInvalidAccessApiConfiguration(channelName)
+  return sequence {
+    for ((_, entry) in data.entries) {
+      val value = entry.getResolvedValue(objectsPool)
+      value?.let { yield(it) }
+    }
+  }.asIterable()
 }
live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveMapTest.kt (2)

3-5: Remove duplicate imports

Lines 4-5 contain redundant imports that are already covered by the wildcard import on line 3.

 import io.ably.lib.objects.*
-import io.ably.lib.objects.ObjectData
-import io.ably.lib.objects.ObjectValue
 import io.ably.lib.objects.integration.helpers.fixtures.createUserMapObject

205-205: Use consistent Long literal for size comparison

For consistency with other size assertions in the test, use 3L instead of 3.

-    assertEquals(3, testMap.size(), "Final map should have exactly 3 entries")
+    assertEquals(3L, testMap.size(), "Final map should have exactly 3 entries")
live-objects/src/test/kotlin/io/ably/lib/objects/integration/DefaultLiveObjectsTest.kt (1)

10-10: Remove unused import

The size import is not used in this file. The size() calls in the tests are methods on LiveMap instances, not this imported function.

-import io.ably.lib.objects.size
 import io.ably.lib.objects.state.ObjectsStateEvent
live-objects/src/main/kotlin/io/ably/lib/objects/Utils.kt (1)

62-98: Consider extracting duplicated error handling logic

The error handling logic is duplicated between launchWithCallback and launchWithVoidCallback. Consider extracting it to reduce duplication and improve maintainability.

+  private fun handleError(tag: String, callback: ObjectsCallback<*>, throwable: Throwable) {
+    when (throwable) {
+      is AblyException -> callback.onError(throwable)
+      else -> {
+        val ex = ablyException("Error executing operation", ErrorCode.BadRequest, cause = throwable)
+        callback.onError(ex)
+      }
+    }
+  }
+
   internal fun <T> launchWithCallback(callback: ObjectsCallback<T>, block: suspend () -> T) {
     scope.launch {
       try {
         val result = block()
         try { callback.onSuccess(result) } catch (t: Throwable) {
           Log.e(tag, "Error occurred while executing callback's onSuccess handler", t)
         } // catch and don't rethrow error from callback
       } catch (throwable: Throwable) {
-        when (throwable) {
-          is AblyException -> { callback.onError(throwable) }
-          else -> {
-            val ex = ablyException("Error executing operation", ErrorCode.BadRequest, cause = throwable)
-            callback.onError(ex)
-          }
-        }
+        handleError(tag, callback, throwable)
       }
     }
   }

   internal fun launchWithVoidCallback(callback: ObjectsCallback<Void>, block: suspend () -> Unit) {
     scope.launch {
       try {
         block()
         try { callback.onSuccess(null) } catch (t: Throwable) {
           Log.e(tag, "Error occurred while executing callback's onSuccess handler", t)
         } // catch and don't rethrow error from callback
       } catch (throwable: Throwable) {
-        when (throwable) {
-          is AblyException -> { callback.onError(throwable) }
-          else -> {
-            val ex = ablyException("Error executing operation", ErrorCode.BadRequest, cause = throwable)
-            callback.onError(ex)
-          }
-        }
+        handleError(tag, callback, throwable)
       }
     }
   }
live-objects/src/test/kotlin/io/ably/lib/objects/integration/helpers/RestObjects.kt (2)

22-24: Improve readability of null-check with exception.

The line break between the Elvis operator and exception makes the code less readable.

-    return operationRequest(channelName, mapCreateOp).objectId ?:
-    throw Exception("Failed to create map: no objectId returned")
+    return operationRequest(channelName, mapCreateOp).objectId
+      ?: throw Exception("Failed to create map: no objectId returned")

58-60: Improve readability of null-check with exception.

Same formatting issue as above for consistency.

-    return operationRequest(channelName, counterCreateOp).objectId
-      ?: throw Exception("Failed to create counter: no objectId returned")
+    return operationRequest(channelName, counterCreateOp).objectId
+      ?: throw Exception("Failed to create counter: no objectId returned")

@sacOO7 sacOO7 requested a review from ttypic August 7, 2025 08:04
Base automatically changed from feature/object-sync-refactored to main August 8, 2025 14:23
@sacOO7 sacOO7 merged commit da85ed6 into main Aug 8, 2025
13 checks passed
@sacOO7 sacOO7 deleted the feature/objects-getroot-refactored branch August 8, 2025 14:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

3 participants