Skip to content

[Event Hubs] Update RetryOptions interface to pass exponential retry params#4400

Merged
ramya0820 merged 31 commits intoAzure:masterfrom
ramya0820:issue-4266
Jul 30, 2019
Merged

[Event Hubs] Update RetryOptions interface to pass exponential retry params#4400
ramya0820 merged 31 commits intoAzure:masterfrom
ramya0820:issue-4266

Conversation

@ramya0820
Copy link
Member

For more context refer to #4266

@ramya0820 ramya0820 requested review from chradek and ramya-rao-a July 23, 2019 18:52
@ramya0820 ramya0820 self-assigned this Jul 23, 2019
@ramya-rao-a ramya-rao-a requested a review from ShivangiReja July 23, 2019 20:50
operation: () => this.initialize(initOptions),
operationType: RetryOperationType.receiverLink,
maxRetries: Constants.defaultMaxRetriesForConnection
maxRetries: Constants.defaultMaxRetriesForConnection,
Copy link
Contributor

Choose a reason for hiding this comment

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

Super nit: looks like this change wasn't needed, does running npm run format remove the comma?

Copy link
Member Author

Choose a reason for hiding this comment

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

That's odd, it wasn't going away on file save. After merge from master it disappears on file save itself..

private _initRetryOptions(
retryOptions: RetryOptions = {}
): Required<Pick<RetryOptions, "maxRetries" | "retryInterval">> {
): Required<Pick<RetryOptions, "maxRetries" | "retryInterval">> & RetryOptions {
Copy link
Contributor

Choose a reason for hiding this comment

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

@chradek What was the intention of _initRetryOptions?
I initially thought it was a way to guarantee non undefined values on maxRetries and retryInterval

With this change, we now allow the rest of properties of RetryOptions here that may be undefined.
I have this feeling that the purpose is being defeated if initRetryOptions is not initializing with some value

Copy link
Contributor

Choose a reason for hiding this comment

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

@ramya-rao-a
The intention was indeed to make sure maxRetries and retryInterval were always defined since we have known default options for them. I think the method name is fine...a comment could be added to indicate that it will set default values if a default exists.

With that in mind, I think this should also set retryPolicy to required since we have a known default (Linear)

Copy link
Member Author

Choose a reason for hiding this comment

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

Sure, we can add the comment for clarity

About default for retryPolicy, core-amqp handles it at https://github.com/Azure/azure-sdk-for-js/blob/master/sdk/core/core-amqp/src/retry.ts#L217

But agree that the value can be set and made required - not one way or against other since this is an internal utility. But we might want to rethink about why we need this utility and have any values be marked as required when they all by design seem to be optional.

Copy link
Contributor

Choose a reason for hiding this comment

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

This method was originally suggested so that we wouldn't have to keep calculating defaults every time a receiveBatch operation was called.

Since we are setting the defaults once when instantiating the class, we also know that these fields are always set. Making them appear Required lets us skip the null checks and avoid using the non-null assertion.

Copy link
Member Author

Choose a reason for hiding this comment

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

Got it, that makes sense in this context
Although I think the defaults for these retry related options can be managed, set within core-amqp's retry?
It doesn't seem like there's much value in doing it again, unless these were Event Hubs specific defaults~

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks, receiver.ts looks good

Copy link
Member Author

Choose a reason for hiding this comment

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

  • About classes like EventHubSender, since we are passing in the retryOptions as part of senderOptions current design/implementation doesn't seem to benefit from using a private instance. Because, we anyway we need to check contents of senderOptions from within send implementations that setup, perform retries.
  • If we do want to have one, then we'll need to refactor the internal API to not require passing senderOptions / retryOptions to eventHubSender and use the private instance set in receiver by moving implementation of send request and retries to sender as opposed to eventHubSender (Because for receive, we have it in receiver and not in eventHubReceiver.) We could refactor, improve the implementation as part of a different issue / PR.

Updated implementations for these however, to simplify and move out the checks where applicable.
Some instances of timeOutInMs still require default value computation as they are used in setTimeout. Few others such retryInterval need checks since they are in a differing units (seconds vs milliseconds) and can be updated as part of #4277

(Could consider naming it to be same as what we have for retry in core-amqp to likes of delayInMs?) @ramya-rao-a @bterlson

Copy link
Member Author

Choose a reason for hiding this comment

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

Discussed offline with @bterlson, we would like to update retryInterval to be delayInSeconds
@ramya-rao-a let us know if there's any concern with it.

Copy link
Contributor

@ramya-rao-a ramya-rao-a Jul 29, 2019

Choose a reason for hiding this comment

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

@ramya0820 I would prefer not to do the renames of the retry options in this PR.
This PR should be scoped to

  • passing the exponential retry related options from user to relevant places
  • ensuring that this flow from user to the relevant places is using good coding practices

@bterlson will be consolidating the names across core-http and storage to come up with the final list and log an issue for it.

Copy link
Contributor

Choose a reason for hiding this comment

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

Few others such retryInterval need checks since they are in a differing units (seconds vs milliseconds) and can be updated as part of #4277

Agreed that we need to do the conversion and so need checks, but we dont need to set the defaults as we expect core-amqp to do that. So I would suggest something like the below

typeof retryInterval === "number" ? retryInterval/1000 : undefined

Copy link
Contributor

@ramya-rao-a ramya-rao-a left a comment

Choose a reason for hiding this comment

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

3 observations:

  • In the getMaxMessageSize() is a function that uses retry. It should also use the exponential parameters as well
  • I like what we have done in the receiver.ts file i.e have all the defaults handled in core-amqp and avoid the retryOptions && retryOptions.maxRetries model in favor of retryOptions.amxRetries. Let's ensure we do the same in the eventHubSender.ts file
  • I believe #4322 is almost done. Let's get that merged, and then update this PR to pass in the exponential things to the management operations

@ramya0820
Copy link
Member Author

  • In the getMaxMessageSize() is a function that uses retry. It should also use the exponential parameters as well

Updated

  • I like what we have done in the receiver.ts file i.e have all the defaults handled in core-amqp and avoid the retryOptions && retryOptions.maxRetries model in favor of retryOptions.amxRetries. Let's ensure we do the same in the eventHubSender.ts file

Updated

Updated, yes depending on which PR gets merged first, I can take care of the conflicts and ensure this is in place. (The other one's waiting on another approval)

cc: @ramya-rao-a

connectionHost: this._context.config.host,
connectionId: this._context.connectionId,
delayInSeconds: retryOptions.retryInterval,
delayInSeconds: retryOptions.delayInMs,
Copy link
Contributor

Choose a reason for hiding this comment

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

We are passing milliseconds to something that expects seconds

? options.retryOptions.retryInterval / 1000
options.retryOptions.delayInMs &&
options.retryOptions.delayInMs >= 0
? options.retryOptions.delayInMs / 1000
Copy link
Contributor

Choose a reason for hiding this comment

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

In the spirit of avoiding the null check for retryOptions we should initialize options.retryOptions to {} if no value was provided like we are doing in a couple of other places in this PR

Copy link
Member Author

Choose a reason for hiding this comment

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

Addressed this and other comments, please see latest commit

: Constants.defaultDelayBetweenOperationRetriesInSeconds;
typeof retryOptions.retryInterval === "number"
? retryOptions.retryInterval / 1000
: undefined;
Copy link
Contributor

@ramya-rao-a ramya-rao-a Jul 30, 2019

Choose a reason for hiding this comment

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

The above 2 constants are not needed. They can be inlined while creating the RetryConfig just like you did in getMaxMessageSize(). Then as part of #4401, the inline will get simplified too

: Constants.defaultDelayBetweenOperationRetriesInSeconds;
typeof retryOptions.retryInterval === "number"
? retryOptions.retryInterval / 1000
: undefined;
Copy link
Contributor

@ramya-rao-a ramya-rao-a Jul 30, 2019

Choose a reason for hiding this comment

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

The above 2 constants are not needed. They can be inlined while creating the RetryConfig just like you did in getMaxMessageSize(). Then as part of #4401, the inline will get simplified too

Copy link
Contributor

@ramya-rao-a ramya-rao-a left a comment

Choose a reason for hiding this comment

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

Looks good. Just 2 comments regarding inlining maxRetries and delayInSeconds to be consistent

@ramya0820
Copy link
Member Author

Looks good. Just 2 comments regarding inlining maxRetries and delayInSeconds to be consistent

Updated

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants