-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Add the callback of send operation. #458
base: main
Are you sure you want to change the base?
Conversation
Add feature: Callback of send data.
Thank you for your pull request and welcome to our community. We require contributors to sign our Contributor License Agreement, and we don't seem to have you on file. In order for us to review and merge your code, please sign up at https://code.facebook.com/cla - and if you have received this in error or have any questions, please drop us a line at [email protected]. Thanks! |
I signed in CLA. Thank you. |
Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks! |
This looks like a nice idea, will review soon and provide some feedback on naming and polish so we can get this merged in! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a great idea, and I absolutely love it!
Let's work together to get this merged in!
There are a lot of minor nits that need to be fixed before we feel comfortable merging it in.
On top of that, please revert all whitespace additions in SRWebSocket.m
lines 1398-1465
@@ -59,6 +59,8 @@ extern NSString *const SRHTTPResponseErrorKey; | |||
|
|||
@protocol SRWebSocketDelegate; | |||
|
|||
typedef void (^SRSendCompleteBlock)(NSError * _Nullable error); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Rename to SRSendCompletionBlock
.
|
||
@return `YES` if the string was scheduled to send, otherwise - `NO`. | ||
*/ | ||
- (BOOL)sendString:(NSString *)string complete:(SRSendCompleteBlock)complete; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's improve the naming here to the following. Also, will improve the Swift imported method.
- (BOOL)sendString:(NSString *)string
completion:(nullable SRSendCompletionBlock)completion NS_SWIFT_NAME(send(string:completion:));
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The above code block also ensures that everyone can pass nil
to the completion argument, since it looks like you are validating it anyway.
Send a UTF-8 String to the server. | ||
|
||
@param string String to send. | ||
@param complete The call back of send result. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Double space after complete
@@ -279,6 +281,18 @@ extern NSString *const SRHTTPResponseErrorKey; | |||
- (BOOL)sendString:(NSString *)string error:(NSError **)error NS_SWIFT_NAME(send(string:)); | |||
|
|||
/** | |||
Send a UTF-8 String to the server. | |||
|
|||
@param string String to send. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Please align String to send
with the next parameter description for better readability.
|
||
@param string String to send. | ||
@param complete The call back of send result. | ||
If an error occurs, this block will invoked with an `NSerror` object cantaining information about the error; Otherwise |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: NSError
Nit: containing
Nit: , otherwise this block will be invoked
} | ||
SRDebugLog(message); | ||
return NO; | ||
} | ||
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Revert white space addition.
@@ -1051,10 +1111,29 @@ - (void)_pumpWriting; | |||
[self _failWithError:error]; | |||
return; | |||
} | |||
|
|||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Remove whitespace addition.
|
||
|
||
SRDataCallback *record = [[SRDataCallback alloc] init]; | ||
record.completeBlock = complete; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This completion
can be nil
and we are going to waste precious (on iOS at least) CPU cycles for running all this math later.
What do you think if we don't add the record
to the _sendCallbacks
at all if completion
is nil
?
This is going to ease the work later as well.
[_sendCallbacks enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull key, SRDataCallback * _Nonnull obj, BOOL * _Nonnull stop) { | ||
if (NSMaxRange(obj.range) <= _outputBufferOffset) { | ||
[removeKeys addObject:key]; | ||
if (obj.completeBlock) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can go away once we can ensure that _sendCallbacks
only contain objects with non-nil completion
.
@@ -1314,74 +1393,85 @@ -(void)_pumpScanner; | |||
|
|||
static const size_t SRFrameHeaderOverhead = 32; | |||
|
|||
- (void)_sendFrameWithOpcode:(SROpCode)opCode data:(NSData *)data | |||
{ | |||
- (void)_sendFrameWithOpcode:(SROpCode)opCode data:(NSData *)data complete:(SRSendCompleteBlock)complete { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Move the opening bracket to the next line.
merge from facebook
@nlutsenko Thank you for taking the time to review my code. I have changed you mentioned, please review again. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Almost there...
Few nits, but most importantly:
- Using
NSValue valueWithRange:
for the key - Improving the method chains and signatures for
error:completion:
style methods
@@ -69,6 +69,31 @@ | |||
NSString *const SRWebSocketErrorDomain = @"SRWebSocketErrorDomain"; | |||
NSString *const SRHTTPResponseErrorKey = @"HTTPResponseStatusCode"; | |||
|
|||
@interface SRDataCallback : NSObject | |||
@property (nonatomic, assign) NSRange range; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Remove extra space aka make it look like NSRange range;
@@ -548,6 +577,13 @@ - (void)_closeWithProtocolError:(NSString *)message; | |||
- (void)_failWithError:(NSError *)error; | |||
{ | |||
dispatch_async(_workQueue, ^{ | |||
[_sendCallbacks enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull key, SRDataCallback * _Nonnull obj, BOOL * _Nonnull stop) { | |||
if (obj.completion) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since completion
is never nil
- you don't need this check.
return; | ||
} | ||
|
||
|
||
if (completion != nil) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Replace with if (completion) {
SRDataCallback *record = [[SRDataCallback alloc] initWithRange:dataRange completion:completion]; | ||
|
||
static NSUInteger keyCount = 0; | ||
_sendCallbacks[@(keyCount++)] = record; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if this is the best way to use a key
here.
Can we use a [NSValue valueWithRange:dataRange]
as a key?
return [self sendString:string error:NULL completion:completion]; | ||
} | ||
|
||
- (BOOL)sendString:(NSString *)string error:(NSError **)error completion:(nullable SRSendCompletionBlock)completion { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think if we would remove error
argument from this method and move it only to the method that needs it? Thus we can eliminate the need for weird method with synchronous and asynchronous signatures?
return [self sendDataNoCopy:data error:NULL completion:completion]; | ||
} | ||
|
||
- (BOOL)sendDataNoCopy:(nullable NSData *)data error:(NSError **)error completion:(SRSendCompletionBlock)completion |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as for sendString:error:completion:
@@ -1320,19 +1418,26 @@ -(void)_pumpScanner; | |||
|
|||
static const size_t SRFrameHeaderOverhead = 32; | |||
|
|||
- (void)_sendFrameWithOpcode:(SROpCode)opCode data:(NSData *)data | |||
- (void)_sendFrameWithOpcode:(SROpCode)opCode data:(NSData *)data completion:(SRSendCompletionBlock)completion |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
completion
argument needs proper nullability annotation aka completion:(nullable SRSendCompletionBlock)completion
Yes, you are right. Use |
@nlutsenko Can you review the code? |
Add feature:
Callback of send data.