Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ECO-5204] Groundwork for wrapper SDK proxy #2021

Merged
merged 7 commits into from
Feb 4, 2025

Conversation

lawrence-forooghian
Copy link
Collaborator

@lawrence-forooghian lawrence-forooghian commented Jan 29, 2025

Groundwork for #2020. See commit messages for more details.

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced authentication and token management capabilities.
    • Expanded push notification handling for iOS.
    • Improved channel and presence management methods.
    • Added more flexible request and stats retrieval options.
  • Improvements

    • Refined protocol structures for Realtime and Rest interfaces.
    • Enhanced error handling and callback mechanisms.
    • Improved nullability annotations for better type safety.
  • Changes

    • Removed several protocol conformances.
    • Simplified class and method signatures.
    • Updated initialization methods for various components.
  • Testing

    • Updated test utilities for more robust HTTP request simulation.

Copy link

coderabbitai bot commented Jan 29, 2025

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 SwiftLint (0.57.0)
Test/Test Utilities/TestUtilities.swift

[
{
"character" : 21,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 292,
"reason" : "Prefer at least one space after slashes for comments",
"rule_id" : "comment_spacing",
"severity" : "Warning",
"type" : "Comment Spacing"
},
{
"character" : 60,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 903,
"reason" : "Prefer at least one space after slashes for comments",
"rule_id" : "comment_spacing",
"severity" : "Warning",
"type" : "Comment Spacing"
},
{
"character" : 11,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 1595,
"reason" : "Prefer at least one space after slashes for comments",
"rule_id" : "comment_spacing",
"severity" : "Warning",
"type" : "Comment Spacing"
},
{
"character" : 11,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 1596,
"reason" : "Prefer at least one space after slashes for comments",
"rule_id" : "comment_spacing",
"severity" : "Warning",
"type" : "Comment Spacing"
},
{
"character" : 11,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 1947,
"reason" : "Prefer at least one space after slashes for comments",
"rule_id" : "comment_spacing",
"severity" : "Warning",
"type" : "Comment Spacing"
},
{
"character" : 1,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 6,
"reason" : "Imports should be unique",
"rule_id" : "duplicate_imports",
"severity" : "Warning",
"type" : "Duplicate Imports"
},
{
"character" : 37,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 137,
"reason" : "Force casts should be avoided",
"rule_id" : "force_cast",
"severity" : "Error",
"type" : "Force Cast"
},
{
"character" : 46,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 185,
"reason" : "Force casts should be avoided",
"rule_id" : "force_cast",
"severity" : "Error",
"type" : "Force Cast"
},
{
"character" : 47,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 735,
"reason" : "Force casts should be avoided",
"rule_id" : "force_cast",
"severity" : "Error",
"type" : "Force Cast"
},
{
"character" : 53,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 1442,
"reason" : "Force casts should be avoided",
"rule_id" : "force_cast",
"severity" : "Error",
"type" : "Force Cast"
},
{
"character" : 27,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 1490,
"reason" : "Force casts should be avoided",
"rule_id" : "force_cast",
"severity" : "Error",
"type" : "Force Cast"
},
{
"character" : 54,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 1490,
"reason" : "Force casts should be avoided",
"rule_id" : "force_cast",
"severity" : "Error",
"type" : "Force Cast"
},
{
"character" : 45,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 1675,
"reason" : "Force casts should be avoided",
"rule_id" : "force_cast",
"severity" : "Error",
"type" : "Force Cast"
},
{
"character" : 23,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 64,
"reason" : "Force tries should be avoided",
"rule_id" : "force_try",
"severity" : "Error",
"type" : "Force Try"
},
{
"character" : 23,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 65,
"reason" : "Force tries should be avoided",
"rule_id" : "force_try",
"severity" : "Error",
"type" : "Force Try"
},
{
"character" : 32,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 322,
"reason" : "Force tries should be avoided",
"rule_id" : "force_try",
"severity" : "Error",
"type" : "Force Try"
},
{
"character" : 20,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 1321,
"reason" : "Force tries should be avoided",
"rule_id" : "force_try",
"severity" : "Error",
"type" : "Force Try"
},
{
"character" : 22,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 1442,
"reason" : "Force tries should be avoided",
"rule_id" : "force_try",
"severity" : "Error",
"type" : "Force Try"
},
{
"character" : 21,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 1556,
"reason" : "Force tries should be avoided",
"rule_id" : "force_try",
"severity" : "Error",
"type" : "Force Try"
},
{
"character" : 21,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 1566,
"reason" : "Force tries should be avoided",
"rule_id" : "force_try",
"severity" : "Error",
"type" : "Force Try"
},
{
"character" : 21,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 1899,
"reason" : "Force tries should be avoided",
"rule_id" : "force_try",
"severity" : "Error",
"type" : "Force Try"
},
{
"character" : 21,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 1557,
"reason" : "Swift constructors are preferred over legacy convenience functions",
"rule_id" : "legacy_constructor",
"severity" : "Warning",
"type" : "Legacy Constructor"
},
{
"character" : 21,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 1567,
"reason" : "Swift constructors are preferred over legacy convenience functions",
"rule_id" : "legacy_constructor",
"severity" : "Warning",
"type" : "Legacy Constructor"
},
{
"character" : 62,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 1900,
"reason" : "Swift constructors are preferred over legacy convenience functions",
"rule_id" : "legacy_constructor",
"severity" : "Warning",
"type" : "Legacy Constructor"
},
{
"character" : 47,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 432,
"reason" : "Initializing an optional variable with nil is redundant",
"rule_id" : "redundant_optional_initialization",
"severity" : "Warning",
"type" : "Redundant Optional Initialization"
},
{
"character" : 29,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 433,
"reason" : "Initializing an optional variable with nil is redundant",
"rule_id" : "redundant_optional_initialization",
"severity" : "Warning",
"type" : "Redundant Optional Initialization"
},
{
"character" : 37,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 541,
"reason" : "Initializing an optional variable with nil is redundant",
"rule_id" : "redundant_optional_initialization",
"severity" : "Warning",
"type" : "Redundant Optional Initialization"
},
{
"character" : 37,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 1153,
"reason" : "Returning Void in a function declaration is redundant",
"rule_id" : "redundant_void_return",
"severity" : "Warning",
"type" : "Redundant Void Return"
},
{
"character" : 94,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 484,
"reason" : "Shorthand syntactic sugar should be used, i.e. Int? instead of Optional",
"rule_id" : "syntactic_sugar",
"severity" : "Warning",
"type" : "Syntactic Sugar"
},
{
"character" : 107,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 494,
"reason" : "Shorthand syntactic sugar should be used, i.e. Int? instead of Optional",
"rule_id" : "syntactic_sugar",
"severity" : "Warning",
"type" : "Syntactic Sugar"
},
{
"character" : 40,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 615,
"reason" : "Shorthand syntactic sugar should be used, i.e. [String: Int] instead of Dictionary<String, Int>",
"rule_id" : "syntactic_sugar",
"severity" : "Warning",
"type" : "Syntactic Sugar"
},
{
"character" : 21,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 1447,
"reason" : "Shorthand syntactic sugar should be used, i.e. [String: Int] instead of Dictionary<String, Int>",
"rule_id" : "syntactic_sugar",
"severity" : "Warning",
"type" : "Syntactic Sugar"
},
{
"character" : 45,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 1447,
"reason" : "Shorthand syntactic sugar should be used, i.e. [String: Int] instead of Dictionary<String, Int>",
"rule_id" : "syntactic_sugar",
"severity" : "Warning",
"type" : "Syntactic Sugar"
},
{
"character" : 66,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 1447,
"reason" : "Shorthand syntactic sugar should be used, i.e. [String: Int] instead of Dictionary<String, Int>",
"rule_id" : "syntactic_sugar",
"severity" : "Warning",
"type" : "Syntactic Sugar"
},
{
"character" : 28,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 1456,
"reason" : "Shorthand syntactic sugar should be used, i.e. [String: Int] instead of Dictionary<String, Int>",
"rule_id" : "syntactic_sugar",
"severity" : "Warning",
"type" : "Syntactic Sugar"
},
{
"character" : 52,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 1456,
"reason" : "Shorthand syntactic sugar should be used, i.e. [String: Int] instead of Dictionary<String, Int>",
"rule_id" : "syntactic_sugar",
"severity" : "Warning",
"type" : "Syntactic Sugar"
},
{
"character" : 58,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 321,
"reason" : "Lines should not have trailing semicolons",
"rule_id" : "trailing_semicolon",
"severity" : "Warning",
"type" : "Trailing Semicolon"
},
{
"character" : 50,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 1996,
"reason" : "Lines should not have trailing semicolons",
"rule_id" : "trailing_semicolon",
"severity" : "Warning",
"type" : "Trailing Semicolon"
},
{
"character" : 60,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 1023,
"reason" : "Unused parameter in a closure should be replaced with _",
"rule_id" : "unused_closure_parameter",
"severity" : "Warning",
"type" : "Unused Closure Parameter"
},
{
"character" : 70,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 1023,
"reason" : "Unused parameter in a closure should be replaced with _",
"rule_id" : "unused_closure_parameter",
"severity" : "Warning",
"type" : "Unused Closure Parameter"
},
{
"character" : 76,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 1023,
"reason" : "Unused parameter in a closure should be replaced with _",
"rule_id" : "unused_closure_parameter",
"severity" : "Warning",
"type" : "Unused Closure Parameter"
},
{
"character" : 99,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 1900,
"reason" : "Unused parameter in a closure should be replaced with _",
"rule_id" : "unused_closure_parameter",
"severity" : "Warning",
"type" : "Unused Closure Parameter"
},
{
"character" : 106,
"file" : "/Test/Test Utilities/TestUtilities.swift",
"line" : 1900,
"reason" : "Unused parameter in a closure should be replaced with _",
"rule_id" : "unused_closure_parameter",
"severity" : "Warning",
"type" : "Unused Closure Parameter"
}
]

Walkthrough

This pull request introduces significant architectural changes to the Ably Cocoa SDK, focusing on protocol restructuring, method additions, and interface refinements across multiple private header files. The changes primarily involve removing protocol conformances, adding new methods for enhanced functionality, and improving nullability annotations. The modifications span various components like authentication, channels, presence, and HTTP execution, suggesting a comprehensive refactoring of the SDK's internal structure.

Changes

File Change Summary
Source/ARTChannel.m Added property synthesis for name
Source/PrivateHeaders/Ably/*+Private.h Removed protocol conformances, added new methods for authentication, connection, push notifications, channels, and presence management
Source/include/Ably/*.h Restructured protocols, split instance methods and initializers, removed redundant property declarations
Test/Test Utilities/TestUtilities.swift Updated MockHTTPExecutor to remove authentication-specific logic

Assessment against linked issues

Objective Addressed Explanation
Implement wrapper SDK proxy [ECO-5204] Changes appear foundational but do not directly implement the proxy

Possibly related issues

Possibly related PRs

Suggested reviewers

  • umair-ably

Poem

🐰 Protocols dance, methods twirl,
In Cocoa's SDK, a code unfurl
Refactoring magic, clean and bright
Ably's framework shines with delight!
Hop, hop, hooray for cleaner code! 🚀


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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. (Beta)
  • @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/2021/features January 29, 2025 12:32 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/2021/jazzydoc January 29, 2025 12:35 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: 4

🔭 Outside diff range comments (3)
Test/Test Utilities/TestUtilities.swift (3)

Line range hint 927-927: Avoid force-unwrapping request.url.

For test robustness, consider safely unwrapping request.url instead of using request.url!, which may crash if the URL is ever nil.


Line range hint 947-949: Check concurrency consistency for _requests usage.

The _requests array is appended to outside of http.queue.sync, but read inside http.queue.sync. This inconsistent approach can cause data races if multiple threads call execute(_:).


Line range hint 980-982: Synchronize _responses access.

Appending to _responses on the main queue while reading it on http.queue.sync can lead to data races. Ensure both read and write operations happen on the same queue or use another thread-safety mechanism.

🧹 Nitpick comments (26)
Source/PrivateHeaders/Ably/ARTClientInformation+Private.h (1)

3-4: LGTM! Good addition of nullability annotations.

The addition of nullability annotations improves type safety and interoperability. This is particularly important for:

  • Providing clear contracts about null/non-null values
  • Improving Swift interoperability
  • Preventing potential null pointer issues

Consider adding similar nullability annotations to other header files in the codebase for consistency. This will be especially beneficial for the wrapper SDK proxy implementation.

Also applies to: 13-14

Source/PrivateHeaders/Ably/ARTRestPresence+Private.h (1)

9-9: Architectural change: Protocol conformance removal

The removal of <ARTRestPresenceProtocol> conformance appears to be part of the wrapper SDK proxy groundwork. This change suggests a move towards a more flexible architecture where the internal implementation can diverge from the public interface when needed.

Consider documenting this architectural decision in the codebase to explain the reasoning behind separating the protocol conformance from internal implementations.

Source/include/Ably/ARTRestPresence.h (1)

63-64: Add documentation for the new history method

The new history: method lacks documentation unlike other methods in this file. Please add documentation explaining:

  • The default behavior when no query is provided
  • Any default limits or constraints
  • The relationship with the query-based variant

Example documentation:

/**
 * Retrieves historical presence messages for the channel using default parameters.
 * If the channel is configured to persist messages, then presence messages can be 
 * retrieved from history for up to 72 hours in the past. If not, presence messages
 * can only be retrieved from history for up to two minutes in the past.
 *
 * @param callback A callback for retrieving an `ARTPaginatedResult` object with 
 *                an array of `ARTPresenceMessage` objects.
 */
Test/Test Utilities/TestUtilities.swift (1)

Line range hint 924-924: Use a more explicit nil-check for request.url.

The pattern var _ = request.url may be confusing. A direct if let _ = request.url or guard let url = request.url else { ... } is clearer for indicating nil-check intentions.

Source/PrivateHeaders/Ably/ARTAuth+Private.h (4)

21-24: Provide callback concurrency guarantees.
When requestToken:withOptions:callback: finishes, ensure the callback executes on a documented queue or thread to avoid race conditions.


25-26: Consider consolidating overloads of requestToken.
Multiple overloads of requestToken might be simplified by using default parameters or by clarifying differences in their doc comments.


27-30: Align authorize with requestToken approach.
authorize:options:callback: is closely related to requestToken. Consider reusing internal logic or references to keep them in sync and reduce duplication.


31-32: Clarify usage in doc comments.
authorize: without params can be confusing if the user is unaware of default token parameters. Consider clarifying usage in a doc comment.

Source/PrivateHeaders/Ably/ARTRest+Private.h (2)

95-102: Clarify meaning of returned BOOL and error pointer.
- (BOOL)request:... error:(NSError **)errorPtr; can be confusing if the BOOL also indicates success/failure. Document how each is used to reduce ambiguity.


103-108: Consolidate stats fetching with request: if possible.
Since stats is a specialized request, consider unifying the logic within a single request path or clarifying differences to avoid duplication.

Source/PrivateHeaders/Ably/ARTPushAdmin+Private.h (1)

17-18: Add doc comments for publish: usage.
Publishing to a recipient with data is a key part of push functionality. Consider clarifying how errors and retries are handled in the callback.

Source/PrivateHeaders/Ably/ARTPushChannelSubscriptions+Private.h (2)

13-21: Consider making callbacks nullable for non-critical operations.

While enforcing error handling is good practice, some operations like listChannels might not always require error handling. Consider making callbacks nullable where appropriate.

-  - (void)listChannels:(ARTPaginatedTextCallback)callback;
+  - (void)listChannels:(nullable ARTPaginatedTextCallback)callback;

17-17: Document the expected format of params dictionary.

The list method accepts a dictionary of parameters, but their format and valid keys are not documented.

Source/PrivateHeaders/Ably/ARTPushDeviceRegistrations+Private.h (1)

15-15: Consider splitting the callback parameters.

The get callback combines two nullable parameters. Consider using separate success and error callbacks for clearer error handling.

-  - (void)get:(ARTDeviceId *)deviceId callback:(void (^)(ARTDeviceDetails *_Nullable, ARTErrorInfo *_Nullable))callback;
+  - (void)get:(ARTDeviceId *)deviceId
+     success:(nullable void (^)(ARTDeviceDetails *))successCallback
+     failure:(nullable void (^)(ARTErrorInfo *))failureCallback;
Source/PrivateHeaders/Ably/ARTPushChannel+Private.h (1)

13-27: Consider consolidating duplicate method pairs.

The pattern of having separate methods with and without callbacks leads to code duplication. Consider keeping only the callback versions and providing convenience methods in a category.

// In a category
+ @implementation ARTPushChannelInternal (Convenience)
+ - (void)subscribeDevice {
+     [self subscribeDevice:nil];
+ }
+ @end
Source/PrivateHeaders/Ably/ARTRealtimeChannels+Private.h (2)

14-14: Protocol conformance removal aligns with architectural changes.

The removal of ARTRealtimeChannelsProtocol conformance appears to be part of a broader architectural shift, possibly to facilitate the wrapper SDK proxy implementation mentioned in the PR description.


28-30: Consider documenting the behavior of release methods.

The new methods look good, but would benefit from documentation explaining:

  • What happens to active subscriptions when a channel is released
  • Whether release is idempotent
  • Error conditions that might trigger the callback
Source/PrivateHeaders/Ably/ARTPush+Private.h (1)

47-49: Document state transitions for activate/deactivate.

The activate/deactivate methods should document:

  • Expected state transitions
  • Whether they're idempotent
  • Any side effects on existing push registrations
Source/PrivateHeaders/Ably/ARTConnection+Private.h (1)

61-65: Document connection state transitions.

The new connection management methods should document:

  • Expected state transitions
  • Timeout behavior
  • Error conditions
  • Impact on existing channels
Source/PrivateHeaders/Ably/ARTRealtime+Private.h (1)

50-56: Consider using a builder pattern for request method.

The request method has many parameters which could make it error-prone to use. Consider introducing a builder pattern or request configuration object.

Example approach:

+@interface ARTRequestConfiguration : NSObject
+@property (nonatomic, copy) NSString *method;
+@property (nonatomic, copy) NSString *path;
+@property (nonatomic, copy, nullable) NSStringDictionary *params;
+@property (nonatomic, nullable) id body;
+@property (nonatomic, copy, nullable) NSStringDictionary *headers;
+@end

 @interface ARTRealtimeInternal : NSObject
-// Original method
+- (BOOL)request:(ARTRequestConfiguration *)config
+       callback:(ARTHTTPPaginatedCallback)callback
+          error:(NSError *_Nullable *_Nullable)errorPtr;
Source/include/Ably/ARTRest.h (1)

77-104: Well-structured protocol hierarchy for proxy support.

The separation of initializers into ARTRestProtocol while inheriting instance methods from ARTRestInstanceMethodsProtocol creates a clean foundation for implementing proxy objects. This structure allows for different initialization strategies while maintaining a consistent interface for instance methods.

This protocol restructuring will make it easier to:

  1. Implement proxy objects that need custom initialization
  2. Maintain API compatibility
  3. Add new initialization methods in the future without affecting instance methods
Source/include/Ably/ARTRealtime.h (2)

Line range hint 28-100: Address TODO comments in method documentation.

The protocol extraction looks good, but there are undocumented methods:

  • ping: (line 73)
  • stats: with single parameter (line 76)

Please add proper documentation for these methods to maintain consistency with the rest of the well-documented API.


Line range hint 20-22: Excellent architectural groundwork for the wrapper SDK proxy.

The protocol restructuring across both ARTRest and ARTRealtime provides a solid foundation for implementing the wrapper SDK proxy. Key architectural benefits:

  1. Clean separation of initialization from instance methods
  2. Consistent patterns across Rest and Realtime clients
  3. Preserved backward compatibility
  4. Improved modularity and maintainability

Consider documenting these architectural decisions in a design document or the PR description to help future maintainers understand the rationale behind this protocol restructuring.

Also applies to: 77-104, 28-30, 101-130

Source/PrivateHeaders/Ably/ARTRealtimePresence+Private.h (2)

28-73: Consider modernizing the asynchronous API design.

While the callback-based approach is well-structured, consider:

  1. Adding support for modern async/await patterns alongside callbacks
  2. Using completion handlers with Result type for better error handling

Example modernization:

// Modern async/await approach (if targeting iOS 13+)
- (void)get:(ARTPresenceMessagesCallback)callback NS_SWIFT_DISABLE_ASYNC;
- (NSArray<ARTPresenceMessage *> *)getWithQuery:(ARTRealtimePresenceQuery *)query error:(NSError **)error NS_SWIFT_NAME(get(query:)) API_AVAILABLE(ios(13.0));

28-73: Improve method organization with pragma marks.

The methods are logically grouped but lack visual separation. Consider adding pragma marks for better code organization.

+#pragma mark - Presence State
 - (void)get:(ARTPresenceMessagesCallback)callback;
 - (void)get:(ARTRealtimePresenceQuery *)query callback:(ARTPresenceMessagesCallback)callback;

+#pragma mark - Presence Actions
 - (void)enter:(id _Nullable)data;
 - (void)enter:(id _Nullable)data callback:(nullable ARTCallback)callback;
 // ... other presence actions

+#pragma mark - Client-specific Operations
 - (void)enterClient:(NSString *)clientId data:(id _Nullable)data;
 // ... other client operations

+#pragma mark - Subscriptions
 - (ARTEventListener *_Nullable)subscribe:(ARTPresenceMessageCallback)callback;
 // ... other subscription methods

+#pragma mark - History
 - (void)history:(ARTPaginatedPresenceCallback)callback;
Source/PrivateHeaders/Ably/ARTRestChannel+Private.h (1)

28-29: Verify error handling consistency.

The new history method follows a different error handling pattern (using error pointer) compared to the callback-based approach used in other methods. Consider standardizing the error handling approach.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between fee79bc and 7e7484e.

📒 Files selected for processing (25)
  • Source/ARTChannel.m (1 hunks)
  • Source/PrivateHeaders/Ably/ARTAuth+Private.h (1 hunks)
  • Source/PrivateHeaders/Ably/ARTClientInformation+Private.h (2 hunks)
  • Source/PrivateHeaders/Ably/ARTConnection+Private.h (2 hunks)
  • Source/PrivateHeaders/Ably/ARTHttp.h (0 hunks)
  • Source/PrivateHeaders/Ably/ARTPaginatedResult+Private.h (0 hunks)
  • Source/PrivateHeaders/Ably/ARTPush+Private.h (2 hunks)
  • Source/PrivateHeaders/Ably/ARTPushActivationState.h (0 hunks)
  • Source/PrivateHeaders/Ably/ARTPushAdmin+Private.h (1 hunks)
  • Source/PrivateHeaders/Ably/ARTPushChannel+Private.h (2 hunks)
  • Source/PrivateHeaders/Ably/ARTPushChannelSubscriptions+Private.h (2 hunks)
  • Source/PrivateHeaders/Ably/ARTPushDeviceRegistrations+Private.h (2 hunks)
  • Source/PrivateHeaders/Ably/ARTRealtime+Private.h (2 hunks)
  • Source/PrivateHeaders/Ably/ARTRealtimeChannel+Private.h (2 hunks)
  • Source/PrivateHeaders/Ably/ARTRealtimeChannels+Private.h (2 hunks)
  • Source/PrivateHeaders/Ably/ARTRealtimePresence+Private.h (2 hunks)
  • Source/PrivateHeaders/Ably/ARTRest+Private.h (2 hunks)
  • Source/PrivateHeaders/Ably/ARTRestChannel+Private.h (2 hunks)
  • Source/PrivateHeaders/Ably/ARTRestChannels+Private.h (2 hunks)
  • Source/PrivateHeaders/Ably/ARTRestPresence+Private.h (1 hunks)
  • Source/include/Ably/ARTChannel.h (0 hunks)
  • Source/include/Ably/ARTRealtime.h (2 hunks)
  • Source/include/Ably/ARTRest.h (2 hunks)
  • Source/include/Ably/ARTRestPresence.h (1 hunks)
  • Test/Test Utilities/TestUtilities.swift (1 hunks)
💤 Files with no reviewable changes (4)
  • Source/PrivateHeaders/Ably/ARTPaginatedResult+Private.h
  • Source/PrivateHeaders/Ably/ARTHttp.h
  • Source/include/Ably/ARTChannel.h
  • Source/PrivateHeaders/Ably/ARTPushActivationState.h
🧰 Additional context used
📓 Learnings (4)
Source/PrivateHeaders/Ably/ARTRestChannel+Private.h (1)
Learnt from: maratal
PR: ably/ably-cocoa#1995
File: Source/ARTRealtimeChannel.m:227-227
Timestamp: 2024-11-12T07:31:47.967Z
Learning: In `ARTRealtimeChannelInternal`, the `internalPresence` property is declared in the private header `ARTRealtimeChannel+Private.h`, so it does not need to be redeclared in `ARTRealtimeChannel.m`.
Source/PrivateHeaders/Ably/ARTRestPresence+Private.h (1)
Learnt from: maratal
PR: ably/ably-cocoa#1995
File: Source/ARTRealtimeChannel.m:227-227
Timestamp: 2024-11-12T07:31:47.967Z
Learning: In `ARTRealtimeChannelInternal`, the `internalPresence` property is declared in the private header `ARTRealtimeChannel+Private.h`, so it does not need to be redeclared in `ARTRealtimeChannel.m`.
Source/PrivateHeaders/Ably/ARTRealtimeChannel+Private.h (1)
Learnt from: maratal
PR: ably/ably-cocoa#1995
File: Source/ARTRealtimeChannel.m:227-227
Timestamp: 2024-11-12T07:31:47.967Z
Learning: In `ARTRealtimeChannelInternal`, the `internalPresence` property is declared in the private header `ARTRealtimeChannel+Private.h`, so it does not need to be redeclared in `ARTRealtimeChannel.m`.
Source/PrivateHeaders/Ably/ARTRealtimePresence+Private.h (1)
Learnt from: maratal
PR: ably/ably-cocoa#1995
File: Source/ARTRealtimeChannel.m:227-227
Timestamp: 2024-11-12T07:31:47.967Z
Learning: In `ARTRealtimeChannelInternal`, the `internalPresence` property is declared in the private header `ARTRealtimeChannel+Private.h`, so it does not need to be redeclared in `ARTRealtimeChannel.m`.
⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: check (macOS, test_macOS)
  • GitHub Check: check (tvOS, test_tvOS17_2)
  • GitHub Check: build
  • GitHub Check: check (iOS, test_iOS17_2)
  • GitHub Check: check
  • GitHub Check: check
🔇 Additional comments (27)
Source/PrivateHeaders/Ably/ARTRestPresence+Private.h (1)

13-19: LGTM: Comprehensive error handling methods added

The new methods provide a good balance of convenience and control:

  • Simple callback variant for basic usage
  • Error pointer variants for detailed error handling
  • Query-based variants for flexible data retrieval

The implementation follows a consistent pattern across all methods.

Source/PrivateHeaders/Ably/ARTAuth+Private.h (3)

16-16: Confirm intentional removal of protocol conformance.
The @interface ARTAuthInternal : NSObject line suggests that ARTAuthProtocol was removed. Verify if this impacts existing call sites that expect ARTAuthProtocol conformance or if the removal was intentional.


33-36: New method looks solid.
createTokenRequest: with parameters and a callback is straightforward. Make sure errors are returned consistently through the callback.


37-38: Good addition.
The no-parameter overload supports flexible scenarios. No major concerns here.

Source/PrivateHeaders/Ably/ARTRest+Private.h (3)

17-18: Validate removal of protocol conformance.
Confirm that discarding ARTRestProtocol and ARTHTTPAuthenticatedExecutor conformance will not break existing code.


19-22: Initializer overloads added.
Providing multiple ways to initialize ARTRestInternal can improve flexibility. No major issues spotted.


93-94: Ensure async safety in time: method.
When retrieving server time, ensure concurrency is handled (callback vs. main thread, etc.).

Source/PrivateHeaders/Ably/ARTPushAdmin+Private.h (1)

10-10: Confirm removal of ARTPushAdminProtocol.
Similar to the other classes, confirm that dropping protocol conformance is intentional and doesn't break references that relied on ARTPushAdminProtocol.

Source/PrivateHeaders/Ably/ARTRestChannels+Private.h (1)

10-10: Protocol conformance removal needs documentation.

The removal of ARTRestChannelsProtocol conformance appears to be part of a broader architectural change. Please document the rationale behind this change and its implications for wrapper SDKs.

Source/PrivateHeaders/Ably/ARTPush+Private.h (1)

31-46: Consider thread safety for notification handling.

The notification registration methods are well-structured, but should document thread safety requirements since they may be called from different iOS application delegate methods.

Run this script to check for any existing thread safety documentation or synchronization:

✅ Verification successful

Thread safety implementation verified, documentation recommended

The notification handling methods are thread-safe through the use of dispatch queues, but should be documented to clarify they can be safely called from any thread, including app delegate methods.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for thread safety documentation and synchronization patterns
rg -A 3 "dispatch_|synchronized|queue|thread|concurrent|serial" Source/

Length of output: 75990

Source/PrivateHeaders/Ably/ARTConnection+Private.h (1)

57-59: Good use of deprecation notice.

The deprecation of recoveryKey in favor of createRecoveryKey is well-handled with a clear message. Consider adding migration examples in the deprecation message.

Source/PrivateHeaders/Ably/ARTRealtime+Private.h (2)

32-35: Well-structured initializer pattern.

Good use of NS_UNAVAILABLE and multiple convenience initializers. This prevents misuse and provides clear initialization paths.


60-62: Good method overloading pattern for stats.

The stats methods are well-designed with a simpler version for common cases and an extended version with query options.

Source/include/Ably/ARTRest.h (1)

20-22: LGTM! Clean protocol extraction.

The extraction of instance methods into a separate protocol improves modularity and follows the Single Responsibility Principle.

Source/include/Ably/ARTRealtime.h (1)

101-130: LGTM! Consistent protocol hierarchy with ARTRest.

The protocol structure mirrors ARTRestProtocol, providing a consistent pattern across both Rest and Realtime clients. This symmetry will simplify maintenance and ensure consistent behavior in the wrapper SDK.

Source/PrivateHeaders/Ably/ARTRealtimePresence+Private.h (1)

6-6: Verify protocol removal implications.

The removal of ARTRealtimePresenceProtocol conformance might affect type safety and interface contracts. Please ensure that:

  1. All required methods from the protocol are still implemented
  2. Existing code doesn't rely on protocol conformance for type checking
✅ Verification successful

Protocol removal is architecturally sound

The removal of ARTRealtimePresenceProtocol conformance from ARTRealtimePresenceInternal is safe as:

  • All protocol methods are fully implemented in the internal class
  • The public ARTRealtimePresence class maintains protocol conformance
  • This is purely an implementation detail change that doesn't affect the public API contract
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify protocol requirements are still met after removal

# Find protocol requirements
echo "Protocol requirements:"
ast-grep --pattern 'protocol ARTRealtimePresenceProtocol {
  $$$
}'

# Find implementation of these requirements
echo "\nImplementation in ARTRealtimePresenceInternal:"
ast-grep --pattern 'interface ARTRealtimePresenceInternal {
  $$$
}'

# Find any potential protocol usage for type checking
echo "\nProtocol usage in type checks:"
rg "ARTRealtimePresenceProtocol"

Length of output: 1685


Script:

#!/bin/bash
# Get the full protocol definition and implementation details

echo "Protocol definition:"
cat Source/include/Ably/ARTRealtimePresence.h

echo -e "\nInternal implementation:"
cat Source/PrivateHeaders/Ably/ARTRealtimePresence+Private.h

Length of output: 16365

Source/PrivateHeaders/Ably/ARTRestChannel+Private.h (3)

30-33: LGTM: New methods align with proxy architecture.

The addition of status and setOptions methods provides necessary functionality for the wrapper SDK proxy. The method signatures are consistent with the codebase style.


26-27: Consider thread-safety for options property.

The options property is marked as readonly but lacks thread-safety annotations. Given the presence of a queue property, consider whether access to this property should be synchronized.


16-16: Protocol conformance removal requires verification.

The removal of <ARTRestChannelProtocol> conformance appears to be part of the architectural changes for the wrapper SDK proxy. However, we should verify that all required protocol methods are still implemented.

✅ Verification successful

Protocol conformance removal is safe

The removal of explicit <ARTRestChannelProtocol> conformance is verified to be safe as all required protocol methods are properly implemented through inheritance from ARTChannel and direct implementation in ARTRestChannelInternal.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Find protocol definition and its required methods
rg -A 10 "protocol ARTRestChannelProtocol"

# Find implementations of these methods in ARTRestChannelInternal
ast-grep --pattern 'interface ARTRestChannelInternal {
  $$$
}'

Length of output: 1268


Script:

#!/bin/bash
# Find parent protocol definition
rg -A 10 "protocol ARTChannelProtocol"

# Find options property
ast-grep --pattern '@property $$ options'

# Find history method implementation
ast-grep --pattern 'history:$$ callback:$$ error:$$'

Length of output: 1001


Script:

#!/bin/bash
# Get complete protocol definitions with more context
rg -B 5 -A 20 "protocol ARTChannelProtocol" Source/include/Ably/ARTChannel.h

# Find class implementation and its methods
ast-grep --pattern '@implementation ARTRestChannelInternal
  $$$
@end'

# Backup search with ripgrep
rg -A 20 "@implementation ARTRestChannelInternal"

Length of output: 2972


Script:

#!/bin/bash
# Find publish method implementations
rg -A 5 "^- \(void\)publish:" Source/ARTRestChannel.m

# Find history method implementation
rg -A 5 "^- \(void\)history:" Source/ARTRestChannel.m

# Check superclass implementation
rg -A 10 "@implementation ARTChannel"

Length of output: 8653

Source/ARTChannel.m (1)

20-21: Verify property access patterns.

The explicit synthesis of the name property with backing ivar _name is good practice. However, since this is a base class, verify that subclasses properly access this property.

✅ Verification successful

Property access patterns are correctly implemented

The explicit synthesis is working as intended. All subclasses properly use the property accessor self.name, while direct ivar access is appropriately limited to the base class implementation.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for direct ivar access in subclasses
rg "_name\W" "Source/**/*.m" --type objc

# Check for proper property access patterns
ast-grep --pattern 'self.name'

Length of output: 218


Script:

#!/bin/bash
# Find correct paths first
fd -e m -e h

# Then search for relevant patterns
rg "_name\W" --type objc
rg "self\.name" --type objc
rg "@interface.*:.*ARTChannel" --type objc

Length of output: 20373

Source/PrivateHeaders/Ably/ARTRealtimeChannel+Private.h (7)

74-81: Verify memory management of event listeners.

The subscription methods return nullable ARTEventListener objects. Please ensure:

  1. Memory ownership is clearly documented
  2. Listeners are properly retained/released
  3. Null return cases are documented

Consider adding documentation comments explaining:

  • Ownership semantics of returned listeners
  • Conditions when null might be returned
  • Lifecycle management responsibilities

88-90: Verify error handling in history and options methods.

Please ensure:

  1. The history method's BOOL return value is documented (success/failure?)
  2. Error parameter handling follows Cocoa conventions
  3. The options callback is called on all execution paths

Consider:

  • Adding documentation about the meaning of the BOOL return value
  • Using NSError best practices (non-null error for failure cases)

62-64: Verify thread-safe property access implementation.

The new properties and options properties appear to be thread-safe alternatives to their _nosync counterparts. Please ensure:

  1. These properties are properly synchronized using the queue property
  2. They maintain consistency with their _nosync variants
✅ Verification successful

Thread-safe property access implementation verified ✓

The properties and options properties are correctly implemented with proper thread synchronization using dispatch_sync and maintain consistency with their _nosync variants.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for property implementations
ast-grep --pattern 'implementation ARTRealtimeChannelInternal {
  $$$
  - (ARTChannelProperties *)properties {
    $$$
  }
  $$$
}'

ast-grep --pattern 'implementation ARTRealtimeChannelInternal {
  $$$
  - (ARTRealtimeChannelOptions *)options {
    $$$
  }
  $$$
}'

Length of output: 269


Script:

#!/bin/bash
# First, find relevant implementation files
rg -l "ARTRealtimeChannel" --type objc

# Then search for property implementations with context
rg "properties\s*[{]|options\s*[{]" --type objc -A 5

Length of output: 11561


92-95: Verify event emitter implementation.

The ART_EMBED_INTERFACE_EVENT_EMITTER macro adds standard event emitter functionality. Please ensure:

  1. Channel state changes are properly propagated
  2. Event handlers are called in the correct order
  3. The event emitter is properly cleaned up
✅ Verification successful

Event emitter implementation is properly structured and safe.

The event emitter macro provides a complete set of event handling methods with proper cleanup through ARTEventEmitter's dealloc. The implementation ensures:

  • Thread-safe event handling
  • Proper cleanup of event handlers
  • Safe object deallocation
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for event emitter usage
rg "ART_EMBED_INTERFACE_EVENT_EMITTER.*ARTChannelEvent" -A 5

Length of output: 916


Script:

#!/bin/bash
# Search for macro definition and related implementations
echo "=== Searching for macro definition ==="
rg "^#define ART_EMBED_INTERFACE_EVENT_EMITTER" -A 10

echo -e "\n=== Searching for event emitter method implementations ==="
ast-grep --pattern 'on($$$) { $$$ }'

echo -e "\n=== Searching for cleanup/dealloc methods ==="
rg "dealloc|cleanup.*ARTChannel" -A 5

Length of output: 36002


82-87: Verify proper cleanup in unsubscribe methods.

The unsubscribe methods should ensure proper cleanup of event listeners. Please ensure:

  1. All listeners are properly removed from the event emitter
  2. Memory is properly released
  3. The methods properly delegate to _unsubscribe where appropriate
✅ Verification successful

✓ Unsubscribe methods implementation verified as correct

The implementation shows proper cleanup with:

  • Thread-safe event listener removal
  • Appropriate delegation to internal methods
  • Proper memory management via EventEmitter
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for unsubscribe implementations
ast-grep --pattern 'implementation ARTRealtimeChannelInternal {
  $$$
  - (void)unsubscribe {
    $$$
  }
  $$$
}'

Length of output: 116


Script:

#!/bin/bash
# Find relevant files first
echo "=== Searching for relevant files ==="
rg -l "ARTRealtimeChannel" --type objc

echo -e "\n=== Searching for unsubscribe implementations ==="
rg "^- \(void\)unsubscribe" --type objc -A 5

echo -e "\n=== Searching for _unsubscribe implementations ==="
rg "^- \(void\)_unsubscribe" --type objc -A 5

Length of output: 17629


20-20: Verify protocol conformance removal impact.

The removal of ARTRealtimeChannelProtocol conformance is a significant architectural change. Please ensure that:

  1. All required protocol methods are still implemented
  2. Type safety is maintained where protocol conformance was expected
✅ Verification successful

Protocol conformance removal is intentionally correct

The removal of explicit protocol conformance from ARTRealtimeChannelInternal is architecturally sound because:

  • It inherits from ARTChannel which implements ARTChannelProtocol
  • Protocol conformance is maintained through the public ARTRealtimeChannel interface
  • Type safety and interface contracts are preserved through inheritance
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Find protocol definition and its usage
echo "Searching for protocol definition..."
rg "ARTRealtimeChannelProtocol" -A 10

echo "Checking protocol usage in type constraints..."
rg "ARTRealtimeChannelProtocol>" -A 2

Length of output: 11552


Script:

#!/bin/bash
# Check ARTChannel and ARTRealtimeChannelInternal implementations
echo "Checking ARTChannel implementation..."
ast-grep --pattern 'interface ARTChannel {
  $$$
}'

echo "Checking ARTRealtimeChannelInternal methods..."
ast-grep --pattern 'interface ARTRealtimeChannelInternal {
  $$$
}'

echo "Checking protocol required methods..."
rg "^- \(.*\);" Source/include/Ably/ARTRealtimeChannel.h

Length of output: 455


Script:

#!/bin/bash
echo "Checking protocol and class declarations..."
rg "@protocol ARTRealtimeChannelProtocol|@interface ARTRealtimeChannel|@interface ARTChannel|@interface ARTRealtimeChannelInternal" -B 1 -A 5 --type objc

echo "Checking method declarations in protocol..."
rg "^- \(.*\);" -A 1 --type objc Source/include/Ably/ARTRealtimeChannel.h

echo "Checking method declarations in internal implementation..."
rg "^- \(.*\);" -A 1 --type objc Source/PrivateHeaders/Ably/ARTRealtimeChannel+Private.h

echo "Checking inheritance hierarchy..."
rg "^@interface.*:.*" --type objc Source/PrivateHeaders/Ably/ARTRealtimeChannel+Private.h

Length of output: 15255


66-73: Verify proper delegation to private methods.

The new public attach/detach methods should properly delegate to their private _attach/_detach counterparts. Please ensure:

  1. Proper error handling in the public methods
  2. Consistent callback handling between public and private implementations
✅ Verification successful

Proper delegation to private methods verified

The implementation in ARTRealtimeChannel.m shows correct delegation patterns:

  • Public methods properly forward calls to internal implementation
  • Callback handling is implemented correctly
  • Error handling is in place through callback wrapping
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for method implementations to verify delegation
ast-grep --pattern 'implementation ARTRealtimeChannelInternal {
  $$$
  - (void)attach {
    $$$
  }
  $$$
  - (void)attach:(ARTCallback)callback {
    $$$
  }
  $$$
}'

ast-grep --pattern 'implementation ARTRealtimeChannelInternal {
  $$$
  - (void)detach {
    $$$
  }
  $$$
  - (void)detach:(ARTCallback)callback {
    $$$
  }
  $$$
}'

Length of output: 341


Script:

#!/bin/bash
# Find implementation files
rg -l "ARTRealtimeChannel" --type cpp

# Search for method implementations with less restrictive pattern
ast-grep --pattern '- (void)attach {
  $$$
}'

ast-grep --pattern '- (void)attach:(ARTCallback)callback {
  $$$
}'

ast-grep --pattern '- (void)detach {
  $$$
}'

ast-grep --pattern '- (void)detach:(ARTCallback)callback {
  $$$
}'

Length of output: 1847


Script:

#!/bin/bash
# Search for implementation files and their content
rg -p "^- \(void\)(attach|detach)(\:|[^:])" --type cpp -g "*.m" -g "*.mm" -A 5

Length of output: 209


Script:

#!/bin/bash
# Find implementation files
fd -e m -e mm | while read -r file; do
  echo "=== $file ==="
  echo "Looking for attach/detach implementations..."
  rg "^- \(void\)attach" "$file" -A 3 || true
  rg "^- \(void\)detach" "$file" -A 3 || true
  echo
done

Length of output: 44150

Preparation for introducing a new class that conforms to these protocols
but which won't have these initializers. Let's use these protocols just
to list the functionality provided by an already-initialized client.

(To do this in a backwards-compatible way I've had to not actually
remove anything from the existing protocols, but rather introduce new
ones, which is a bit messy. Have created #2019 for us to sort this out
in our next major release.)
This is to allow us to add additional parameters (which are internal to
the SDK) to some of these methods.
It's already declared in ARTChannelProtocol.
For consistency with ARTRealtimePresenceProtocol, and to express as much
of the SDK's functionality through protocols as possible.
It's unused (i.e. nobody takes one as a dependency).
Nobody makes use of this conformance.
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: 0

♻️ Duplicate comments (2)
Source/PrivateHeaders/Ably/ARTPushChannel+Private.h (1)

29-31: 🛠️ Refactor suggestion

Inconsistent error handling pattern.

The listSubscriptions method uses NSError pattern while other methods use callbacks. Consider using the callback pattern for consistency.

-  - (BOOL)listSubscriptions:(NSStringDictionary *)params
-                 callback:(ARTPaginatedPushChannelCallback)callback
-                    error:(NSError *_Nullable *_Nullable)errorPtr;
+  - (void)listSubscriptions:(NSStringDictionary *)params
+                 callback:(ARTPaginatedPushChannelCallback)callback;
Source/PrivateHeaders/Ably/ARTRealtimePresence+Private.h (1)

26-26: ⚠️ Potential issue

Ensure consistent property attributes.

The syncComplete property is declared twice with different attributes:

  • Here: @property (readonly) BOOL syncComplete;
  • In PresenceMap category: @property (readonly, nonatomic) BOOL syncComplete;

This inconsistency in thread-safety attributes could lead to undefined behavior.

Apply this diff to maintain consistency:

-@property (readonly) BOOL syncComplete;
+@property (readonly, nonatomic) BOOL syncComplete;
🧹 Nitpick comments (7)
Source/PrivateHeaders/Ably/ARTPushDeviceRegistrations+Private.h (1)

13-21: Consider adding validation requirements in method documentation.

While the interface design is clean and consistent with callback patterns, consider documenting:

  • Required parameter formats/constraints
  • Possible error conditions
  • Threading/queue expectations

Example documentation format:

/**
 * Saves the device details to the push notification service.
 * @param deviceDetails The device details to save. Must not be nil.
 * @param callback Called on completion. Error is nil on success.
 * @discussion This method must be called from the main thread.
 */
Source/PrivateHeaders/Ably/ARTRestChannel+Private.h (1)

28-29: Add documentation for the history method.

While the method signature is well-designed with proper nullability annotations and error handling, it would benefit from documentation explaining:

  • The meaning of the BOOL return value
  • Expected query parameters
  • Possible error conditions
Source/PrivateHeaders/Ably/ARTRealtimePresence+Private.h (1)

28-72: Add documentation for public-facing methods.

While the method signatures are well-designed with consistent nullability annotations and clear parameter naming, they lack documentation. Consider adding documentation comments to describe:

  • Method purpose
  • Parameter descriptions
  • Return value descriptions
  • Any side effects or important notes

Example documentation format:

/**
 * Enters the presence set for the current client.
 *
 * @param data Optional data payload for the presence message
 * @param callback Optional callback to be notified of success/failure
 */
- (void)enter:(id _Nullable)data callback:(nullable ARTCallback)callback;
Source/include/Ably/ARTRest.h (1)

20-22: Well-structured protocol separation!

The separation of instance methods into ARTRestInstanceMethodsProtocol and having ARTRestProtocol inherit from it is a good architectural decision. This makes it easier to implement proxies/wrappers and follows the Interface Segregation Principle.

Also applies to: 77-104

Source/PrivateHeaders/Ably/ARTAuth+Private.h (1)

21-37: Comprehensive token lifecycle management.

The new methods provide a complete token management system with both detailed and simplified interfaces. Consider adding retry logic for token requests in case of network failures.

 - (void)requestToken:(nullable ARTTokenParams *)tokenParams
         withOptions:(nullable ARTAuthOptions *)authOptions
            callback:(ARTTokenDetailsCallback)callback {
+    [self requestTokenWithRetry:3 tokenParams:tokenParams withOptions:authOptions callback:callback];
 }

+- (void)requestTokenWithRetry:(NSInteger)retryCount
+                  tokenParams:(nullable ARTTokenParams *)tokenParams
+                 withOptions:(nullable ARTAuthOptions *)authOptions
+                   callback:(ARTTokenDetailsCallback)callback {
+    // Implementation with exponential backoff retry logic
+}
Source/PrivateHeaders/Ably/ARTRealtime+Private.h (2)

48-67: Comprehensive realtime functionality implementation.

The addition of time, request, ping, stats, and connection management methods provides a complete realtime client implementation. Consider adding connection state validation before operations.

 - (void)ping:(ARTCallback)cb {
+    if (self.connection.state != ARTRealtimeConnected) {
+        cb([ARTErrorInfo createWithCode:0 message:@"Connection not in CONNECTED state"]);
+        return;
+    }
     // Implementation
 }

30-35: Consider adding validation in initializers.

The initializers should validate input parameters and potentially throw exceptions for invalid inputs.

 - (instancetype)initWithKey:(NSString *)key {
+    if (!key || [key isEqualToString:@""]) {
+        @throw [NSException exceptionWithName:NSInvalidArgumentException
+                                     reason:@"Key cannot be null or empty"
+                                   userInfo:nil];
+    }
     // Implementation
 }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 7e7484e and 870c8a6.

📒 Files selected for processing (25)
  • Source/ARTChannel.m (1 hunks)
  • Source/PrivateHeaders/Ably/ARTAuth+Private.h (1 hunks)
  • Source/PrivateHeaders/Ably/ARTClientInformation+Private.h (2 hunks)
  • Source/PrivateHeaders/Ably/ARTConnection+Private.h (2 hunks)
  • Source/PrivateHeaders/Ably/ARTHttp.h (0 hunks)
  • Source/PrivateHeaders/Ably/ARTPaginatedResult+Private.h (0 hunks)
  • Source/PrivateHeaders/Ably/ARTPush+Private.h (2 hunks)
  • Source/PrivateHeaders/Ably/ARTPushActivationState.h (0 hunks)
  • Source/PrivateHeaders/Ably/ARTPushAdmin+Private.h (1 hunks)
  • Source/PrivateHeaders/Ably/ARTPushChannel+Private.h (2 hunks)
  • Source/PrivateHeaders/Ably/ARTPushChannelSubscriptions+Private.h (2 hunks)
  • Source/PrivateHeaders/Ably/ARTPushDeviceRegistrations+Private.h (2 hunks)
  • Source/PrivateHeaders/Ably/ARTRealtime+Private.h (2 hunks)
  • Source/PrivateHeaders/Ably/ARTRealtimeChannel+Private.h (2 hunks)
  • Source/PrivateHeaders/Ably/ARTRealtimeChannels+Private.h (2 hunks)
  • Source/PrivateHeaders/Ably/ARTRealtimePresence+Private.h (2 hunks)
  • Source/PrivateHeaders/Ably/ARTRest+Private.h (2 hunks)
  • Source/PrivateHeaders/Ably/ARTRestChannel+Private.h (2 hunks)
  • Source/PrivateHeaders/Ably/ARTRestChannels+Private.h (2 hunks)
  • Source/PrivateHeaders/Ably/ARTRestPresence+Private.h (1 hunks)
  • Source/include/Ably/ARTChannel.h (0 hunks)
  • Source/include/Ably/ARTRealtime.h (2 hunks)
  • Source/include/Ably/ARTRest.h (2 hunks)
  • Source/include/Ably/ARTRestPresence.h (1 hunks)
  • Test/Test Utilities/TestUtilities.swift (1 hunks)
💤 Files with no reviewable changes (4)
  • Source/PrivateHeaders/Ably/ARTPaginatedResult+Private.h
  • Source/PrivateHeaders/Ably/ARTHttp.h
  • Source/include/Ably/ARTChannel.h
  • Source/PrivateHeaders/Ably/ARTPushActivationState.h
🚧 Files skipped from review as they are similar to previous changes (12)
  • Source/PrivateHeaders/Ably/ARTClientInformation+Private.h
  • Source/ARTChannel.m
  • Source/PrivateHeaders/Ably/ARTRealtimeChannels+Private.h
  • Source/PrivateHeaders/Ably/ARTPushAdmin+Private.h
  • Source/include/Ably/ARTRestPresence.h
  • Source/PrivateHeaders/Ably/ARTRestChannels+Private.h
  • Source/include/Ably/ARTRealtime.h
  • Source/PrivateHeaders/Ably/ARTPushChannelSubscriptions+Private.h
  • Source/PrivateHeaders/Ably/ARTRestPresence+Private.h
  • Test/Test Utilities/TestUtilities.swift
  • Source/PrivateHeaders/Ably/ARTRealtimeChannel+Private.h
  • Source/PrivateHeaders/Ably/ARTPush+Private.h
🧰 Additional context used
📓 Learnings (2)
Source/PrivateHeaders/Ably/ARTRestChannel+Private.h (1)
Learnt from: maratal
PR: ably/ably-cocoa#1995
File: Source/ARTRealtimeChannel.m:227-227
Timestamp: 2024-11-12T07:31:47.967Z
Learning: In `ARTRealtimeChannelInternal`, the `internalPresence` property is declared in the private header `ARTRealtimeChannel+Private.h`, so it does not need to be redeclared in `ARTRealtimeChannel.m`.
Source/PrivateHeaders/Ably/ARTRealtimePresence+Private.h (1)
Learnt from: maratal
PR: ably/ably-cocoa#1995
File: Source/ARTRealtimeChannel.m:227-227
Timestamp: 2024-11-12T07:31:47.967Z
Learning: In `ARTRealtimeChannelInternal`, the `internalPresence` property is declared in the private header `ARTRealtimeChannel+Private.h`, so it does not need to be redeclared in `ARTRealtimeChannel.m`.
⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: check (macOS, test_macOS)
  • GitHub Check: check (tvOS, test_tvOS17_2)
  • GitHub Check: check (iOS, test_iOS17_2)
  • GitHub Check: build
  • GitHub Check: check
  • GitHub Check: check
🔇 Additional comments (12)
Source/PrivateHeaders/Ably/ARTPushDeviceRegistrations+Private.h (1)

7-8: LGTM! Good addition of nullability annotations.

Adding explicit nullability annotations improves type safety and helps prevent null pointer issues.

Also applies to: 33-33

Source/PrivateHeaders/Ably/ARTPushChannel+Private.h (2)

7-8: LGTM! Good addition of nullability annotations.

Adding explicit nullability annotations improves type safety and helps prevent null pointer issues.

Also applies to: 43-43


13-28: LGTM! Well-designed method pairs pattern.

Good design providing both simple and callback variants for each operation. The nullable callback parameter allows for optional completion handling.

Source/PrivateHeaders/Ably/ARTRestChannel+Private.h (4)

26-27: LGTM! Well-designed property declaration.

The property is correctly marked as nullable and readonly, with proper encapsulation through the companion setOptions method.


32-33: LGTM! Well-designed setter method.

The method provides controlled mutation of options with proper nullability annotation, complementing the readonly options property.


30-31: Verify ARTChannelDetailsCallback definition.

The method follows good asynchronous patterns, but let's ensure the callback type is properly defined.

✅ Verification successful

Callback type is properly defined and used correctly

The ARTChannelDetailsCallback is well-defined in ARTTypes.h with proper nullability annotations and error handling support. The implementation shows correct usage with async dispatch.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify callback type definition
# Search for ARTChannelDetailsCallback definition and usage

echo "Searching for callback type definition..."
rg "ARTChannelDetailsCallback" -B 2 -A 2

echo "Checking for typedef declaration..."
ast-grep --pattern 'typedef void (^ARTChannelDetailsCallback)'

Length of output: 2064


16-16: Verify protocol removal impact on wrapper SDK.

The removal of ARTRestChannelProtocol conformance appears to be part of the broader architectural changes. This change aligns with similar protocol removals across the codebase.

✅ Verification successful

Protocol removal from internal class is architecturally sound

The removal of ARTRestChannelProtocol conformance from ARTRestChannelInternal is valid as the protocol remains intact in the public API where ARTRestChannel continues to conform to it. This change appropriately decouples the internal implementation while maintaining the public interface contract.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the broader impact of protocol removal
# Check for any remaining protocol conformances and usages

echo "Checking for remaining protocol conformances..."
rg "ARTRestChannelProtocol" -A 3

echo "Checking for any protocol forward declarations..."
ast-grep --pattern 'protocol ARTRestChannelProtocol'

Length of output: 840

Source/PrivateHeaders/Ably/ARTRealtimePresence+Private.h (1)

6-6: Verify architectural change: Protocol conformance removal.

The removal of ARTRealtimePresenceProtocol conformance from ARTRealtimePresenceInternal represents a significant architectural change. This could impact type safety and interface contracts.

✅ Verification successful

Protocol conformance removal is architecturally sound

The removal of ARTRealtimePresenceProtocol conformance from ARTRealtimePresenceInternal is a valid architectural decision. The public ARTRealtimePresence class maintains protocol conformance while delegating to the internal implementation. All protocol methods are properly implemented, maintaining full functionality while improving the separation of concerns.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if ARTRealtimePresenceProtocol methods are still implemented
ast-grep --pattern 'protocol ARTRealtimePresenceProtocol {
  $$$
}'

# Check for any references to ARTRealtimePresenceProtocol
rg "ARTRealtimePresenceProtocol" -A 5

Length of output: 2385


Script:

#!/bin/bash
# First, get the protocol methods
ast-grep --pattern 'protocol ARTRealtimePresenceProtocol {
  $$$
}'

# Then, check if these methods are implemented in ARTRealtimePresenceInternal
ast-grep --pattern 'interface ARTRealtimePresenceInternal : NSObject {
  $$$
}'

# Also check the implementation file
rg "ARTRealtimePresenceInternal" -A 5 "Source/**/ARTRealtimePresence.m"

Length of output: 295


Script:

#!/bin/bash
# Find the implementation file
fd "ARTRealtimePresence\.m$"

# Get protocol definition with proper Objective-C syntax
ast-grep --pattern '@protocol ARTRealtimePresenceProtocol
$$$'

# Check internal class implementation with proper Objective-C syntax
ast-grep --pattern '@implementation ARTRealtimePresenceInternal
$$$'

# Look for method implementations
rg "@implementation ARTRealtimePresenceInternal" -A 20

Length of output: 1809


Script:

#!/bin/bash
# Get the protocol definition
echo "=== Protocol Definition ==="
rg -A 50 "@protocol ARTRealtimePresenceProtocol" "Source/include/Ably/ARTRealtimePresence.h"

# Get the complete implementation
echo -e "\n=== Implementation Methods ==="
rg -A 5 "^- \(" "Source/ARTRealtimePresence.m" | grep "ARTRealtimePresenceInternal"

Length of output: 2814


Script:

#!/bin/bash
echo "=== Internal Class Method Implementations ==="
# Search for protocol method implementations
rg "^- \(void\)(?:enter|update|get)|@property.*syncComplete" "Source/ARTRealtimePresence.m" -A 3

echo -e "\n=== Class Structure ==="
# Get the complete class structure
rg "^@implementation ARTRealtimePresence|^@implementation ARTRealtimePresenceInternal" "Source/ARTRealtimePresence.m" -B 2 -A 10

Length of output: 4680

Source/PrivateHeaders/Ably/ARTConnection+Private.h (2)

57-57: Good deprecation practice for recoveryKey property.

The deprecation notice provides a clear migration path to the createRecoveryKey method.


59-66: Verify connection management method implementations.

The new connection management methods (connect, close, ping) need to be implemented consistently across different transport types.

✅ Verification successful

Connection management methods are implemented consistently

The connection management methods (connect, close, ping) are properly implemented through the entire stack:

  • Consistent delegation pattern from public interfaces through internal implementations
  • Proper resource cleanup in the WebSocket transport layer
  • Thread-safe implementations with appropriate callback handling
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for implementations of these methods across different transport types
ast-grep --pattern 'class $_ {
  $$$
  connect() {
    $$$
  }
  $$$
}'

ast-grep --pattern 'class $_ {
  $$$
  close() {
    $$$
  }
  $$$
}'

ast-grep --pattern 'class $_ {
  $$$
  ping($_) {
    $$$
  }
  $$$
}'

Length of output: 218


Script:

#!/bin/bash
# First, find transport-related files
echo "=== Transport-related files ==="
fd -e h -e m ".*Transport.*"

echo -e "\n=== Connect method implementations ==="
rg "^[-+]\s*\(void\)\s*connect\b" -A 5

echo -e "\n=== Close method implementations ==="
rg "^[-+]\s*\(void\)\s*close\b" -A 5

echo -e "\n=== Ping method implementations ==="
rg "^[-+]\s*\(void\)\s*ping:" -A 5

Length of output: 10035

Source/PrivateHeaders/Ably/ARTRest+Private.h (2)

19-22: Good initialization pattern.

The initialization methods mirror the public interface, maintaining consistency.


95-102: Verify error handling in request method.

The request method should handle all potential error cases consistently.

✅ Verification successful

Error handling implementation is comprehensive and robust

The request method implements thorough error handling covering:

  • Input validation (method, body, path)
  • Network errors and retries
  • HTTP status codes
  • Token-related errors
  • Content type validation
  • Proper error propagation through callbacks

All error cases are handled consistently with appropriate error codes and messages.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for error handling patterns in request implementations
rg -A 5 'error\(' Source/

Length of output: 27


Script:

#!/bin/bash
# Search for the method implementation
ast-grep --pattern 'request:$_ path:$_ params:$_ body:$_ headers:$_ callback:$_ error:$_'

# Search for NSError patterns and error handling
rg -l "NSError|errorPtr|error:" Source/

# Search specifically in implementation files
fd "\.m$" Source/ --exec grep -l "NSError"

Length of output: 4072


Script:

#!/bin/bash
# Look for the request method implementation and surrounding context
rg -A 20 'request:.*path:.*params:.*body:.*headers:.*callback:.*error:' Source/ARTRest.m

# Also check for error handling patterns in the same file
rg -B 2 -A 5 'if.*error' Source/ARTRest.m

Length of output: 8539

Copy link
Collaborator

@maratal maratal left a comment

Choose a reason for hiding this comment

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

LGTM

Source/include/Ably/ARTRealtime.h Show resolved Hide resolved
@lawrence-forooghian lawrence-forooghian merged commit f78ec80 into main Feb 4, 2025
8 checks passed
@lawrence-forooghian lawrence-forooghian deleted the groundwork-for-wrapper-sdk-proxy branch February 4, 2025 12:33
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.

2 participants