-
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
[service-bus] Reliability improvements and testing updates #15098
[service-bus] Reliability improvements and testing updates #15098
Conversation
…er (and associated code) are correct.
…my with internal functions. For the most part though the tests got simpler since there were fewer functions that needed mocking (subscribe now does initialization and subscription), etc.. There were also some interesting breakages when I changed assertThrow to chain on the promises returned (which made my test callstacks a bit nicer) in that one of the methods that's being tested (settleMessages) was not marked as async, causing it to throw exceptions that were not "catchable" by chaining to the returned promise. I've also enabled code coverage, even for unit tests. They go under the coverage/unit-tests folder, just to keep it all clean.
/azp run js - service-bus - tests |
Azure Pipelines successfully started running 1 pipeline(s). |
…rom a more relevant place) in the caller.
/azp run js - service-bus - tests |
Azure Pipelines successfully started running 1 pipeline(s). |
/azp run js - service-bus - tests |
Azure Pipelines successfully started running 1 pipeline(s). |
- Add in another 'debugging' event (preInitialize) that gets called before our internal _init() - Doing some rearrangement and testing
…g and debugging just work, etc.. - Fixing some other issues: - Revert sesions back over to the way it was before, with a resume call thrown in for now. NOTE: messagesession could use some work as it's falling behind some of the changes we're making to the non-session workflow.
/azp run js - service-bus - tests |
Azure Pipelines successfully started running 1 pipeline(s). |
/azp run js - service-bus - tests |
Azure Pipelines successfully started running 1 pipeline(s). |
/azp run js - service-bus - tests |
Azure Pipelines successfully started running 1 pipeline(s). |
/azp run js - service-bus - tests |
Azure Pipelines successfully started running 1 pipeline(s). |
*/ | ||
async drain(): Promise<void> { | ||
const { receiver, logPrefix } = this._getCurrentReceiver(); | ||
|
||
if (!this._isValidReceiver(receiver)) { | ||
// TODO: should we throw? |
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 guess draining is technically done?
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.
Yeah, this comment was me thinking "aloud".
I think we could consider it a candidate to throw on but it seemed less important. The spot where it's used would basically do nothing useful if the receiver was invalid anyways but it'd be nice to go through here again. I think we have some future work to add in a "drain with timeout" for another bug in our tests, so perhaps we could lump in the investigation there.
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 would consider this a no-op and not an error scenario. The need for drain comes in order to avoid receiving messages when we are not ready for them. Absence of the receiver achieves that goal. So, I would combine the two checks here
if (!receiver || !received.isOpen() || receiver.credit === 0) {
return;
}
* | ||
* @returns A promise that will resolve when a link is created and we successfully add credits to it. | ||
*/ | ||
private async _subscribeImpl(caller: "detach" | "subscribe"): Promise<void> { |
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 caller
parameter feels a little odd to me. Are you just trying to get away from using useNewName
? Maybe something that's a bit more descriptive of what's happening where the values are something like "initialize" and "reconnect" would be a bit clearer without coupling us to the method names calling 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.
I can change the parameter name but those are the names of the two logical flows I think.
However, I have thought about renaming 'detach' to 'reconnect' a few times. Maybe this is just a happy chance to do so?
…scribe() as a SessionLockLost error. This gives the user a hint that the link is definitely dead.
… in our version check.
Co-authored-by: Ramya Rao <ramya.rao.a@outlook.com>
- Send a nice standard error message that indicates the session lock has been lost when we throw for addCredit() in session receivers.
/azp run js - service-bus - tests |
Azure Pipelines successfully started running 1 pipeline(s). |
* | ||
* @internal | ||
*/ | ||
export async function retryForever<T>( |
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 and not a blocker for this PR
retryForever
is only used by the streaming receiver in non session case. So far other methods in this file "receiverCommon" are for cases that are indeed common between sessions and non sessions. So, perhaps not the right place for the code. Moving it can also re-enforce the understanding of one of the main differences in sessions and non sessions receiver which is the forever loop
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.
Yeah, there are a few little naming changes that I didn't do but @HarshaNalluru has in one of his PRs (specifically receiverHelper is really only streamingReceiver helper, etc..). We should do a little cleanup of our file organization as it's a bit of a mess at the moment.
…es more on public APIs. It did point out a simple use-case where we shouldn't bug the user with an error - if they suspend the receiver (and thus addCredit throws AbortErrors) we can ignore those since the user has initiated the action that caused it and there'd be nothing useful about reporting that specific error. Also, I made the session "failed to add credit" message a bit more like the one we throw in non-session receivers.
/azp run js - service-bus - tests |
Azure Pipelines successfully started running 1 pipeline(s). |
@ramya-rao-a - made a slight change to MessageSession just now. I don't report the error to the user if it happens to be AbortError. That only happens if the error is being caused by a user suspending the receiver, so something like this: const subscription = sessionReceiver.subscribe({
processMessage: async () => {
await subscription.close();
}
// and addCredit happens after processMessage and throws an AbortError
}); I think this sticks with the spirit of our original discussion - let's not report errors to the user if they shouldn't do anything or it's not useful (which this qualifies). All other errors are still reported. For non-sessions we only report the error to our internal debugging-only processError so I've left that in place. (BTW: found this because we had a test that was doing this, but in a really round-about way. I fixed that test as well so it looks like what I have above, which is legitimate) |
/azp run js - service-bus - tests |
Azure Pipelines successfully started running 1 pipeline(s). |
This pull request is protected by Check Enforcer. What is Check Enforcer?Check Enforcer helps ensure all pull requests are covered by at least one check-run (typically an Azure Pipeline). When all check-runs associated with this pull request pass then Check Enforcer itself will pass. Why am I getting this message?You are getting this message because Check Enforcer did not detect any check-runs being associated with this pull request within five minutes. This may indicate that your pull request is not covered by any pipelines and so Check Enforcer is correctly blocking the pull request being merged. What should I do now?If the check-enforcer check-run is not passing and all other check-runs associated with this PR are passing (excluding license-cla) then you could try telling Check Enforcer to evaluate your pull request again. You can do this by adding a comment to this pull request as follows: What if I am onboarding a new service?Often, new services do not have validation pipelines associated with them, in order to bootstrap pipelines for a new service, you can issue the following command as a pull request comment: |
/azp run js - service-bus - tests |
Azure Pipelines successfully started running 1 pipeline(s). |
- Fixing a test that used to depend on only a single error happening on detach to handle the possibility of more than one. This might point to moving towards more like what we did in non-session-receiver.
/azp run js - service-bus - tests |
Azure Pipelines successfully started running 1 pipeline(s). |
Updating vm sizes property (Azure#15098) * updating vm sizes property * prettier fix * prettier fix Co-authored-by: Aaheli Chattopadhyay <aahelic@microsoft.com>
This PR has a few changes in it, primarily to improve our robustness and our reporting:
General reliability improvements:
SDK debugging:
processInitialize
handler has been split into two (still internal) handlers - preInitialize and postInitialize. preInitialize runs before init(), and postInitialize runs after init() but before addCredit. This lets us write more reliable tests. These are not exposed to customers.Fixes #14535