Skip to content

Conversation

@lawrence-forooghian
Copy link
Collaborator

@lawrence-forooghian lawrence-forooghian commented Jul 31, 2025

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

Implements ably/specification#353. See commit messages for more details.

Summary by CodeRabbit

  • New Features

    • Implemented creation and mutation operations for live maps and counters, including support for initial values and error handling for invalid states or values.
    • Added support for generating unique object IDs and creation messages for live objects.
    • Enhanced error reporting with new error cases for invalid counter values and increment amounts.
  • Bug Fixes

    • Improved validation and error propagation for map and counter operations, ensuring correct behavior in edge cases and invalid states.
  • Refactor

    • Updated internal method signatures and logic to require additional context parameters and align with protocol specifications.
    • Improved separation of concerns in encoding/decoding logic for protocol messages.
  • Tests

    • Added comprehensive test suites for live map and counter creation, mutation, and error handling.
    • Introduced smoke tests for public API usage and extended mock infrastructure for better test coverage.
  • Documentation

    • Updated guidelines and inline documentation to clarify usage patterns and protocol compliance.
  • Style

    • Added Equatable conformance to multiple internal data structures for easier comparison and testing.

@coderabbitai
Copy link

coderabbitai bot commented Jul 31, 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 implements the full write API for LiveObjects in Swift, including creation, mutation, and message publishing for live counters and maps. It introduces new helper utilities for object creation, updates internal and public APIs to support the new flows, refines protocol encoding/decoding, and adds comprehensive unit and integration tests for all major write operations.

Changes

Cohort / File(s) Change Summary
Internal LiveCounter Write Implementation
Sources/AblyLiveObjects/Internal/InternalDefaultLiveCounter.swift
Implements increment and decrement methods, adding validation, error handling, message construction, and asynchronous publishing. Updates method signatures to require coreSDK.
Internal LiveMap Write Implementation
Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swift
Implements set and remove methods with state validation, message construction, error handling, and async publishing. Updates method signatures to require coreSDK and internal value types.
Internal RealtimeObjects Creation
Sources/AblyLiveObjects/Internal/InternalDefaultRealtimeObjects.swift
Implements createMap and createCounter methods, including channel state validation, creation operation/message construction, publishing, and pool management. Updates signatures to require coreSDK and internal value types.
Object Creation Utilities
Sources/AblyLiveObjects/Internal/ObjectCreationHelpers.swift
Adds new enum with helpers for generating creation operations, serializing initial values, generating unique IDs, and nonces for live objects. Includes protocol compliance and test-only utilities.
Objects Pool Enhancements
Sources/AblyLiveObjects/Internal/ObjectsPool.swift
Adds getOrCreateCounter and getOrCreateMap methods for typed, spec-compliant object retrieval/creation and initial value merging.
InternalLiveMapValue Enhancements
Sources/AblyLiveObjects/Internal/InternalLiveMapValue.swift
Adds initializer to convert public value to internal, and computed property for protocol data conversion.
Error Handling Enhancements
Sources/AblyLiveObjects/Utility/Errors.swift
Adds new error cases for invalid counter initial value and increment amount, with updated codes and messages.
Protocol Model Updates
Sources/AblyLiveObjects/Protocol/ObjectMessage.swift, Sources/AblyLiveObjects/Protocol/WireObjectMessage.swift
Refines encoding/decoding: moves action property out of partial operations, updates wire model logic, and adds Equatable conformance to multiple protocol structs.
Public Proxy Object Updates
Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultLiveCounter.swift, Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultLiveMap.swift, Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultRealtimeObjects.swift
Updates method calls to pass coreSDK and internal values, wraps internal objects in public proxies, and aligns with new internal API signatures.
Internal Struct Conformance
Sources/AblyLiveObjects/Internal/InternalObjectsMapEntry.swift
Adds Equatable conformance to InternalObjectsMapEntry.
JSONValue Convenience Accessors
Sources/AblyLiveObjects/Utility/JSONValue.swift
Adds computed properties for extracting object and array values.
Swift Linting/Guidelines
.cursor/rules/swift.mdc
Adds guideline to use Swift raw string literals for JSON strings.
CoreSDK Mock Enhancements
Tests/AblyLiveObjectsTests/Mocks/MockCoreSDK.swift
Adds async publish handler injection for test control, with thread safety.
Internal Write API Tests
Tests/AblyLiveObjectsTests/InternalDefaultLiveCounterTests.swift, Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift, Tests/AblyLiveObjectsTests/InternalDefaultRealtimeObjectsTests.swift
Adds comprehensive async tests for counter/map write methods and object creation, covering error handling, message correctness, and pool behavior.
Object Creation Helper Tests
Tests/AblyLiveObjectsTests/ObjectCreationHelpersTests.swift
Adds tests for creation operation correctness, ID generation, and encoding compliance.
Integration/Smoke Test
Tests/AblyLiveObjectsTests/AblyLiveObjectsTests.swift
Adds async smoke test covering public API usage and event propagation for counters and maps.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant PublicRealtimeObjects
    participant InternalRealtimeObjects
    participant ObjectCreationHelpers
    participant CoreSDK
    participant ObjectsPool

    Client->>PublicRealtimeObjects: createMap(entries)
    PublicRealtimeObjects->>InternalRealtimeObjects: createMap(entries, coreSDK)
    InternalRealtimeObjects->>ObjectCreationHelpers: creationOperationForLiveMap(entries, timestamp)
    ObjectCreationHelpers-->>InternalRealtimeObjects: MapCreationOperation (objectID, op, message)
    InternalRealtimeObjects->>CoreSDK: publish([OutboundObjectMessage])
    CoreSDK-->>InternalRealtimeObjects: (async)
    InternalRealtimeObjects->>ObjectsPool: getOrCreateMap(MapCreationOperation, ...)
    ObjectsPool-->>InternalRealtimeObjects: InternalDefaultLiveMap
    InternalRealtimeObjects-->>PublicRealtimeObjects: InternalDefaultLiveMap
    PublicRealtimeObjects->>Client: PublicDefaultLiveMap
Loading
sequenceDiagram
    participant Client
    participant PublicDefaultLiveMap
    participant InternalDefaultLiveMap
    participant CoreSDK

    Client->>PublicDefaultLiveMap: set(key, value)
    PublicDefaultLiveMap->>InternalDefaultLiveMap: set(key, InternalLiveMapValue, coreSDK)
    InternalDefaultLiveMap->>CoreSDK: publish([OutboundObjectMessage])
    CoreSDK-->>InternalDefaultLiveMap: (async)
    InternalDefaultLiveMap-->>PublicDefaultLiveMap: (success or error)
    PublicDefaultLiveMap-->>Client: (success or error)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Assessment against linked issues

Objective Addressed Explanation
Implement LiveObjects Swift Write API (ECO-5435): Internal methods for creating, incrementing, and mutating live counters and maps
Implement LiveObjects Swift Write API (ECO-5435): Public API for creating and mutating live objects, with correct wrapping and error handling
Implement LiveObjects Swift Write API (ECO-5435): Protocol message construction, encoding/decoding, and publishing
Implement LiveObjects Swift Write API (ECO-5435): Comprehensive unit and integration tests for write operations

Assessment against linked issues: Out-of-scope changes

No out-of-scope changes found.

Possibly related PRs

Suggested reviewers

  • maratal
  • umair-ably

Poem

In the warren where Swift code grows,
Counters tick and live maps flow.
With helpers, mocks, and tests in tow,
Each object gets an ID’s glow.
Messages published, errors caught,
This rabbit’s work—robust and taut!
🐇✨

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ECO-5435-write-API

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.
    • @coderabbitai modularize this function.
  • 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.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

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

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

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/51/AblyLiveObjects July 31, 2025 08:26 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/51/AblyLiveObjects July 31, 2025 13:18 Inactive
@lawrence-forooghian lawrence-forooghian changed the base branch from 44-JSON-map-entries-support to ECO-5461-deletions July 31, 2025 14:31
@github-actions github-actions bot temporarily deployed to staging/pull/51/AblyLiveObjects July 31, 2025 14:37 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/51/AblyLiveObjects July 31, 2025 15:38 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/51/AblyLiveObjects July 31, 2025 15:45 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/51/AblyLiveObjects July 31, 2025 15:49 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/51/AblyLiveObjects August 1, 2025 11:02 Inactive
@lawrence-forooghian lawrence-forooghian marked this pull request as ready for review August 1, 2025 11:28
@lawrence-forooghian lawrence-forooghian changed the title [WIP, ECO-5435] Implement the write spec [ECO-5435] Implement the write spec Aug 1, 2025
@github-actions github-actions bot temporarily deployed to staging/pull/51/AblyLiveObjects August 1, 2025 11:29 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/51/AblyLiveObjects August 1, 2025 11:35 Inactive
@lawrence-forooghian
Copy link
Collaborator Author

@coderabbitai full review

@coderabbitai
Copy link

coderabbitai bot commented Aug 1, 2025

✅ Actions performed

Full review triggered.

@github-actions github-actions bot temporarily deployed to staging/pull/51/AblyLiveObjects August 1, 2025 11:38 Inactive
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: 5

🧹 Nitpick comments (1)
Sources/AblyLiveObjects/Internal/ObjectCreationHelpers.swift (1)

218-222: Consider safer nonce generation implementation.

While the current implementation works, the force unwrap could be avoided for better safety:

-        return String((0 ..< 16).map { _ in letters.randomElement()! })
+        return String((0 ..< 16).compactMap { _ in letters.randomElement() })

Also, the TODO comment indicates specification clarification is needed for nonce requirements.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between fe7503c and 48e6937.

📒 Files selected for processing (21)
  • .cursor/rules/swift.mdc (1 hunks)
  • Sources/AblyLiveObjects/Internal/InternalDefaultLiveCounter.swift (1 hunks)
  • Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swift (1 hunks)
  • Sources/AblyLiveObjects/Internal/InternalDefaultRealtimeObjects.swift (1 hunks)
  • Sources/AblyLiveObjects/Internal/InternalLiveMapValue.swift (1 hunks)
  • Sources/AblyLiveObjects/Internal/InternalObjectsMapEntry.swift (1 hunks)
  • Sources/AblyLiveObjects/Internal/ObjectCreationHelpers.swift (1 hunks)
  • Sources/AblyLiveObjects/Internal/ObjectsPool.swift (1 hunks)
  • Sources/AblyLiveObjects/Protocol/ObjectMessage.swift (7 hunks)
  • Sources/AblyLiveObjects/Protocol/WireObjectMessage.swift (6 hunks)
  • Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultLiveCounter.swift (1 hunks)
  • Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultLiveMap.swift (1 hunks)
  • Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultRealtimeObjects.swift (1 hunks)
  • Sources/AblyLiveObjects/Utility/Errors.swift (2 hunks)
  • Sources/AblyLiveObjects/Utility/JSONValue.swift (1 hunks)
  • Tests/AblyLiveObjectsTests/AblyLiveObjectsTests.swift (1 hunks)
  • Tests/AblyLiveObjectsTests/InternalDefaultLiveCounterTests.swift (1 hunks)
  • Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift (1 hunks)
  • Tests/AblyLiveObjectsTests/InternalDefaultRealtimeObjectsTests.swift (2 hunks)
  • Tests/AblyLiveObjectsTests/Mocks/MockCoreSDK.swift (2 hunks)
  • Tests/AblyLiveObjectsTests/ObjectCreationHelpersTests.swift (1 hunks)
🧰 Additional context used
🧠 Learnings (20)
📓 Common learnings
Learnt from: CR
PR: ably/ably-cocoa-liveobjects-plugin#0
File: .cursor/rules/specification.mdc:0-0
Timestamp: 2025-07-29T08:07:37.861Z
Learning: The LiveObjects functionality is referred to in the Specification simply as 'Objects'.
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`.
📚 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:

  • .cursor/rules/swift.mdc
  • Sources/AblyLiveObjects/Utility/JSONValue.swift
  • Sources/AblyLiveObjects/Protocol/WireObjectMessage.swift
📚 Learning: applies to **/!(*test|*tests).swift : satisfy swiftlint's `explicit_acl` rule: all declarations shou...
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 **/!(*Test|*Tests).swift : Satisfy SwiftLint's `explicit_acl` rule: all declarations should specify Access Control Level keywords explicitly.

Applied to files:

  • .cursor/rules/swift.mdc
📚 Learning: applies to **/*.swift : when writing an array literal that starts with an initializer expression, st...
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 an array literal that starts with an initializer expression, start the initializer expression on the line after the opening square bracket of the array literal.

Applied to files:

  • .cursor/rules/swift.mdc
📚 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:

  • .cursor/rules/swift.mdc
  • Sources/AblyLiveObjects/Internal/InternalObjectsMapEntry.swift
  • Sources/AblyLiveObjects/Utility/Errors.swift
  • Sources/AblyLiveObjects/Internal/InternalLiveMapValue.swift
  • Tests/AblyLiveObjectsTests/AblyLiveObjectsTests.swift
  • Sources/AblyLiveObjects/Protocol/ObjectMessage.swift
  • Sources/AblyLiveObjects/Internal/InternalDefaultRealtimeObjects.swift
  • Tests/AblyLiveObjectsTests/ObjectCreationHelpersTests.swift
  • Tests/AblyLiveObjectsTests/Mocks/MockCoreSDK.swift
  • Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultLiveCounterTests.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultRealtimeObjectsTests.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift
  • Sources/AblyLiveObjects/Internal/ObjectCreationHelpers.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:

  • .cursor/rules/swift.mdc
  • Sources/AblyLiveObjects/Internal/InternalObjectsMapEntry.swift
  • Sources/AblyLiveObjects/Internal/InternalLiveMapValue.swift
  • Tests/AblyLiveObjectsTests/AblyLiveObjectsTests.swift
  • Sources/AblyLiveObjects/Protocol/ObjectMessage.swift
  • Tests/AblyLiveObjectsTests/ObjectCreationHelpersTests.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultLiveCounterTests.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultRealtimeObjectsTests.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift
  • Sources/AblyLiveObjects/Internal/ObjectCreationHelpers.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:

  • .cursor/rules/swift.mdc
  • Sources/AblyLiveObjects/Internal/InternalObjectsMapEntry.swift
  • Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultLiveMap.swift
  • Sources/AblyLiveObjects/Internal/InternalLiveMapValue.swift
  • Tests/AblyLiveObjectsTests/AblyLiveObjectsTests.swift
  • Sources/AblyLiveObjects/Internal/InternalDefaultLiveCounter.swift
  • Sources/AblyLiveObjects/Protocol/ObjectMessage.swift
  • Sources/AblyLiveObjects/Internal/InternalDefaultRealtimeObjects.swift
  • Sources/AblyLiveObjects/Internal/ObjectsPool.swift
  • Tests/AblyLiveObjectsTests/ObjectCreationHelpersTests.swift
  • Tests/AblyLiveObjectsTests/Mocks/MockCoreSDK.swift
  • Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultLiveCounterTests.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultRealtimeObjectsTests.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift
  • Sources/AblyLiveObjects/Internal/ObjectCreationHelpers.swift
📚 Learning: applies to **/*.swift : when writing initializer expressions, when the type that is being initialize...
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 initializer expressions, when the type that is being initialized can be inferred, favour using the implicit `.init(…)` form instead of explicitly writing the type name.

Applied to files:

  • .cursor/rules/swift.mdc
📚 Learning: applies to **/*.swift : when writing enum value expressions, when the type that is being initialized...
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 enum value expressions, when the type that is being initialized can be inferred, favour using the implicit `.caseName` form instead of explicitly writing the type name.

Applied to files:

  • .cursor/rules/swift.mdc
📚 Learning: applies to **/!(*test|*tests).swift : when writing an `extension` of a type, favour placing the acce...
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 **/!(*Test|*Tests).swift : When writing an `extension` of a type, favour placing the access level on the declaration of the extension rather than each of its individual members.

Applied to files:

  • .cursor/rules/swift.mdc
📚 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:07:58.385Z
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:

  • .cursor/rules/swift.mdc
  • Tests/AblyLiveObjectsTests/InternalDefaultLiveCounterTests.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultRealtimeObjectsTests.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.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:08:00.588Z
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/AblyLiveObjectsTests.swift
  • Tests/AblyLiveObjectsTests/ObjectCreationHelpersTests.swift
  • Tests/AblyLiveObjectsTests/Mocks/MockCoreSDK.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultLiveCounterTests.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultRealtimeObjectsTests.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift
📚 Learning: applies to **/tests/**/*.swift : use the swift testing framework (`import testing`), not xctest....
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 : Use the Swift Testing framework (`import Testing`), not XCTest.

Applied to files:

  • Tests/AblyLiveObjectsTests/AblyLiveObjectsTests.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/AblyLiveObjectsTests.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultLiveCounterTests.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultRealtimeObjectsTests.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift
📚 Learning: the liveobjects functionality is referred to in the specification simply as 'objects'....
Learnt from: CR
PR: ably/ably-cocoa-liveobjects-plugin#0
File: .cursor/rules/specification.mdc:0-0
Timestamp: 2025-07-29T08:07:37.861Z
Learning: The LiveObjects functionality is referred to in the Specification simply as 'Objects'.

Applied to files:

  • Sources/AblyLiveObjects/Protocol/ObjectMessage.swift
  • Sources/AblyLiveObjects/Internal/ObjectCreationHelpers.swift
📚 Learning: applies to **/tests/**/*.swift : follow the guidelines given under 'attributing tests to a spec poin...
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 : Follow the guidelines given under 'Attributing tests to a spec point' in the file `CONTRIBUTING.md` in order to tag the unit tests with the relevant specification points. Make sure to follow the exact format of the comments as described in that file. Pay particular attention to the difference between the meaning of `@spec` and `@specPartial` and be sure not to write `@spec` multiple times for the same specification point.

Applied to files:

  • Tests/AblyLiveObjectsTests/ObjectCreationHelpersTests.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultLiveCounterTests.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift
📚 Learning: applies to **/tests/**/*.swift : when writing tests, follow the guidelines given under 'attributing ...
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, follow the guidelines given under 'Attributing tests to a spec point' in the file `CONTRIBUTING.md` in order to tag the unit tests with the relevant specification points. Make sure to follow the exact format of the comments as described in that file. Pay particular attention to the difference between the meaning of `@spec` and `@specPartial` and be sure not to write `@spec` multiple times for the same specification point.

Applied to files:

  • Tests/AblyLiveObjectsTests/ObjectCreationHelpersTests.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultLiveCounterTests.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.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/ObjectCreationHelpersTests.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultRealtimeObjectsTests.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift
📚 Learning: applies to **/tests/**/*.swift : only add labels to test cases or suites when the label is different...
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 : Only add labels to test cases or suites when the label is different to the name of the suite `struct` or test method.

Applied to files:

  • Tests/AblyLiveObjectsTests/ObjectCreationHelpersTests.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultLiveCounterTests.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/ObjectCreationHelpersTests.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultRealtimeObjectsTests.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift
🧬 Code Graph Analysis (5)
Sources/AblyLiveObjects/Utility/Errors.swift (1)
Sources/AblyLiveObjects/Internal/InternalDefaultLiveCounter.swift (1)
  • value (82-90)
Sources/AblyLiveObjects/Internal/InternalLiveMapValue.swift (1)
Sources/AblyLiveObjects/Internal/InternalDefaultLiveCounter.swift (1)
  • value (82-90)
Sources/AblyLiveObjects/Internal/InternalDefaultLiveCounter.swift (3)
Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultLiveCounter.swift (2)
  • increment (29-31)
  • decrement (33-35)
Sources/AblyLiveObjects/Internal/CoreSDK.swift (2)
  • validateChannelState (56-68)
  • publish (32-39)
Tests/AblyLiveObjectsTests/Helpers/TestFactories.swift (1)
  • counterOp (386-388)
Tests/AblyLiveObjectsTests/Mocks/MockCoreSDK.swift (2)
Sources/AblyLiveObjects/Internal/CoreSDK.swift (1)
  • publish (32-39)
Tests/AblyLiveObjectsTests/Helpers/Assertions.swift (1)
  • protocolRequirementNotImplemented (2-7)
Sources/AblyLiveObjects/Internal/ObjectCreationHelpers.swift (1)
Tests/AblyLiveObjectsTests/ObjectCreationHelpersTests.swift (1)
  • createObjectID (201-214)
⏰ 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). (12)
  • GitHub Check: Example app, iOS (Xcode 16.3)
  • GitHub Check: Example app, tvOS (Xcode 16.3)
  • GitHub Check: Example app, macOS (Xcode 16.3)
  • GitHub Check: Xcode, release configuration, macOS (Xcode 16.3)
  • GitHub Check: Xcode, release configuration, tvOS (Xcode 16.3)
  • GitHub Check: Xcode, release configuration, iOS (Xcode 16.3)
  • GitHub Check: Xcode, tvOS (Xcode 16.3)
  • GitHub Check: Xcode, macOS (Xcode 16.3)
  • GitHub Check: Xcode, iOS (Xcode 16.3)
  • GitHub Check: SPM, release configuration (Xcode 16.3)
  • GitHub Check: SPM (Xcode 16.3)
  • GitHub Check: Generate code coverage
🔇 Additional comments (56)
.cursor/rules/swift.mdc (1)

14-14: LGTM! Excellent coding guideline addition.

Using Swift raw string literals for JSON strings improves readability and reduces escaping errors, which is particularly valuable for the LiveObjects implementation that involves extensive JSON handling.

Sources/AblyLiveObjects/Internal/InternalObjectsMapEntry.swift (1)

4-4: LGTM! Appropriate protocol conformance addition.

Adding Equatable conformance enables equality comparisons for InternalObjectsMapEntry instances, which is beneficial for the LiveObjects write operations. Swift will automatically synthesize the implementation since all properties are Equatable.

Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultLiveCounter.swift (2)

30-30: LGTM! Correct API alignment.

The addition of the coreSDK parameter correctly aligns with the updated internal method signature for write operations.


34-34: LGTM! Correct API alignment.

The addition of the coreSDK parameter correctly aligns with the updated internal method signature for write operations.

Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultLiveMap.swift (2)

79-81: LGTM! Correct implementation of public-to-internal value conversion.

The conversion from public LiveMapValue to InternalLiveMapValue and the addition of the coreSDK parameter correctly enable write operations while maintaining API separation.


85-85: LGTM! Correct API alignment.

The addition of the coreSDK parameter correctly aligns with the updated internal method signature for write operations.

Sources/AblyLiveObjects/Utility/JSONValue.swift (1)

181-197: LGTM! Well-implemented convenience accessors.

The new computed properties provide clean, convenient access to associated values following standard Swift patterns. The implementation correctly returns the associated value or nil using pattern matching, improving code readability for JSON handling operations.

Sources/AblyLiveObjects/Utility/Errors.swift (4)

9-10: LGTM! Well-structured error cases for counter validation.

The new error cases follow the established pattern and provide clear validation feedback for invalid counter values and increment amounts.


17-19: Good adherence to specification requirements.

The error code mapping correctly references the specification requirements (RTO12f1, RTLC12e1) and uses the appropriate .invalidParameterValue error code.


26-29: Consistent HTTP status code mapping.

The 400 status code is appropriate for invalid parameter validation errors and maintains consistency with the existing error case.


38-41: Clear and descriptive error messages.

The error messages clearly indicate the validation requirement (finite numbers) and include the invalid value for debugging purposes.

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

14-31: LGTM! Conversion logic is sound despite runtime checks.

The initializer correctly converts public types to internal representations. While the runtime type checks aren't ideal, they're appropriately acknowledged with TODO comments referencing issue #37 for future improvement.


36-61: Excellent specification compliance for protocol conversion.

The toObjectData property correctly implements the protocol requirements (RTO11f4 and RTLM20e4) for converting internal values to wire format. The handling of primitive types and object references is thorough and accurate.

Tests/AblyLiveObjectsTests/Mocks/MockCoreSDK.swift (3)

9-9: LGTM! Consistent with existing mutable state patterns.

The new _publishHandler property follows the same nonisolated(unsafe) pattern as the existing _channelState property.


15-21: Good fallback behavior for testing flexibility.

The publish method appropriately uses the injected handler when available and falls back to the existing protocolRequirementNotImplemented() behavior, maintaining backwards compatibility.


36-41: Proper thread-safe handler injection.

The setPublishHandler method correctly uses mutex protection to safely set the handler, consistent with the existing thread-safety patterns in this mock class.

Tests/AblyLiveObjectsTests/AblyLiveObjectsTests.swift (1)

126-187: Excellent comprehensive smoke test of the write API.

This test effectively exercises the complete public API workflow including:

  • Object creation with initial values
  • Subscription to updates
  • Various mutation operations (set, increment, remove)
  • Verification of both state changes and update events

The test structure is well-organized and properly validates the asynchronous, event-driven nature of the LiveObjects system.

Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultRealtimeObjects.swift (4)

38-50: LGTM! Proper conversion and wrapping for map creation with entries.

The method correctly converts public LiveMapValue entries to internal representations using the new initializer, passes the coreSDK parameter, and wraps the result with the appropriate public proxy.


52-63: Consistent pattern for parameterless map creation.

The method follows the same pattern as the entries version, maintaining consistency in the API implementation.


65-75: Proper counter creation with initial value.

The method correctly passes the count parameter and coreSDK to the internal implementation and wraps the result appropriately.


77-87: Complete and consistent counter creation pattern.

The parameterless counter creation follows the established pattern, completing the set of creation methods with consistent implementation.

Tests/AblyLiveObjectsTests/InternalDefaultLiveCounterTests.swift (5)

426-444: LGTM! Comprehensive channel state validation testing.

The test correctly validates that increment throws appropriate errors for invalid channel states (.detached, .failed, .suspended) as specified in RTLC12c. The error code validation (90001) and status code (400) are accurate.


446-466: LGTM! Thorough validation of invalid amount handling.

The test properly covers RTLC12e1 by testing all non-finite values (NaN, infinity, -infinity) and validates the correct error code (40003) and status code (400).


468-497: LGTM! Comprehensive outbound message validation.

The test effectively validates all aspects of the published message per RTLC12e2-e4 and RTLC12f:

  • Correct action (.counterInc)
  • Correct objectId propagation
  • Correct amount encoding as NSNumber
  • Single message published

The use of MockCoreSDK with custom publish handler is well implemented.


499-517: LGTM! Proper error propagation testing.

The test correctly validates that publish failures are properly converted and propagated as ARTErrorInfo, ensuring robust error handling in the increment operation.


521-540: LGTM! Appropriate smoke test for decrement operation.

The test correctly validates RTLC13b by confirming that decrement behaves as the negation of increment. The assertion that the published amount is -10.5 (negated from the input 10.5) effectively demonstrates the opposite behavior. The approach of treating this as a smoke test is sensible since the underlying increment logic is tested elsewhere.

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

160-160: LGTM! Accurate comment update.

The comment correctly reflects that PartialWireObjectOperation now excludes both action and objectId properties, which aligns with its usage for encoding initial values.


232-270: LGTM! Well-structured refactoring of action handling.

The separation of concerns is well-implemented:

  • WireObjectOperation now explicitly handles action and objectId decoding/encoding
  • Proper delegation to PartialWireObjectOperation for common fields
  • Clean separation maintains functionality while improving code organization

The encoding logic correctly adds the action field after encoding the partial operation.


355-355: LGTM! Appropriate Equatable conformance.

Adding Equatable conformance to WireObjectsCounterOp enables equality comparisons which are valuable for testing and validation purposes.


409-409: LGTM! Appropriate Equatable conformance.

Adding Equatable conformance to WireObjectsCounter enables equality comparisons which are valuable for testing and validation purposes.

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

126-129: LGTM! Clean delegation to increment.

The decrement method correctly implements RTLC13b by delegating to increment with the negated amount. This is an elegant and correct approach.

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

21-21: LGTM! Good addition of Equatable conformances.

Adding Equatable conformance to these protocol message structures is beneficial for testing and debugging, allowing for clear equality comparisons between expected and actual message structures.

Also applies to: 46-46, 57-57, 66-66, 71-71, 78-78, 83-83


34-34: LGTM! Documentation correctly updated.

The documentation now accurately reflects that PartialObjectOperation excludes both action and objectId properties, which aligns with the code changes in this file.


150-152: LGTM! Clean separation of concerns in encoding/decoding.

The refactored encoding and decoding logic properly separates the responsibilities - ObjectOperation now explicitly handles action and objectId while delegating other properties to PartialObjectOperation. This makes the code more maintainable and the separation of concerns clearer.

Also applies to: 190-193

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

317-351: LGTM! Comprehensive implementation of RTO12h1.

The getOrCreateCounter method correctly implements the "find or create zero-value" behavior specified in RTO12h1. The type checking with preconditionFailure is appropriate for catching programming errors, and the method properly handles both existing and new counter creation scenarios.


361-396: LGTM! Comprehensive implementation of RTO11h1.

The getOrCreateMap method correctly implements the "find or create zero-value" behavior specified in RTO11h1. It properly handles map-specific concerns including semantics and passing the objectsPool for nested merges during initial value merging.

Tests/AblyLiveObjectsTests/ObjectCreationHelpersTests.swift (3)

22-143: LGTM! Comprehensive test coverage for map creation.

This test thoroughly validates the map creation operation including:

  • All supported entry types (object references and primitives)
  • JSON serialization correctness per RTO13
  • Object ID format validation per RTO14
  • Nonce generation per RTO11f11
  • Proper denormalization of properties

The test coverage is excellent and follows the specification attribution guidelines correctly.


151-192: LGTM! Thorough counter creation test.

The counter creation test appropriately validates:

  • Initial value serialization per RTO13
  • Counter-specific properties per RTO12f2a
  • Object ID format per RTO14
  • Action type and nonce generation

The test is well-structured and covers all essential aspects of counter creation operations.


201-214: LGTM! Clever edge case testing for object ID generation.

This test excellently validates RTO14 object ID generation with a particularly good choice of test data. The nonce "arbitraryNonceABC" is specifically chosen to produce Base64 characters (+, /, =) that must be converted to Base64URL format (-, _, removed), ensuring the encoding implementation is correct.

Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift (1)

1365-1365: Missing @test annotation on test function.

The publishesCorrectObjectMessage function won't be executed by the test runner without the @test annotation.

Apply this diff to add the missing annotation:

+        @Test
         func publishesCorrectObjectMessage() async throws {
⛔ Skipped due to learnings
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 : Follow the guidelines given under 'Attributing tests to a spec point' in the file `CONTRIBUTING.md` in order to tag the unit tests with the relevant specification points. Make sure to follow the exact format of the comments as described in that file. Pay particular attention to the difference between the meaning of `@spec` and `@specPartial` and be sure not to write `@spec` multiple times for the same specification point.
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.
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, follow the guidelines given under 'Attributing tests to a spec point' in the file `CONTRIBUTING.md` in order to tag the unit tests with the relevant specification points. Make sure to follow the exact format of the comments as described in that file. Pay particular attention to the difference between the meaning of `@spec` and `@specPartial` and be sure not to write `@spec` multiple times for the same specification point.
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`.
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`.
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 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`.
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 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.
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.
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.
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`.
Tests/AblyLiveObjectsTests/InternalDefaultRealtimeObjectsTests.swift (6)

10-14: LGTM! Good test enhancement for time-dependent functionality.

Adding the optional clock parameter with a default value is a clean way to support deterministic timestamp testing while maintaining backward compatibility with existing tests.


1047-1061: Well-structured channel state validation test.

Good use of parameterized testing to cover all invalid channel states per RTO11d specification.


1067-1105: Comprehensive test coverage for map creation flow.

The test properly validates message publishing (RTO11g), initial value merging (RTO11h3a), and pool management (RTO11h3b). The mock clock approach for deterministic timestamp testing is well implemented.

Note: The TODO comment on line 1095 indicates a future enhancement to use server time.


1109-1132: Good edge case coverage for empty map creation.

Test properly validates RTO11f4b specification for creating maps without initial entries.


1136-1173: Excellent test for concurrent object creation scenario.

This sophisticated test properly validates RTO11h2 by simulating a race condition where an object appears in the pool before the create operation completes. The use of reference equality (===) correctly verifies that the existing object is reused rather than replaced.


1198-1298: Well-structured counter creation tests.

The remaining counter tests properly validate message publishing (RTO12g), initial value handling (RTO12h3a), pool management (RTO12h3b), zero value creation (RTO12f2a), and existing object reuse (RTO12h2). Good consistency with the map tests structure.

Sources/AblyLiveObjects/Internal/ObjectCreationHelpers.swift (6)

1-3: Correct module imports.

The use of internal import AblyPlugin follows the established pattern for library code, and the other imports are appropriate for the functionality implemented.


10-44: Well-designed creation operation structs.

Good API design separating the non-nil objectID and operation properties from the nullable fields in objectMessage. The documentation clearly explains the rationale.


51-96: Correct implementation of counter creation per RTO12f.

The method properly implements all specification steps from RTO12f2 through RTO12f12, including initial value creation, JSON serialization, nonce generation, and object ID construction.


103-160: Correct implementation of map creation per RTO11f.

The method properly implements all specification steps from RTO11f4 through RTO11f13. The use of LWW semantics is consistent throughout, and the entry conversion is handled correctly.


165-179: Proper implementation of RTO13 JSON encoding.

The method correctly implements RTO13b (OM4 encoding) and RTO13c (JSON string conversion). The use of preconditionFailure for conversion errors is appropriate since this indicates a programmer error.


182-215: Correct implementation of object ID generation per RTO14.

The method properly implements:

  • RTO14b1: SHA-256 digest generation
  • RTO14b2: Base64URL encoding (correctly replacing +-, /_, removing =)
  • RTO14c: Proper ID format [type]:[hash]@[timestamp]

The timestamp conversion to milliseconds is correctly implemented.

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

160-192: LGTM! Well-structured implementation of the map creation flow.

The implementation correctly validates channel state, constructs the creation operation, publishes it, and manages the object pool access with proper thread safety. The error handling with type conversions is appropriate.

Note: There's a TODO comment about switching from local clock to server time per RTO11f5, tracked in issue #50.


194-197: LGTM! Clean convenience method implementation.

Correctly delegates to the main createMap method with empty entries as per RTO11f4b.


199-237: Well-implemented counter creation with proper validation.

The implementation correctly validates the initial count value for finiteness, handles channel state validation, and manages the object pool with thread safety. Good error handling throughout.

Note: There's a TODO comment about switching from local clock to server time per RTO12f5, tracked in issue #50.


239-242: LGTM! Consistent convenience method implementation.

Correctly delegates to the main createCounter method with a default count of 0 as per RTO12f2a.

@lawrence-forooghian lawrence-forooghian force-pushed the ECO-5461-deletions branch 2 times, most recently from e334349 to 2167277 Compare August 1, 2025 14:06
Based on [1] at cb11ba8. Internal interfaces by me, implementation and
tests by Cursor (both with some tweaking by me).

Haven't implemented:

- the RTO11e etc echoMessages check — deferred to #49
- the RTO11c etc channel mode checking - same reason as 392fae3
- using server time for generating object ID — deferred to #50

[1] ably/specification#353
Based on [1] at cb11ba8. Code by me, tests by Cursor and tidied up by
me.

Channel mode checking and echoMessages check omitted as in e65643a.

[1] ably/specification#353
Just to convince myself that the write API is somewhat working. Will get
further confidence upon porting across more of the JS integration tests
in the future.
@lawrence-forooghian lawrence-forooghian merged commit 1474140 into main Aug 13, 2025
18 checks passed
@lawrence-forooghian lawrence-forooghian deleted the ECO-5435-write-API branch August 13, 2025 10:55
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