Skip to content

Conversation

@lawrence-forooghian
Copy link
Collaborator

@lawrence-forooghian lawrence-forooghian commented Aug 4, 2025

Note: This PR is based on top of #51; please review that one first.

This enables the integration tests that I'd ported from JS in fa255c1 but which were disabled because the features they depended on hadn't been implemented yet. The enabling of the tests is preceded by some improvements to logging (which I used to help me debug some failing tests), and some fixes for test failures. See commit messages for more details.

Summary by CodeRabbit

  • New Features

    • Enhanced logging with improved formatting for object messages and added detailed debug descriptions for key objects.
    • Logging can now be prefixed with a custom identifier in test clients.
  • Refactor

    • Centralized map and counter logic within internal state structures for improved modularity and maintainability.
    • Simplified and streamlined asynchronous test helpers using modern async sequence patterns.
  • Bug Fixes

    • Improved handling of optional data fields in maps and protocol messages to prevent errors and ensure correct behavior.
  • Tests

    • Updated and enabled tests to reflect changes in data handling and logging, ensuring more robust and accurate test coverage.

@coderabbitai
Copy link

coderabbitai bot commented Aug 4, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

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

Walkthrough

This change introduces significant refactoring to LiveMap and related types, centralizing logic and synchronization within internal state structures. It also makes the data property of map entries optional throughout the codebase, updates logging with improved formatting, and simplifies test helpers and assertions to accommodate the new optionality and refactored async patterns. Several debug string representations are added for easier logging and debugging.

Changes

Cohort / File(s) Change Summary
LiveMap and MapEntry Refactor
Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swift, Sources/AblyLiveObjects/Internal/InternalObjectsMapEntry.swift, Sources/AblyLiveObjects/Protocol/ObjectMessage.swift, Sources/AblyLiveObjects/Protocol/WireObjectMessage.swift
Refactored LiveMap logic into internal state, made data property of map entries optional, updated related methods and helpers, and added debug string conformances.
LiveCounter Logic Refactor
Sources/AblyLiveObjects/Internal/InternalDefaultLiveCounter.swift
Delegated value retrieval and validation to internal mutable state struct, simplifying locking and validation logic.
CoreSDK & InternalPlugin Logging and Client Dispatch
Sources/AblyLiveObjects/Internal/CoreSDK.swift, Sources/AblyLiveObjects/Internal/DefaultInternalPlugin.swift, Sources/AblyLiveObjects/Public/ARTRealtimeChannel+Objects.swift
Added logger property and improved logging, updated method signatures to include client parameter, and ensured correct logger and client usage throughout.
Logging Utilities
Sources/AblyLiveObjects/Utility/LoggingUtilities.swift
Added a utility for formatting arrays of debug-printable objects for logging.
Debug Logging Improvements
Sources/AblyLiveObjects/Internal/InternalDefaultRealtimeObjects.swift
Updated logging to use new formatting utility for object messages.
Test Helpers and Factories
Tests/AblyLiveObjectsTests/Helpers/ClientHelper.swift, Tests/AblyLiveObjectsTests/Helpers/TestFactories.swift
Updated test helpers to support optional data, added prefixed logger for test clients, and adjusted factory signatures.
LiveMap and WireObject Tests
Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift, Tests/AblyLiveObjectsTests/WireObjectMessageTests.swift
Updated assertions to handle optional data properties using optional chaining.
Integration Tests Refactor
Tests/AblyLiveObjectsTests/JS Integration Tests/ObjectsIntegrationTests.swift
Refactored async update waiting to use AsyncStream, enabled previously skipped tests, and improved scenario setup and test clarity.
Submodule Update
ably-cocoa
Updated the ably-cocoa submodule commit reference.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant CoreSDK
    participant Logger
    participant InternalPlugin
    participant PluginAPI

    Client->>CoreSDK: publish(objectMessages)
    CoreSDK->>Logger: log formatted objectMessages
    CoreSDK->>InternalPlugin: sendObject(objectMessages, channel, client, pluginAPI)
    InternalPlugin->>PluginAPI: dispatch sendObject on client internal queue
    PluginAPI-->>InternalPlugin: sendObject result
    InternalPlugin-->>CoreSDK: async result
    CoreSDK-->>Client: async result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Assessment against linked issues

Objective Addressed Explanation
Migrate and refactor integration tests for LiveObjects Swift (ECO-5465)

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
Update of ably-cocoa submodule reference (ably-cocoa) Submodule update is not directly related to integration test migration or refactor.
Addition of debug string conformances for protocol types (Sources/AblyLiveObjects/Protocol/ObjectMessage.swift, Sources/AblyLiveObjects/Protocol/WireObjectMessage.swift) While helpful for debugging, explicit debug string implementation is not mentioned in the migration objective.

Possibly related PRs

Suggested reviewers

  • maratal
  • umair-ably

Poem

In the warren of code, a refactor hops,
Making LiveMap logic tidy, with fewer stops.
Optional data now gently appears,
Logging’s more clever, debugging with cheers!
Async streams ripple, tests run anew,
This bunny’s delighted—so should be you!

(\(<)
( -.-)
o_(")(")

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ECO-5465-enable-disabled-integration-tests

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/55/AblyLiveObjects August 4, 2025 15:45 Inactive
@lawrence-forooghian
Copy link
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Aug 4, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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)
Tests/AblyLiveObjectsTests/Helpers/TestFactories.swift (1)

408-417: Consider making internalMapEntry data parameter optional for consistency

The internalMapEntry factory method still requires non-optional ObjectData while mapEntry now accepts optional ObjectData?. This creates an inconsistency between the two factory methods that should ideally mirror each other.

Consider updating the signature to match:

 static func internalMapEntry(
     tombstonedAt: Date? = nil,
     timeserial: String? = "ts1",
-    data: ObjectData,
+    data: ObjectData?,
 ) -> InternalObjectsMapEntry {
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 4e8e076 and e2a78f7.

📒 Files selected for processing (16)
  • Sources/AblyLiveObjects/Internal/CoreSDK.swift (1 hunks)
  • Sources/AblyLiveObjects/Internal/DefaultInternalPlugin.swift (1 hunks)
  • Sources/AblyLiveObjects/Internal/InternalDefaultLiveCounter.swift (2 hunks)
  • Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swift (6 hunks)
  • Sources/AblyLiveObjects/Internal/InternalDefaultRealtimeObjects.swift (2 hunks)
  • Sources/AblyLiveObjects/Internal/InternalObjectsMapEntry.swift (1 hunks)
  • Sources/AblyLiveObjects/Protocol/ObjectMessage.swift (4 hunks)
  • Sources/AblyLiveObjects/Protocol/WireObjectMessage.swift (3 hunks)
  • Sources/AblyLiveObjects/Public/ARTRealtimeChannel+Objects.swift (1 hunks)
  • Sources/AblyLiveObjects/Utility/LoggingUtilities.swift (1 hunks)
  • Tests/AblyLiveObjectsTests/Helpers/ClientHelper.swift (2 hunks)
  • Tests/AblyLiveObjectsTests/Helpers/TestFactories.swift (1 hunks)
  • Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift (3 hunks)
  • Tests/AblyLiveObjectsTests/JS Integration Tests/ObjectsIntegrationTests.swift (12 hunks)
  • Tests/AblyLiveObjectsTests/WireObjectMessageTests.swift (5 hunks)
  • ably-cocoa (1 hunks)
🧰 Additional context used
🧠 Learnings (10)
📚 Learning: applies to ablyliveobjects/**/!(*test|*tests).swift : when importing the ably module inside the ably...
Learnt from: CR
PR: ably/ably-cocoa-liveobjects-plugin#0
File: .cursor/rules/swift.mdc:0-0
Timestamp: 2025-07-29T08:07:47.875Z
Learning: Applies to AblyLiveObjects/**/!(*Test|*Tests).swift : When importing the Ably module inside the AblyLiveObjects library code (non-test code), use `import Ably`.

Applied to files:

  • Tests/AblyLiveObjectsTests/JS Integration Tests/ObjectsIntegrationTests.swift
  • Sources/AblyLiveObjects/Internal/InternalObjectsMapEntry.swift
  • Sources/AblyLiveObjects/Utility/LoggingUtilities.swift
  • Tests/AblyLiveObjectsTests/Helpers/ClientHelper.swift
  • Sources/AblyLiveObjects/Protocol/ObjectMessage.swift
  • Sources/AblyLiveObjects/Internal/InternalDefaultRealtimeObjects.swift
  • Sources/AblyLiveObjects/Internal/CoreSDK.swift
  • Tests/AblyLiveObjectsTests/Helpers/TestFactories.swift
  • Sources/AblyLiveObjects/Public/ARTRealtimeChannel+Objects.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift
  • Tests/AblyLiveObjectsTests/WireObjectMessageTests.swift
  • Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swift
📚 Learning: applies to **/tests/**/*.swift : when you need to import the following modules in the tests, do so i...
Learnt from: CR
PR: ably/ably-cocoa-liveobjects-plugin#0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-07-29T08:07:58.385Z
Learning: Applies to **/Tests/**/*.swift : When you need to import the following modules in the tests, do so in the following way: Ably: use `import Ably`; AblyLiveObjects: use `@testable import AblyLiveObjects`; AblyPlugin: use `import AblyPlugin`; do not do `internal import`.

Applied to files:

  • Tests/AblyLiveObjectsTests/JS Integration Tests/ObjectsIntegrationTests.swift
  • Sources/AblyLiveObjects/Utility/LoggingUtilities.swift
  • Tests/AblyLiveObjectsTests/Helpers/ClientHelper.swift
  • Sources/AblyLiveObjects/Internal/CoreSDK.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift
  • Tests/AblyLiveObjectsTests/WireObjectMessageTests.swift
📚 Learning: applies to ablyliveobjects/**/!(*test|*tests).swift : when importing the ablyplugin module inside th...
Learnt from: CR
PR: ably/ably-cocoa-liveobjects-plugin#0
File: .cursor/rules/swift.mdc:0-0
Timestamp: 2025-07-29T08:07:47.875Z
Learning: Applies to AblyLiveObjects/**/!(*Test|*Tests).swift : When importing the AblyPlugin module inside the AblyLiveObjects library code (non-test code), use `internal import AblyPlugin`.

Applied to files:

  • Tests/AblyLiveObjectsTests/JS Integration Tests/ObjectsIntegrationTests.swift
  • Sources/AblyLiveObjects/Internal/InternalObjectsMapEntry.swift
  • Sources/AblyLiveObjects/Utility/LoggingUtilities.swift
  • Tests/AblyLiveObjectsTests/Helpers/ClientHelper.swift
  • Sources/AblyLiveObjects/Internal/DefaultInternalPlugin.swift
  • Sources/AblyLiveObjects/Internal/CoreSDK.swift
  • Sources/AblyLiveObjects/Public/ARTRealtimeChannel+Objects.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift
  • Tests/AblyLiveObjectsTests/WireObjectMessageTests.swift
  • Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swift
📚 Learning: applies to **/tests/**/*.swift : do not use `fatalerror` in response to a test expectation failure. ...
Learnt from: CR
PR: ably/ably-cocoa-liveobjects-plugin#0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-07-29T08:08:00.588Z
Learning: Applies to **/Tests/**/*.swift : Do not use `fatalError` in response to a test expectation failure. Favour the usage of Swift Testing's `#require` macro.

Applied to files:

  • Tests/AblyLiveObjectsTests/JS Integration Tests/ObjectsIntegrationTests.swift
📚 Learning: applies to **/tests/**/*.swift : add comments that explain when some piece of test data is not impor...
Learnt from: CR
PR: ably/ably-cocoa-liveobjects-plugin#0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-07-29T08:08:00.588Z
Learning: Applies to **/Tests/**/*.swift : Add comments that explain when some piece of test data is not important for the scenario being tested.

Applied to files:

  • Tests/AblyLiveObjectsTests/JS Integration Tests/ObjectsIntegrationTests.swift
  • Tests/AblyLiveObjectsTests/Helpers/TestFactories.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift
  • Tests/AblyLiveObjectsTests/WireObjectMessageTests.swift
📚 Learning: applies to **/tests/**/*.swift : when you need to pass a logger to internal components in the tests,...
Learnt from: CR
PR: ably/ably-cocoa-liveobjects-plugin#0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-07-29T08:08:00.588Z
Learning: Applies to **/Tests/**/*.swift : When you need to pass a logger to internal components in the tests, pass `TestLogger()`.

Applied to files:

  • Tests/AblyLiveObjectsTests/Helpers/ClientHelper.swift
  • Sources/AblyLiveObjects/Internal/CoreSDK.swift
  • Sources/AblyLiveObjects/Public/ARTRealtimeChannel+Objects.swift
📚 Learning: applies to **/tests/**/*.swift : when writing tests, make sure to add comments that explain when som...
Learnt from: CR
PR: ably/ably-cocoa-liveobjects-plugin#0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-07-29T08:07:58.385Z
Learning: Applies to **/Tests/**/*.swift : When writing tests, make sure to add comments that explain when some piece of test data is not important for the scenario being tested.

Applied to files:

  • Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift
  • Tests/AblyLiveObjectsTests/WireObjectMessageTests.swift
📚 Learning: applies to **/tests/**/*.swift : when creating `testsonly_` property declarations, do not write gene...
Learnt from: CR
PR: ably/ably-cocoa-liveobjects-plugin#0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-07-29T08:07:58.385Z
Learning: Applies to **/Tests/**/*.swift : When creating `testsOnly_` property declarations, do not write generic comments of the form 'Test-only access to the private createOperationIsMerged property'; the meaning of these properties is already well understood.

Applied to files:

  • Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift
  • Tests/AblyLiveObjectsTests/WireObjectMessageTests.swift
📚 Learning: applies to **/tests/**/*.swift : when you need to unwrap an optional value in the tests, favour usin...
Learnt from: CR
PR: ably/ably-cocoa-liveobjects-plugin#0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-07-29T08:08:00.588Z
Learning: Applies to **/Tests/**/*.swift : When you need to unwrap an optional value in the tests, favour using `#require` instead of `guard let`.

Applied to files:

  • Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift
  • Tests/AblyLiveObjectsTests/WireObjectMessageTests.swift
📚 Learning: applies to **/*.swift : when writing jsonvalue or wirevalue types, favour using the literal syntax e...
Learnt from: CR
PR: ably/ably-cocoa-liveobjects-plugin#0
File: .cursor/rules/swift.mdc:0-0
Timestamp: 2025-07-29T08:07:47.875Z
Learning: Applies to **/*.swift : When writing JSONValue or WireValue types, favour using the literal syntax enabled by their conformance to the `ExpressibleBy*Literal` protocols where possible.

Applied to files:

  • Tests/AblyLiveObjectsTests/WireObjectMessageTests.swift
  • Sources/AblyLiveObjects/Protocol/WireObjectMessage.swift
🧬 Code Graph Analysis (5)
Tests/AblyLiveObjectsTests/JS Integration Tests/ObjectsIntegrationTests.swift (3)
Sources/AblyLiveObjects/Public/PublicTypes.swift (1)
  • updates (425-437)
Tests/AblyLiveObjectsTests/JS Integration Tests/ObjectsHelper.swift (1)
  • createAndSetOnMap (380-397)
Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swift (2)
  • get (112-114)
  • get (806-822)
Sources/AblyLiveObjects/Internal/InternalDefaultLiveCounter.swift (1)
Sources/AblyLiveObjects/Internal/CoreSDK.swift (1)
  • validateChannelState (62-74)
Sources/AblyLiveObjects/Internal/InternalDefaultRealtimeObjects.swift (2)
Tests/AblyLiveObjectsTests/Helpers/ClientHelper.swift (1)
  • log (55-58)
Sources/AblyLiveObjects/Utility/LoggingUtilities.swift (1)
  • formatObjectMessagesForLogging (7-13)
Sources/AblyLiveObjects/Internal/DefaultInternalPlugin.swift (1)
Sources/AblyLiveObjects/Utility/InternalError.swift (2)
  • toInternalError (28-30)
  • toInternalError (34-36)
Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift (1)
Tests/AblyLiveObjectsTests/ObjectMessageTests.swift (3)
  • number (133-145)
  • number (229-241)
  • number (326-338)
⏰ 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). (5)
  • GitHub Check: Xcode, iOS (Xcode 16.3)
  • GitHub Check: Xcode, tvOS (Xcode 16.3)
  • GitHub Check: Xcode, macOS (Xcode 16.3)
  • GitHub Check: Generate code coverage
  • GitHub Check: Xcode, iOS (Xcode 16.3)
🔇 Additional comments (34)
Sources/AblyLiveObjects/Utility/LoggingUtilities.swift (3)

1-1: LGTM!

Appropriate import for the utility functionality.


3-6: LGTM!

The enum structure and documentation follow Swift conventions well. The internal access level is appropriate for utility code within the module.


7-13: LGTM! Clean and efficient implementation.

The method implementation is well-structured with:

  • Modern Swift generics syntax using some CustomDebugStringConvertible
  • Proper empty array handling
  • Clean multi-line formatting with consistent indentation
  • Efficient string concatenation approach

This utility will provide consistent, readable log formatting across the codebase.

ably-cocoa (1)

1-1: Confirm the submodule SHA is pushed and reachable

I ran git ls-remote against https://github.com/ably/ably-cocoa.git for bc19368559fe1b860d18f375e421e8fd2526572f but saw no output (since ls-remote only shows refs). Please manually verify that:

  • The commit bc19368559fe1b860d18f375e421e8fd2526572f is present on the ably/ably-cocoa remote (e.g. included in a branch or tag).
  • All CI mirrors and forks have this commit (so git submodule update --init --recursive picks it up).
  • Any dependency managers (SPM/Carthage/CocoaPods) that vendor Ably Cocoa reference this exact SHA.
Sources/AblyLiveObjects/Internal/InternalObjectsMapEntry.swift (1)

12-12: LGTM: Clean transition to optional data property

The change from ObjectData to ObjectData? is consistent with the broader refactoring to support optional data in map entries. This allows for proper handling of tombstoned or empty entries.

Sources/AblyLiveObjects/Internal/InternalDefaultRealtimeObjects.swift (2)

392-392: LGTM: Improved logging format for better debugging

The use of LoggingUtilities.formatObjectMessagesForLogging will produce much more readable log output compared to direct array interpolation, especially when dealing with multiple object messages.


492-492: LGTM: Consistent logging improvement

Same formatting improvement as above, ensuring consistent and readable log output across both sync and regular object message handling.

Tests/AblyLiveObjectsTests/Helpers/TestFactories.swift (1)

396-396: Good alignment with optional data changes

The parameter change to optional ObjectData? correctly aligns with the broader refactoring to make map entry data optional throughout the codebase.

Sources/AblyLiveObjects/Public/ARTRealtimeChannel+Objects.swift (1)

15-22: LGTM: Improved initialization order and logger consistency

Moving the logger initialization before coreSDK creation allows the same logger instance to be passed to DefaultCoreSDK and ensures consistent logging behavior across all components. This is a clean refactoring that maintains functionality while improving the initialization pattern.

Tests/AblyLiveObjectsTests/WireObjectMessageTests.swift (4)

183-183: LGTM: Correct optional chaining for optional data property

The addition of optional chaining (?.data?.string) correctly handles the fact that the data property in wire object map entries is now optional, preventing potential runtime crashes.


285-285: LGTM: Consistent optional handling

Same correct pattern of optional chaining to safely access the optional data property.


491-491: LGTM: Proper optional chaining in map entry tests

Both assertions correctly use optional chaining to handle the optional data property in wire map entries.

Also applies to: 494-494


587-587: LGTM: Complete optional handling in wire map entry tests

The test assertions correctly handle the optional data property with proper optional chaining, ensuring tests remain robust with the new optional data semantics.

Also applies to: 596-596

Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift (3)

537-538: LGTM! Correct adaptation to optional data property.

The test correctly uses optional chaining to access the data property fields, reflecting the change from non-optional to optional ObjectsMapEntry.data.


720-720: LGTM! Correct nil check for optional data property.

The assertion correctly verifies that data is nil for a MAP_REMOVE operation, which aligns with the specification requirement "Set ObjectsMapEntry.data to undefined/null" (RTLM8a2a).


749-749: LGTM! Consistent nil check for new entry data.

The test correctly verifies that newly created entries from MAP_REMOVE operations have nil data, which is consistent with the specification requirement (RTLM8b1).

Sources/AblyLiveObjects/Internal/CoreSDK.swift (4)

19-19: LGTM! Good addition of logging capability.

Adding the logger property enables structured logging within the CoreSDK, which is beneficial for debugging and monitoring.


24-25: LGTM! Constructor properly updated for logger injection.

The constructor correctly accepts and stores the logger parameter, maintaining consistency with the dependency injection pattern used throughout the codebase.

Also applies to: 30-30


36-36: LGTM! Valuable debug logging added.

The debug log statement using LoggingUtilities.formatObjectMessagesForLogging will provide helpful visibility into object message publishing for debugging purposes.


42-42: LGTM! Client parameter addition aligns with DefaultInternalPlugin changes.

Adding the client parameter to the sendObject call is consistent with the updated method signature in DefaultInternalPlugin.swift, enabling proper queue dispatching.

Sources/AblyLiveObjects/Internal/InternalDefaultLiveCounter.swift (2)

83-83: LGTM! Clean delegation to internal state method.

The refactoring properly delegates the validation and value retrieval to the MutableState, improving encapsulation and consistency with similar patterns in the codebase.


417-423: LGTM! Well-implemented internal state method.

The new value(coreSDK:) method in MutableState correctly:

  • Validates channel state per RTLC5b specification
  • Returns the counter data per RTLC5c specification
  • Maintains the same error handling behavior as the original implementation

This refactoring centralizes state-related logic within the MutableState struct, which is a good architectural improvement.

Sources/AblyLiveObjects/Internal/DefaultInternalPlugin.swift (2)

131-131: LGTM! Client parameter addition enables proper queue dispatching.

Adding the client parameter allows the method to obtain the correct internal queue for thread-safe message sending, which is essential for proper SDK operation.


137-151: LGTM! Proper async dispatch implementation.

The implementation correctly:

  • Obtains the client's internal queue via pluginAPI.internalQueue(for: client)
  • Dispatches the sendObject call asynchronously on that queue
  • Properly handles both success and error cases in the completion handler
  • Uses the existing continuation pattern for async/await integration

This ensures thread-safe message sending while maintaining the existing async interface.

Sources/AblyLiveObjects/Protocol/WireObjectMessage.swift (2)

562-604: LGTM! Well-structured debug descriptions

The CustomDebugStringConvertible implementations provide comprehensive and consistent debug representations that will enhance logging and debugging capabilities.


434-434: No issues found with optional data usage
All direct accesses to WireObjectsMapEntry.data now use safe optional handling, and initializations accept the new optional parameter correctly:

  • In Sources/AblyLiveObjects/Protocol/ObjectMessage.swift, data is unwrapped via if let wireObjectData = wireObjectsMapEntry.data { … }.
  • All tests in WireObjectMessageTests.swift use optional chaining (entry.data?.string) or pass a WireObjectData literal into the now-optional parameter without forcing unwraps.

No further changes are required.

Sources/AblyLiveObjects/Protocol/ObjectMessage.swift (2)

74-74: LGTM! Consistent optional data handling

The changes correctly implement optional data handling for ObjectsMapEntry, maintaining consistency with the wire format changes in WireObjectsMapEntry.

Also applies to: 389-393, 405-405


476-603: Excellent debug string implementations

The CustomDebugStringConvertible conformances are well-designed:

  • Consistent formatting across all types
  • Smart choice to display byte count instead of raw data
  • Clear hierarchical representation for nested structures
Tests/AblyLiveObjectsTests/JS Integration Tests/ObjectsIntegrationTests.swift (4)

91-97: Excellent refactoring to use AsyncStream

The simplified implementation using AsyncStream.first is much cleaner and more idiomatic than the previous subscription-based approach. This removes manual continuation management and makes the code more maintainable.


160-174: Good test setup improvements

Creating ClientHelper.PartialClientOptions once and modifying it for different test scenarios reduces duplication. The logIdentifier addition will help distinguish client logs during test runs.


304-312: Consistent AsyncStream usage pattern

The tests correctly use the updates() method to obtain AsyncStreams and pass them to the wait helpers. The pattern of creating multiple streams for concurrent update monitoring is appropriate.

Also applies to: 327-339


296-296: Great to see previously disabled tests now enabled

The enabling of these integration tests indicates that the required features have been implemented, which aligns with the PR's objective of "[ECO-5465] Enable disabled integration tests".

Also applies to: 371-371, 513-513, 569-569, 624-624

Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swift (2)

616-617: LGTM! Proper handling of optional data property

The changes correctly handle the new optionality of the data property:

  • Optional parameter type in method signature
  • Safe optional chaining when accessing objectId
  • Setting data to nil for tombstoned entries is cleaner than using empty ObjectData

Also applies to: 645-645, 682-683, 691-691


805-935: Well-structured refactoring with proper RTLM compliance

The refactored methods correctly implement the RTLM specifications:

  • Proper channel state validation (RTLM5c, RTLM10c, RTLM11c)
  • Correct tombstone handling at multiple levels (map, entry, and referenced objects)
  • Systematic value conversion following the specification order
  • Thread safety maintained through outer mutex locks

The helper methods isEntryTombstoned and convertEntryToLiveMapValue provide good separation of concerns and avoid code duplication.

The log output was really hard to read; asked Cursor to do this with the
following guidance:

- one InboundObjectMessage per line
- I don't need to see any of the type names in the output, just their
  properties
- I don't need to see "Optional" in the output; if it's nil just write
  nil, if it's non-nil then just display the wrapped value

Have not checked its output in any detail.
The bumped ably-cocoa submodule requires this.
This gives us atomicity instead of breaking it up into multiple mutex
acquisitions. Should have done this when I implemented these methods.
Make sure that we perform the subscription synchronously so as not to
miss events. This is a nuance that I missed when looking at Cursor's
generated code in fa255c1.

The way in which I've chosen to do this is not particularly elegant (and
to be honest Swift doesn't make it very easy to do so) but I think that
it's the closest to the JS code, which hopefully will mean Cursor will
be able to easily apply this pattern when translating further JS tests.
The features that these depended on have now been implemented.
Base automatically changed from ECO-5435-write-API to main August 13, 2025 10:55
@lawrence-forooghian lawrence-forooghian merged commit 3fa3be5 into main Aug 13, 2025
18 checks passed
@lawrence-forooghian lawrence-forooghian deleted the ECO-5465-enable-disabled-integration-tests branch August 13, 2025 10:56
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.

3 participants