-
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] Use AwaitableSender in lieu of Sender #4446
Changes from 22 commits
260b0e6
c74f5e4
00016cb
5c12c13
2081256
f3511e0
7f00436
e2dc78b
232390c
05046df
c58e6eb
298990b
5956ffa
b2633be
264794c
aa664ff
25e3f63
edf1949
ebd7dde
11dbe10
cb14ba3
f5f0428
abc9689
ffca3c9
dee862c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -481,12 +481,20 @@ export const retryableErrors: string[] = [ | |
"ServerBusyError", | ||
"ServiceUnavailableError", | ||
"OperationCancelledError", | ||
|
||
// OperationTimeoutError occurs when the service fails to respond within a given timeframe. | ||
// Since reasons for such failures can be transient, this is treated as a retryable error. | ||
"OperationTimeoutError", | ||
|
||
"SenderBusyError", | ||
"MessagingError", | ||
"DetachForcedError", | ||
"ConnectionForcedError", | ||
"TransferLimitExceededError" | ||
"TransferLimitExceededError", | ||
|
||
// InsufficientCreditError occurs when the number of credits available on Rhea link is insufficient. | ||
// Since reasons for such shortage can be transient such as for pending delivery of messages, this is treated as a retryable error. | ||
"InsufficientCreditError" | ||
]; | ||
|
||
/** | ||
|
@@ -539,6 +547,32 @@ function isBrowserWebsocketError(err: any): boolean { | |
return result; | ||
} | ||
|
||
/** | ||
* @internal | ||
* Checks if given object maps to a valid custom error. If yes, configures and returns the appropriate error instance, else returns `undefined`. | ||
* @param err | ||
*/ | ||
function getCustomError(err: AmqpError | Error): MessagingError | undefined { | ||
const error: MessagingError = err as MessagingError; | ||
const errorName = (err as Error).name; | ||
if ( | ||
// instanceof checks on custom Errors doesn't work without manually setting the prototype within the error. | ||
// Must do a name check until the custom error is updated, and that doesn't break compatibility | ||
// https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work | ||
retryableErrors.indexOf(errorName) > -1 | ||
) { | ||
error.retryable = true; | ||
return error; | ||
} | ||
|
||
if (errorName === "AbortError") { | ||
error.retryable = false; | ||
return error; | ||
} | ||
|
||
return undefined; | ||
} | ||
|
||
/** | ||
* Translates the AQMP error received at the protocol layer or a generic Error into a MessagingError. | ||
* | ||
|
@@ -553,28 +587,9 @@ export function translate(err: AmqpError | Error): MessagingError { | |
|
||
let error: MessagingError = err as MessagingError; | ||
|
||
// OperationTimeoutError occurs when the service fails to respond within a given timeframe. | ||
// Since reasons for such failures can be transient, this is treated as a retryable error. | ||
if ( | ||
// instanceof checks on custom Errors doesn't work without manually setting the prototype within the error. | ||
// Must do a name check until OperationTimeoutError is updated, and that doesn't break compatibility | ||
// https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work | ||
(err as Error).name === "OperationTimeoutError" | ||
) { | ||
error.retryable = true; | ||
return error; | ||
} | ||
|
||
// Built-in errors like TypeError and RangeError should not be retryable as these indicate issues | ||
// with user input and not an issue with the Messaging process. | ||
if ( | ||
err instanceof TypeError || | ||
err instanceof RangeError || | ||
// instanceof checks on custom Errors doesn't work without manually setting the prototype within the error. | ||
// Must do a name check until AbortError is updated, and that doesn't break compatibility | ||
// https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work | ||
(err as Error).name === "AbortError" | ||
) { | ||
if (err instanceof TypeError || err instanceof RangeError) { | ||
error.retryable = false; | ||
return error; | ||
} | ||
|
@@ -622,6 +637,10 @@ export function translate(err: AmqpError | Error): MessagingError { | |
error = new MessagingError("Websocket connection failed."); | ||
error.name = ConditionErrorNameMapper[ErrorNameConditionMapper.ServiceCommunicationError]; | ||
error.retryable = false; | ||
} | ||
const customError = getCustomError(err); | ||
if (customError) { | ||
return customError; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since we are creating the custom error up front and using it only after a series of if/elses, the current model slightly hurts code readability and the ease of understanding. I would suggest the below if (isAmqpError(err)) { // do the needful and return the error }
if (isSystemError(err)) { // do the needful and return the error }
if (isBrowserWebsocketError(err)) { // do the needful and return the error }
const customError = getCustomError(err)
if (customError) {
return customError
}
// The generic error handling here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please take another look at the suggested code change above. With f5f0428, you have moved the call to Due to this regardless of all the processing that is done by |
||
} else { | ||
// Translate a generic error into MessagingError. | ||
error = new MessagingError((err as Error).message); | ||
|
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 don't want to cover any of the amqp errors here because amqp errors should undergo the appropriate processing as covered in the
translate()
. Therefore, make an early exit from here ifisAmqpError(err)
returnstrue
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 see that we have updated the if/else in translate() to use the result of this method only when it is not an amqp error. That is good.
But here since the input supports both AmqpError and simple Error, it is still confusing to anyone reading this code independently
My first suggestion would have been to update this method to take in only
Error
, but this might not work out due to typing issues. Because as far as the typescript compiler is concerned, theerr
object you pass in could be either of the 2 types.Please consider not having this as a separate method and moving the code here directly into
translate()