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

Basic NSURLSessionWebSocketTask functionality #1541

Open
wants to merge 16 commits into
base: main
Choose a base branch
from

Conversation

maratal
Copy link
Collaborator

@maratal maratal commented Nov 28, 2022

Closes #1540

@maratal maratal marked this pull request as draft November 28, 2022 12:43
@github-actions github-actions bot temporarily deployed to staging/pull/1541/jazzydoc November 28, 2022 12:49 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1541/jazzydoc December 4, 2022 22:55 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1541/jazzydoc December 5, 2022 17:34 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1541/jazzydoc December 10, 2022 22:43 Inactive
@maratal maratal marked this pull request as ready for review December 10, 2022 23:13
@maratal maratal force-pushed the feature/1540-NSURLSessionWebSocketTask branch from a3e6134 to 0a13cd6 Compare December 11, 2022 21:28
@github-actions github-actions bot temporarily deployed to staging/pull/1541/jazzydoc December 11, 2022 21:38 Inactive
@maratal
Copy link
Collaborator Author

maratal commented Dec 12, 2022

Because this will replace core/critical functionality, it is probably a good idea to introduce it gradually via something like clientOptions.useNativeWebSocket and explicitly ask some clients to give it a try. WDYT @lawrence-forooghian @QuintinWillison

@lawrence-forooghian
Copy link
Collaborator

I'll probably need to take some time to get some understanding of WebSockets in general (perhaps reading the RFC) before I can give this a proper review. I'll see if I can find some time this week for that, but can't guarantee that I'll be able to.

@lawrence-forooghian
Copy link
Collaborator

Because this will replace core/critical functionality, it is probably a good idea to introduce it gradually via something like clientOptions.useNativeWebSocket and explicitly ask some clients to give it a try. WDYT @lawrence-forooghian @QuintinWillison

It's definitely worth thinking about ways to get confidence in this change, yeah.

@QuintinWillison
Copy link
Contributor

I don't think that adding a client option to change core runtime behaviour is going to do anything to explain this to time poor customers, nor drive them to use it. My preference would be to use the tools already available to us to make this change happen (versioning). So, perhaps, we should be discussing this as part of scope for version 2 of this SDK? (i.e. a major version bump) -- this should count as an enhancement from a customer's perspective, as well as from ours as maintainers. FYI, @mikelee638

Copy link
Collaborator

@lawrence-forooghian lawrence-forooghian left a comment

Choose a reason for hiding this comment

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

It's exciting to think that we might be able to get rid of an external dependency at some point, so I'm happy to see this PR! I've popped some initial thoughts on here. I haven't looked at the implementation of ARTURLSessionWebSocket yet, since I'd like to understand the ARTWebSocket* protocols better first (see my comment re documentation).

Also, did you give any thought to the fact that, as it stands, CI will no longer be testing that the SDK works correctly when it uses SocketRocket, since we only test on:

Perhaps we need to add some older OS versions there too?

I also think that making the change that's proposed here makes sense mainly if we’re intending to drop support for iOS < 13 at some point. If not, then we're just going to end up having to maintain two WebSocket implementations instead of one. Do you have thoughts on this @QuintinWillison or @mikelee638?

@@ -3414,6 +3430,7 @@
SDKROOT = macosx;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OBJC_BRIDGING_HEADER = "Spec/AblySpec-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this related to the contents of the PR?

Copy link
Collaborator Author

@maratal maratal Dec 25, 2022

Choose a reason for hiding this comment

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

4793ebd
(Sorry this thing pops up every time, I should create an issue for it already 🤌)

NS_ASSUME_NONNULL_BEGIN

API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0))
@interface ARTURLSessionWebSocket : NSObject <ARTWebSocket, NSURLSessionWebSocketDelegate>
Copy link
Collaborator

Choose a reason for hiding this comment

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

The NSURLSessionWebSocketDelegate conformance seems like an implementation detail; can we keep it private by placing its declaration in the .m file?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@@ -5,16 +5,24 @@

NS_ASSUME_NONNULL_BEGIN

@class ARTLog;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this needed?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

ARTWS_CLOSING = 2,
ARTWS_CLOSED = 3,
};

/**
This protocol has the subset of ARTSRWebSocket we actually use.
*/
@protocol ARTWebSocket <NSObject>
Copy link
Collaborator

Choose a reason for hiding this comment

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

Part of my task in reviewing ARTURLSessionWebSocket is to confirm whether it seems to correctly conform to the ARTWebSocket protocol, which I can't currently do since this protocol has no documentation. I think that now would be a good moment to add documentation to this protocol. What do you think?

(Same goes for ARTWebSocketDelegate; to review ARTURLSessionWebSocket I need to verify whether it respects the contract of the delegate protocol, which I can't do since it's not documented.)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@@ -319,6 +325,8 @@ - (ARTRealtimeTransportError *)classifyError:(NSError *)error {
type = ARTRealtimeTransportErrorTypeHostUnreachable;
} else if ([error.domain isEqualToString:@"NSPOSIXErrorDomain"] && (error.code == 57 || error.code == 50)) {
type = ARTRealtimeTransportErrorTypeNoInternet;
} else if ([error.domain isEqualToString:@"NSURLErrorDomain"] && (error.code == -1009)) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
} else if ([error.domain isEqualToString:@"NSURLErrorDomain"] && (error.code == -1009)) {
} else if ([error.domain isEqualToString:NSURLErrorDomain] && (error.code == NSURLErrorNotConnectedToInternet)) {

Copy link
Collaborator

Choose a reason for hiding this comment

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

Also, it feels to me like the error classification should probably be delegated to the implementations of the ARTWebSocket protocol. If the point of using a protocol is to hide the implementation details of the WebSocket class (i.e. whether we're using SocketRocket or NSURLSession), then it doesn't make sense to be checking for SocketRocket-specific error codes here, for example. Furthermore, if in the future we want to remove SocketRocket, it's going to be harder to do because we won't know which lines in this method are safe to remove because they only applied to SocketRocket.

Copy link
Collaborator Author

@maratal maratal Dec 25, 2022

Choose a reason for hiding this comment

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

@protocol ARTWebSocketDelegate;

typedef NS_ENUM(NSInteger, ARTWebSocketState) {
ARTWS_CONNECTING = 0,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Style: I think that ARTWebSocketStateConnecting etc would be more appropriate.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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


@end

@implementation ARTURLSessionWebSocket {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Given how fundamental this class is to the SDK, I think it's important that we unit test it, to confirm that it conforms to the ARTWebSocket protocol and that it respects the contract of the ARTWebSocketDelegate protocol.

@lawrence-forooghian
Copy link
Collaborator

@QuintinWillison:

So, perhaps, we should be discussing this as part of scope for version 2 of this SDK? (i.e. a major version bump) -- this should count as an enhancement from a customer's perspective, as well as from ours as maintainers. FYI, @mikelee638

I'm not sure I understand how versioning would help us here – this change is meant to be a backwards-compatible enhancement so it wouldn't warrant a major version bump. If we did want to use versioning to provide customers with a way to opt in to this new code (which, as you say, I'm not sure many would be interested in doing), then it would probably make more sense to use a pre-release version.

@github-actions github-actions bot temporarily deployed to staging/pull/1541/jazzydoc December 25, 2022 21:36 Inactive
@QuintinWillison
Copy link
Contributor

Thanks for your comments, @lawrence-forooghian. You're right regarding versioning, though perhaps it might be a version 2 scope change if we're going to significantly increment minimum OS runtime version(s). 🤔 You also commented:

I also think that making the change that's proposed here makes sense mainly if we’re intending to drop support for iOS < 13 at some point. If not, then we're just going to end up having to maintain two WebSocket implementations instead of one.

Maintaining two WebSocket implementations is not ideal, both in terms of maintainability of the codebase and how it is tested. So my preference would be to drop support for the older iOS runtimes as soon as we can.

@QuintinWillison QuintinWillison removed their request for review February 28, 2023 11:53
@lawrence-forooghian
Copy link
Collaborator

lawrence-forooghian commented Apr 15, 2024

Taking another look at this, in the context of @umair-ably’s RFC for dropping support for iOS < 14. @maratal, do you remember whether your work here concluded that NSURLSessionWebSocketTask would be an adequate replacement for SocketRocket? Also, I noticed that the Network framework provides WebSocket functionality through NWProtocolWebSocket, also introduced in iOS 13; do you know if/how this differs to NSURLSessionWebSocketTask?

@maratal
Copy link
Collaborator Author

maratal commented Apr 15, 2024

I noticed that the Network framework provides WebSocket functionality through NWProtocolWebSocket, also introduced in iOS 13; do you know if/how this differs to NSURLSessionWebSocketTask?

Looks like it's swift only. And NSURLSessionWebSocketTask is an objective-c wrapper around it. That's my conclusion from the first glance.

@lawrence-forooghian
Copy link
Collaborator

Ah, OK. There is also a C version, though. Apple’s guidance is to favour the Network framework:

Unless you have a specific reason to use URLSession, use Network framework for new WebSocket code.

@maratal
Copy link
Collaborator Author

maratal commented Apr 15, 2024

Ah, OK. There is also a C version, though. Apple’s guidance is to favour the Network framework:

Unless you have a specific reason to use URLSession, use Network framework for new WebSocket code.

That's interesting, will check in depth the effort needed to move to c-version, thanks @lawrence-forooghian

@lawrence-forooghian
Copy link
Collaborator

If we drop support for iOS < 14, as is being proposed, we can then start using Swift inside the codebase anyway

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.

Investigate using native NSURLSession web socket instead of SocketRocket
3 participants