Skip to content

[ECO-5483] Loosening validation for Occupancy#340

Merged
maratal merged 2 commits intomainfrom
337-message-validation-for-all-features
Aug 18, 2025
Merged

[ECO-5483] Loosening validation for Occupancy#340
maratal merged 2 commits intomainfrom
337-message-validation-for-all-features

Conversation

@maratal
Copy link
Copy Markdown
Collaborator

@maratal maratal commented Jul 24, 2025

Closes #337

Loosening validation for Occupancy (for everything else was already there).
Add self capture for subscription handlers instead of particular objects capture list.

Also:
Loose validation for presence as well despite the fact it's not mentioned in the task, since clientID and updatedAt is non null in the PresenceMember structure. I could make them nullable, but it doesn't have a lot of sense IMO (internal conversation - https://ably-real-time.slack.com/archives/C03JDBVM5MY/p1753443612066009?thread_ts=1753373214.880469&cid=C03JDBVM5MY)

Related PR - #330

Summary by CodeRabbit

Summary by CodeRabbit

  • Bug Fixes
    • Improved memory management for chat message, reaction, and occupancy event subscriptions to prevent potential crashes or retain cycles.
    • Enhanced handling of occupancy event data to be more resilient when expected data fields are missing.
    • Updated presence event processing to handle missing client ID and timestamp fields gracefully without errors.
  • Refactor
    • Streamlined event listener callbacks for better safety and maintainability.
  • Tests
    • Added a test to verify occupancy events emit zero values when invalid data is received.

@maratal maratal requested a review from umair-ably July 24, 2025 16:15
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jul 24, 2025

Walkthrough

This change updates subscription closures in several classes to capture self weakly, preventing retain cycles. It also relaxes validation for occupancy event data, defaulting to empty dictionaries if expected fields are missing. Error throwing for missing presence fields is replaced with default values. An unused error enum is removed. Additionally, a new test verifies occupancy event handling when invalid data is received. New error cases related to channel attachment are added and used for improved error handling.

Changes

File(s) Change Summary
Sources/AblyChat/DefaultMessageReactions.swift Subscription closures now capture self weakly and safely unwrap it; early return if self is nil.
Sources/AblyChat/DefaultMessages.swift Subscription closure now captures self weakly and safely unwraps it; early return if self is nil; improved error handling using new ChatError cases.
Sources/AblyChat/DefaultOccupancy.swift Subscription closure captures self weakly; validation for data and metrics relaxed to allow empty dicts.
Sources/AblyChat/DefaultPresence.swift Removed error throwing for missing clientId and timestamp; replaced with default empty string and current date.
Sources/AblyChat/DefaultRoomReactions.swift Subscription and unsubscribe closures capture self weakly; removed unused error enum.
Sources/AblyChat/Errors.swift Added new ChatError cases for channel attachment errors with associated error codes and descriptions.
Tests/AblyChatTests/DefaultRoomOccupancyTests.swift Added async test verifying zero-value occupancy event emission on invalid event data.

Sequence Diagram(s)

sequenceDiagram
    participant SDKClient
    participant DefaultMessages
    participant EventSource

    SDKClient->>DefaultMessages: subscribe()
    DefaultMessages->>EventSource: subscribe (closure captures self weakly)
    EventSource-->>DefaultMessages: event callback
    alt self is alive
        DefaultMessages->>SDKClient: handle event
    else self is nil
        EventSource-->>EventSource: closure returns early
    end
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Possibly related PRs

Suggested reviewers

  • umair-ably

Poem

A rabbit hops through code so neat,
Weak captures make retain cycles obsolete.
Validation relaxed, events flow free,
No more strong holds—just let it be!
With closures safe and memory light,
The chat hops forward, swift and bright.
🐇✨

Note

⚡️ Unit Test Generation is now available in beta!

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


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0441c2b and 7b6d013.

📒 Files selected for processing (2)
  • Sources/AblyChat/DefaultMessages.swift (2 hunks)
  • Sources/AblyChat/Errors.swift (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • Sources/AblyChat/DefaultMessages.swift
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Sources/AblyChat/DefaultOccupancy.swift:10-13
Timestamp: 2025-05-12T21:01:14.109Z
Learning: The `Occupancy` protocol in the Ably Chat Swift SDK is annotated with `@MainActor`, making all conforming types like `DefaultOccupancy` automatically main actor-isolated without requiring explicit annotations on their methods.
Learnt from: maratal
PR: ably/ably-chat-swift#165
File: Sources/AblyChat/Reaction.swift:14-14
Timestamp: 2024-12-10T01:59:02.065Z
Learning: For the 'ably-chat-swift' repository, documentation-only PRs should focus exclusively on public methods and properties. Avoid suggesting changes to internal comments or private methods in such PRs.
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Sources/AblyChat/DefaultTyping.swift:131-138
Timestamp: 2025-05-12T21:04:36.263Z
Learning: In the AblyChat Swift codebase, SubscriptionHandle closures should capture self weakly with `[weak self]` to avoid potential retain cycles, particularly when calling channel.unsubscribe() within the closure.
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Sources/AblyChat/RoomLifecycleManager.swift:611-624
Timestamp: 2025-05-22T20:57:48.147Z
Learning: In AblyChat Swift, when using continuations with subscription callbacks, the continuation object is captured directly by the closure and doesn't depend on `self`. Even with `[weak self]` capture, the continuation will still be resumed properly.
Learnt from: maratal
PR: ably/ably-chat-swift#262
File: Tests/AblyChatTests/DefaultRoomReactionsTests.swift:0-0
Timestamp: 2025-05-23T16:20:38.904Z
Learning: In Swift tests using mock objects like MockRealtimeChannel, explicit subscription cleanup (via unsubscribe() or similar methods) is generally unnecessary since the mocks don't maintain real connections and will be garbage collected after the test completes.
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Example/AblyChatExample/ContentView.swift:203-209
Timestamp: 2025-05-12T21:11:08.937Z
Learning: In the AblyChat Swift codebase, SubscriptionHandle doesn't need to be retained/stored to keep subscriptions active. The subscription callbacks continue to work even when the handle is not stored, as the underlying services maintain their own storage of callbacks that remain registered until explicitly unsubscribed via the handle's unsubscribe() method.
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Example/AblyChatExample/ContentView.swift:203-209
Timestamp: 2025-05-12T21:11:08.937Z
Learning: In the AblyChat Swift codebase, SubscriptionHandle doesn't need to be retained/stored to keep subscriptions active. The subscription continues to work even if the handle is not stored, as the underlying services maintain references to the callbacks until explicitly unsubscribed via the handle's unsubscribe() method.
Learnt from: maratal
PR: ably/ably-chat-swift#249
File: Tests/AblyChatTests/DefaultMessagesTests.swift:45-48
Timestamp: 2025-05-22T19:17:21.392Z
Learning: The `let doIt = {}` closures in DefaultMessagesTests.swift are temporary workarounds for compiler crashes (related to issue #233) and will be removed once Xcode 16.3 is released, so they should not be flagged for missing async/throws annotations.
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Sources/AblyChat/SubscriptionAsyncSequence.swift:36-41
Timestamp: 2025-06-29T16:02:43.988Z
Learning: In the AblyChat Swift codebase, the fatalError in SubscriptionAsyncSequence.swift's mock async sequence handling (around line 39) is intentional and should not be flagged. This fatalError catches programmer errors when a throwing AsyncSequence is incorrectly passed to the mock initializer, which is meant for testing/development purposes.
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Sources/AblyChat/DefaultPresence.swift:269-277
Timestamp: 2025-05-16T22:07:33.286Z
Learning: In Swift, capturing an instance method in a closure's capture list (like `[someMethod]`) implicitly captures `self` strongly, as instance methods are functions that take `self` as their first parameter. This can lead to retain cycles, and should be avoided by using `[weak self]` instead.
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Sources/AblyChat/SubscriptionHandleStorage.swift:37-40
Timestamp: 2025-05-12T21:02:28.274Z
Learning: In the AblyChat Swift codebase, the `SubscriptionHandle` struct has an `unsubscribe()` method for terminating subscriptions, not a `cancel()` method.
Sources/AblyChat/Errors.swift (5)

Learnt from: maratal
PR: #286
File: Sources/AblyChat/SubscriptionAsyncSequence.swift:36-41
Timestamp: 2025-06-29T16:02:43.988Z
Learning: In the AblyChat Swift codebase, the fatalError in SubscriptionAsyncSequence.swift's mock async sequence handling (around line 39) is intentional and should not be flagged. This fatalError catches programmer errors when a throwing AsyncSequence is incorrectly passed to the mock initializer, which is meant for testing/development purposes.

Learnt from: maratal
PR: #293
File: Example/AblyChatExample/ContentView.swift:94-99
Timestamp: 2025-06-14T21:47:20.509Z
Learning: In the Ably Chat Swift example app, using fatalError for missing clientID is intentional and appropriate since it represents a programmer error rather than a recoverable runtime condition. The clientID is considered an essential configuration requirement.

Learnt from: maratal
PR: #165
File: Sources/AblyChat/Reaction.swift:14-14
Timestamp: 2024-12-10T01:59:02.065Z
Learning: For the 'ably-chat-swift' repository, documentation-only PRs should focus exclusively on public methods and properties. Avoid suggesting changes to internal comments or private methods in such PRs.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/DefaultTyping.swift:131-138
Timestamp: 2025-05-12T21:04:36.263Z
Learning: In the AblyChat Swift codebase, SubscriptionHandle closures should capture self weakly with [weak self] to avoid potential retain cycles, particularly when calling channel.unsubscribe() within the closure.

Learnt from: maratal
PR: #165
File: docs-coverage-report:5-8
Timestamp: 2024-12-10T01:59:12.404Z
Learning: In the AblyChat Swift project, documentation coverage should focus on public methods and properties. Private and internal entities do not require documentation.

⏰ 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). (34)
  • GitHub Check: Example app, macOS (Xcode 16.1)
  • GitHub Check: Example app, macOS (Xcode 16.2)
  • GitHub Check: Example app, macOS (Xcode 16.3)
  • GitHub Check: Example app, tvOS (Xcode 16.3)
  • GitHub Check: Xcode, release configuration, iOS (Xcode 16.3)
  • GitHub Check: Example app, iOS (Xcode 16.2)
  • GitHub Check: Example app, tvOS (Xcode 16.1)
  • GitHub Check: Example app, tvOS (Xcode 16.2)
  • GitHub Check: Xcode, release configuration, macOS (Xcode 16.3)
  • GitHub Check: Example app, iOS (Xcode 16.3)
  • GitHub Check: Example app, iOS (Xcode 16.1)
  • GitHub Check: Xcode, release configuration, tvOS (Xcode 16.2)
  • GitHub Check: Xcode, release configuration, tvOS (Xcode 16.3)
  • GitHub Check: Xcode, macOS (Xcode 16.2)
  • GitHub Check: Xcode, release configuration, tvOS (Xcode 16.1)
  • GitHub Check: Xcode, tvOS (Xcode 16.2)
  • GitHub Check: Xcode, release configuration, macOS (Xcode 16.2)
  • GitHub Check: Xcode, release configuration, iOS (Xcode 16.1)
  • GitHub Check: Xcode, macOS (Xcode 16.3)
  • GitHub Check: Xcode, tvOS (Xcode 16.3)
  • GitHub Check: Xcode, release configuration, iOS (Xcode 16.2)
  • GitHub Check: Xcode, iOS (Xcode 16.2)
  • GitHub Check: Xcode, iOS (Xcode 16.3)
  • GitHub Check: Xcode, tvOS (Xcode 16.1)
  • GitHub Check: Xcode, release configuration, macOS (Xcode 16.1)
  • GitHub Check: Xcode, macOS (Xcode 16.1)
  • GitHub Check: Xcode, iOS (Xcode 16.1)
  • GitHub Check: SPM, release configuration (Xcode 16.3)
  • GitHub Check: SPM (Xcode 16.3)
  • GitHub Check: SPM, release configuration (Xcode 16.1)
  • GitHub Check: SPM (Xcode 16.2)
  • GitHub Check: SPM, release configuration (Xcode 16.2)
  • GitHub Check: SPM (Xcode 16.1)
  • GitHub Check: Generate code coverage
🔇 Additional comments (4)
Sources/AblyChat/Errors.swift (4)

178-179: LGTM: Well-defined error cases for channel attachment scenarios.

The new error cases are appropriately named and structured. The channelFailedToAttach case correctly includes a cause parameter for error chaining, while attachSerialIsNotDefined represents a specific condition that doesn't require additional context.


214-217: LGTM: Appropriate status code mappings.

Both new error cases correctly map to .badRequest (400), which is appropriate for client-side validation errors related to channel attachment failures and missing attach serials.


274-277: LGTM: Clear and informative error descriptions.

The localized descriptions are well-written and provide appropriate context. The use of String(describing: cause) correctly handles the optional ARTErrorInfo parameter.


288-302: LGTM: Correct cause property handling.

The cause property correctly handles both new error cases - returning the associated cause for channelFailedToAttach and nil for attachSerialIsNotDefined. This maintains consistency with the existing error handling pattern.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 337-message-validation-for-all-features

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.

@maratal maratal requested a review from ttypic July 24, 2025 16:16
@github-actions github-actions Bot temporarily deployed to staging/pull/340/AblyChat July 24, 2025 16:17 Inactive
@maratal maratal force-pushed the 337-message-validation-for-all-features branch from 2522ee1 to 65fee52 Compare July 24, 2025 20:35
@github-actions github-actions Bot temporarily deployed to staging/pull/340/AblyChat July 24, 2025 20:36 Inactive
… there).

Add self capture for subscription handlers instead of particular objects capture list.
@maratal maratal force-pushed the 337-message-validation-for-all-features branch from 65fee52 to d161f7b Compare July 24, 2025 23:48
@github-actions github-actions Bot temporarily deployed to staging/pull/340/AblyChat July 24, 2025 23:49 Inactive
…oned in the task, since `clientID` and `updatedAt` is non null in the `PresenceMember` structure. I could make them nullable, but it doesn't have a lot of sense IMO (internal conversation - https://ably-real-time.slack.com/archives/C03JDBVM5MY/p1753443612066009?thread_ts=1753373214.880469&cid=C03JDBVM5MY)
@github-actions github-actions Bot temporarily deployed to staging/pull/340/AblyChat July 26, 2025 12:42 Inactive
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between d161f7b and 0441c2b.

📒 Files selected for processing (1)
  • Sources/AblyChat/DefaultPresence.swift (2 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Sources/AblyChat/DefaultOccupancy.swift:10-13
Timestamp: 2025-05-12T21:01:14.109Z
Learning: The `Occupancy` protocol in the Ably Chat Swift SDK is annotated with `@MainActor`, making all conforming types like `DefaultOccupancy` automatically main actor-isolated without requiring explicit annotations on their methods.
Learnt from: maratal
PR: ably/ably-chat-swift#165
File: Sources/AblyChat/Reaction.swift:14-14
Timestamp: 2024-12-10T01:59:02.065Z
Learning: For the 'ably-chat-swift' repository, documentation-only PRs should focus exclusively on public methods and properties. Avoid suggesting changes to internal comments or private methods in such PRs.
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Sources/AblyChat/DefaultTyping.swift:131-138
Timestamp: 2025-05-12T21:04:36.263Z
Learning: In the AblyChat Swift codebase, SubscriptionHandle closures should capture self weakly with `[weak self]` to avoid potential retain cycles, particularly when calling channel.unsubscribe() within the closure.
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Sources/AblyChat/RoomLifecycleManager.swift:611-624
Timestamp: 2025-05-22T20:57:48.147Z
Learning: In AblyChat Swift, when using continuations with subscription callbacks, the continuation object is captured directly by the closure and doesn't depend on `self`. Even with `[weak self]` capture, the continuation will still be resumed properly.
Learnt from: maratal
PR: ably/ably-chat-swift#262
File: Tests/AblyChatTests/DefaultRoomReactionsTests.swift:0-0
Timestamp: 2025-05-23T16:20:38.904Z
Learning: In Swift tests using mock objects like MockRealtimeChannel, explicit subscription cleanup (via unsubscribe() or similar methods) is generally unnecessary since the mocks don't maintain real connections and will be garbage collected after the test completes.
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Example/AblyChatExample/ContentView.swift:203-209
Timestamp: 2025-05-12T21:11:08.937Z
Learning: In the AblyChat Swift codebase, SubscriptionHandle doesn't need to be retained/stored to keep subscriptions active. The subscription callbacks continue to work even when the handle is not stored, as the underlying services maintain their own storage of callbacks that remain registered until explicitly unsubscribed via the handle's unsubscribe() method.
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Example/AblyChatExample/ContentView.swift:203-209
Timestamp: 2025-05-12T21:11:08.937Z
Learning: In the AblyChat Swift codebase, SubscriptionHandle doesn't need to be retained/stored to keep subscriptions active. The subscription continues to work even if the handle is not stored, as the underlying services maintain references to the callbacks until explicitly unsubscribed via the handle's unsubscribe() method.
Learnt from: maratal
PR: ably/ably-chat-swift#249
File: Tests/AblyChatTests/DefaultMessagesTests.swift:45-48
Timestamp: 2025-05-22T19:17:21.392Z
Learning: The `let doIt = {}` closures in DefaultMessagesTests.swift are temporary workarounds for compiler crashes (related to issue #233) and will be removed once Xcode 16.3 is released, so they should not be flagged for missing async/throws annotations.
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Sources/AblyChat/DefaultPresence.swift:269-277
Timestamp: 2025-05-16T22:07:33.286Z
Learning: In Swift, capturing an instance method in a closure's capture list (like `[someMethod]`) implicitly captures `self` strongly, as instance methods are functions that take `self` as their first parameter. This can lead to retain cycles, and should be avoided by using `[weak self]` instead.
Sources/AblyChat/DefaultPresence.swift (12)

Learnt from: maratal
PR: #286
File: Example/AblyChatExample/Mocks/MockClients.swift:0-0
Timestamp: 2025-05-16T21:04:26.244Z
Learning: In the ably-chat-swift project, mock implementations (like those in MockClients.swift) are intentionally kept simple, sometimes omitting parameter-based filtering behavior for testing simplicity.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/DefaultTyping.swift:131-138
Timestamp: 2025-05-12T21:04:36.263Z
Learning: In the AblyChat Swift codebase, SubscriptionHandle closures should capture self weakly with [weak self] to avoid potential retain cycles, particularly when calling channel.unsubscribe() within the closure.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/DefaultOccupancy.swift:10-13
Timestamp: 2025-05-12T21:01:14.109Z
Learning: The Occupancy protocol in the Ably Chat Swift SDK is annotated with @MainActor, making all conforming types like DefaultOccupancy automatically main actor-isolated without requiring explicit annotations on their methods.

Learnt from: maratal
PR: #249
File: Tests/AblyChatTests/DefaultMessagesTests.swift:45-48
Timestamp: 2025-05-22T19:17:21.392Z
Learning: The let doIt = {} closures in DefaultMessagesTests.swift are temporary workarounds for compiler crashes (related to issue #233) and will be removed once Xcode 16.3 is released, so they should not be flagged for missing async/throws annotations.

Learnt from: maratal
PR: #293
File: Example/AblyChatExample/ContentView.swift:94-99
Timestamp: 2025-06-14T21:47:20.509Z
Learning: In the Ably Chat Swift example app, using fatalError for missing clientID is intentional and appropriate since it represents a programmer error rather than a recoverable runtime condition. The clientID is considered an essential configuration requirement.

Learnt from: maratal
PR: #165
File: Sources/AblyChat/Reaction.swift:14-14
Timestamp: 2024-12-10T01:59:02.065Z
Learning: For the 'ably-chat-swift' repository, documentation-only PRs should focus exclusively on public methods and properties. Avoid suggesting changes to internal comments or private methods in such PRs.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/SubscriptionAsyncSequence.swift:36-41
Timestamp: 2025-06-29T16:02:43.988Z
Learning: In the AblyChat Swift codebase, the fatalError in SubscriptionAsyncSequence.swift's mock async sequence handling (around line 39) is intentional and should not be flagged. This fatalError catches programmer errors when a throwing AsyncSequence is incorrectly passed to the mock initializer, which is meant for testing/development purposes.

Learnt from: maratal
PR: #165
File: docs-coverage-report:5-8
Timestamp: 2024-12-10T01:59:12.404Z
Learning: In the AblyChat Swift project, documentation coverage should focus on public methods and properties. Private and internal entities do not require documentation.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/RoomLifecycleManager.swift:611-624
Timestamp: 2025-05-22T20:57:48.147Z
Learning: In AblyChat Swift, when using continuations with subscription callbacks, the continuation object is captured directly by the closure and doesn't depend on self. Even with [weak self] capture, the continuation will still be resumed properly.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/DefaultTyping.swift:11-14
Timestamp: 2025-05-12T21:03:31.914Z
Learning: The Typing protocol in the Ably Chat Swift SDK is annotated with @MainActor, making all conforming types like DefaultTyping automatically main actor-isolated without requiring explicit annotations on their methods.

Learnt from: maratal
PR: #262
File: Tests/AblyChatTests/DefaultRoomReactionsTests.swift:0-0
Timestamp: 2025-05-23T16:29:39.712Z
Learning: In the ably-chat-swift project, MockRealtimeChannel processes messages synchronously when subscribe is called, immediately delivering the configured messages to the callback.

Learnt from: maratal
PR: #262
File: Tests/AblyChatTests/DefaultRoomReactionsTests.swift:0-0
Timestamp: 2025-05-23T16:29:39.712Z
Learning: In the ably-chat-swift project, MockRealtimeChannel processes messages synchronously when subscribe is called, immediately delivering the configured messages to the callback.

🔇 Additional comments (2)
Sources/AblyChat/DefaultPresence.swift (2)

313-313: Timestamp fallback strategy looks reasonable.

Using Date() as the fallback for missing timestamps is a sensible approach. It provides a meaningful timestamp representing when the message was processed, which is better than using an arbitrary date or leaving it nil.

Also applies to: 327-327


307-320: processPresenceGet is intentionally permissive — no downstream error handlers are affected

  • Both processPresenceGet and processPresenceSubscribe never actually throw today (their throws signatures are unused), so:
    • The outer catch { throw error.toARTErrorInfo() } around processPresenceGet will never be entered
    • The subscription-level catch {} after processPresenceSubscribe likewise becomes dead code
  • All real error paths continue to surface only channel- or lifecycle-related errors
  • Falling back to "" for missing clientId and Date() for missing timestamp only applies when the server omits those fields—confirm these defaults meet your data-quality requirements

No changes required; behavior aligns with the PR’s goal.

Comment thread Sources/AblyChat/DefaultPresence.swift
@umair-ably
Copy link
Copy Markdown
Collaborator

Add self capture for subscription handlers instead of particular objects capture list.

why?

@umair-ably
Copy link
Copy Markdown
Collaborator

Add self capture for subscription handlers instead of particular objects capture list.

why?

@maratal waiting for an answer to this before approving

@maratal
Copy link
Copy Markdown
Collaborator Author

maratal commented Aug 15, 2025

Add self capture for subscription handlers instead of particular objects capture list.

why?

@maratal waiting for an answer to this before approving

I decided to make it the same everywhere to avoid any risk of retain cycle, since coderabbit complained about it elsewhere. Holding self weakly is a standard practice for escaping closures. Also if you hold function ref like this you can't navigate to it by clicking on it, only via search which makes it inconvenient.

@maratal maratal merged commit c260653 into main Aug 18, 2025
80 checks passed
@maratal maratal deleted the 337-message-validation-for-all-features branch August 18, 2025 11:27
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.

Ensure new message validation policy implemented across all features

2 participants