-
Notifications
You must be signed in to change notification settings - Fork 1.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
[Event Hubs] Perform sendRequest() operation handling from SDK #4322
Conversation
Bringing over the entire RequestResponseLink from core-amqp is an overkill. I would suggest the below:
I am basically suggesting something similar to what was tried in #4321 except instead of disabling the retry in core-amqp, we remove that feature altogether. Since removing that feature will break your changes in #4265, we can update the version of core-amqp to 1.0.0-preview.2 |
@ramya0820 The build is failing. Can you take a look? |
name: "OperationTimeoutError", | ||
message: desc | ||
}; | ||
return reject(translate(e)); |
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.
We need to remove the event listener for abort event here before returning with the rejected promise
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.
Updated
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.
I recall this being resolved, but now I don't see the removal of event listener when the timer times out.
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.
We aren't adding listeners anymore as part of the outer abort for init.
Asynchronous abortion (by using event emitter listeners), is currently not trivial for init
and right way to go about it would be to pass in the aborter to init
So that the connection gets cleanly closed if already in progress of being created.
Discussed this with @chradek (See #4322 (comment))
Since abort during init is not solved for receive as well, and needs more work and tests, we were looking to move it out of this PR.
/azp run js - eventhubs-client - tests |
Azure Pipelines successfully started running 1 pipeline(s). |
/azp run js - eventhubs-client - tests |
Azure Pipelines successfully started running 1 pipeline(s). |
const retryTimeoutInMs = getRetryAttemptTimeoutInMs(options.retryOptions); | ||
let timeTakenByInit = 0; | ||
|
||
if (!this._isMgmtRequestResponseLinkOpen()) { |
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.
We should check if the operation has been cancelled before this point so we don't do an unnecessary initialization.
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.
We are doing that check right before this line, that should suffice right?
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.
Prior to this comment, I had removed abort for around init altogether, since the test "respects cancellation token" was failing.
This was because init doesn't accept the abortSignal and so the connection, sessions, sender/receiver links and associated listeners, timers were all still staying open.
I had tried a lot of things, explicitly closing, clearing them, but looks like the connection needs to be explicitly closed and doing that was not trivial as reference to connection within abandoned init was getting lost. See #4322 (comment)
Here, I agreed with making the synchronous check for before the init for in case we know by then that operation was aborted.
} catch (err) { | ||
return reject(translate(err)); | ||
} finally { | ||
clearTimeout(waitTimer); |
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.
We should also check if the operation was cancelled after calling _init. If it has, we know we can close the connection and reject.
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 second check is unnecessary since we already have one at the start of sendRequest
Discussed offline about how abortSignal
will need to be passed in to the init
and other internal operations to gracefully handle cancellation during init as well.
Clearing connection, links, listeners and timers will need to be done as part of this.
Since this needs to be done for receive() as well and would involve more work, changes for it and tests can be added as part of new PR and be linked to separate issue #4422
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 second check is unnecessary since we already have one at the start of sendRequest
I agree
/azp run js - eventhubs-client - tests |
Azure Pipelines successfully started running 1 pipeline(s). |
@ramya0820 Looks like when resolving merge conflicts, some changes have been missed out Please do one round of review on your own |
The links to comments seem to be missing ^ One of them seems to have been about #4322 (comment) which wasn't a miss, but is deliberate conclusion we arrived at to handle abort during init outside of this PR. Could you share link to the other item you think was missing? @ramya-rao-a |
const result = await this._mgmtReqResLink!.sendRequest(request, sendRequestOptions); | ||
|
||
resolve(result); | ||
} catch (err) { |
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.
init()
call has its own try/catch
This catch
corresponds to the outer try block i.e the block that covers both init()
and this._mgmtReqResLink!.sendRequest()
Any reason to have an outer try/catch block this way?
I would imagine that init()
and this._mgmtReqResLink!.sendRequest()
would have their own try/catch blocks
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.
It allows us to catch errors from other code paths in case any gets thrown and indicate in logs with a message about source of it.
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 2 points from where an error can be expected to be thrown (by code that this file doesnt control) are the init()
call and the this._mgmtReqResLink!.sendRequest()
call. Having try/catch around the 2 calls separately is enough.
Bring over RequestResponseLink setup utilities over from
core-amqp
to the Event Hubs SDK.This will be subsequently trimmed down, updated so it does only what the SDK requires (specifically exclude retries)
This is the alternate and preferred implementation that may override PR #4321 @ramya-rao-a