Skip to content
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] Introduce timeoutInMs #4239

Merged
merged 9 commits into from
Jul 11, 2019

Conversation

ramya0820
Copy link
Member

@ramya0820 ramya0820 commented Jul 10, 2019

Following is summary of usage of retryOptions and instances of applicable operation timeouts

  • makeManagementRequest relies on retryOptions to support send requests. This already has per try operation timeout implemented in core-amqp and just required us to make option available to users and pass it in
  • receive and receiveBatch operations already support per try operation timeouts and allow users to configure this value using maxWaitTimeInSeconds. However introducing operationTimeoutInMs on retryOptions to mean same thing is bound to get confusing. Should we get rid of this parameter and have users supply this using the retryOptions ? @ramya-rao-a

For more context refer to #4171

@ramya0820 ramya0820 requested a review from ramya-rao-a July 10, 2019 01:29
@ramya0820 ramya0820 self-assigned this Jul 10, 2019
* should wait to receiver the said amount of messages. If not provided, it defaults to 60 seconds.
* @param [maxWaitTimeInSeconds]
*
* This will no longer be used.
Copy link
Member Author

Choose a reason for hiding this comment

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

@ramya-rao-a Specifically anted to clarify if making this change to API is fine. This will subsequently require updates across source, tests and likely samples.

Copy link
Contributor

Choose a reason for hiding this comment

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

Lets keep receiver changes out of scope of this PR and re-visit later

@ramya-rao-a
Copy link
Contributor

receive does not take any timeouts, only receiveBatch does. Keep receive operations out of scope of this PR. We will clarify this with the service team and get back to it

/**
* Number of milliseconds to wait for each operation attempt to get completed within.
*/
operationTimeoutInMs?: number;
Copy link
Contributor

Choose a reason for hiding this comment

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

Did we run the name by @bterlson?
I worry that operationTimeout would make one think that the time applies to the entire operation and not the individual attempts

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, the name 'operationTimeoutInMs' was decided on by Brian and it has always referred to the individual attempt/execution.

Currently though, this PR is scoped per specific changes you wanted in. The documentation/usage of RetryPolicy will need to be made clear and is likely going to have more changes based on further discussions/work we discussed offline for #2835

Copy link
Member Author

Choose a reason for hiding this comment

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

@bterlson Given the current context of RetryPolicy related changes/usage in this PR, could you clarify if this needs to change?

Copy link
Contributor

Choose a reason for hiding this comment

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

Since we're enforcing a minimum timeout value, I think we should document it here as well.

Copy link
Member Author

Choose a reason for hiding this comment

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

But that's only for exponential retry correct? As I see it, that isn't supported yet

Copy link
Member

Choose a reason for hiding this comment

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

To be fair, I only decided on the suffix! I agree with @ramya-rao-a that operationTimeout is misleading. perAttemptTimeoutInMs? Just timeoutInMs may be appropriate too...

Copy link
Contributor

Choose a reason for hiding this comment

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

@chradek was referring to #4239 (comment) when he spoke of the "minimum"

I would go with timeoutInMs for now.

Copy link
Member Author

Choose a reason for hiding this comment

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

Updated

eventHubPath: string,
credential: TokenCredential,
options?: EventHubClientOptions
);
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you check if you are using the prettier extension or not? These formatting changes shouldnt be happening

Copy link
Member Author

Choose a reason for hiding this comment

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

Removed

options.retryOptions.operationTimeoutInMs == undefined ||
options.retryOptions.operationTimeoutInMs < 0
? Constants.defaultOperationTimeoutInSeconds
: options.retryOptions.operationTimeoutInMs / 1000,
Copy link
Contributor

Choose a reason for hiding this comment

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

We had feedback that we should have a minimum value for per operation timeout, else it is easy to abuse the system by forcing frequent timeouts by giving smaller values.

Use the Constants.defaultOperationTimeoutInSeconds as the "minimum" for now

Copy link
Contributor

Choose a reason for hiding this comment

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

I see that 4ba2e14 commit has been made in an attempt to address the issue, but the change is not solving the problem at hand.

Use Constants.defaultOperationTimeoutInSeconds as minimum value means that if user provides a value lesser than this, then we ignore user's value and use Constants.defaultOperationTimeoutInSeconds instead

Copy link
Member Author

Choose a reason for hiding this comment

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

Updated

* should wait to receiver the said amount of messages. If not provided, it defaults to 60 seconds.
* @param [maxWaitTimeInSeconds]
*
* This will no longer be used.
Copy link
Contributor

Choose a reason for hiding this comment

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

Lets keep receiver changes out of scope of this PR and re-visit later

@ramya0820 ramya0820 force-pushed the issue-4171-eh-only branch from c5257d8 to 1d1975e Compare July 11, 2019 00:12
options.retryOptions.operationTimeoutInMs == undefined ||
options.retryOptions.operationTimeoutInMs <= 0
? Constants.defaultOperationTimeoutInSeconds * 1000
: options.retryOptions.operationTimeoutInMs
Copy link
Contributor

Choose a reason for hiding this comment

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

  • For readability, pull this code out and have a variable/constant hold the value of the timeout
  • Initializing options with {} is done early on, so the check options == undefined is not needed

Copy link
Member Author

Choose a reason for hiding this comment

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

Within the event handler it seemed to require the check, please see updated code

@@ -296,6 +296,12 @@ export class ManagementClient extends LinkEntity {
maxRetries: options.retryOptions && options.retryOptions.maxRetries,
abortSignal: options.abortSignal,
requestName: options.requestName,
timeoutInSeconds:
options.retryOptions == undefined ||
Copy link
Contributor

Choose a reason for hiding this comment

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

For readability, pull this code out and have a variable/constant hold the value of the timeout

@ramya0820 ramya0820 force-pushed the issue-4171-eh-only branch from 4ba2e14 to badb691 Compare July 11, 2019 02:15
@ramya-rao-a
Copy link
Contributor

@ramya0820 Please avoid force pushing to an open PR, we lose track of all older comments in the Files view

/**
* Number of milliseconds to wait for each operation attempt to get completed within.
*/
operationTimeoutInMs?: number;
Copy link
Contributor

Choose a reason for hiding this comment

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

Since we're enforcing a minimum timeout value, I think we should document it here as well.

@@ -471,6 +471,13 @@ export class EventHubSender extends LinkEntity {
options = {};
}

const operationTimeoutInMs =
options.retryOptions == undefined ||
options.retryOptions.operationTimeoutInMs == undefined ||
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe a safer check would be

Suggested change
options.retryOptions.operationTimeoutInMs == undefined ||
typeof options.retryOptions.operationTimeoutInMs !== "number" ||

That way we don't allow it to be set to a different type in the last part of your ternary operation. Could also add an isFinite(options.retryOptions.operationTimeoutInMs so we protect against NaN or Infinity (unless we want Infinity as a valid value).

Copy link
Member Author

Choose a reason for hiding this comment

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

Nice, we should probably add these validations to other such parameters as well

@@ -323,10 +318,18 @@ export class ManagementClient extends LinkEntity {
options = {};
}

const operationTimeoutInMs =
options.retryOptions == undefined ||
Copy link
Contributor

Choose a reason for hiding this comment

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

This logic is duplicated in eventHubReceiver, and will probably be used by the receiver at some point. Could you refactor this into its own function that takes in either retryOptions or operationTimeoutInMs, and then reference this function in both places?

Copy link
Member Author

Choose a reason for hiding this comment

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

Finding a place to house a utility like that seemed a bit tricky. Updated/created one along side RetryOptions interface definition in eventHubClient file.

Moreover, this may change and all required validations would likely be done in one place as part of retry module within core-amqp eventually.

actionAfterTimeout,
Constants.defaultOperationTimeoutInSeconds * 1000
);
waitTimer = setTimeout(actionAfterTimeout, getRetryAttemptTimeoutInMs(options!.retryOptions));
Copy link
Contributor

Choose a reason for hiding this comment

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

Just curious, was the TypeScript compiler unable to tell that options is always defined?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, in the IDE I was seeing a squiggly prompt that it may be undefined..

Copy link
Contributor

Choose a reason for hiding this comment

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

@chradek Would you prefer options && options.retryOptions over options!.retryOptions.
I am aware of the knee jerk reaction we get when we see the ! :)
Was just curious about what you felt about the above alternative

Copy link
Contributor

@chradek chradek Jul 11, 2019

Choose a reason for hiding this comment

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

I actually wonder if changing

private _trySendBatch(
    message: AmqpMessage | Buffer,
    tag: any,
    options?: SendOptions & EventHubProducerOptions,
    format?: number
  ): Promise<void> {
    if (!options) {
      options = {};
    }

to

private _trySendBatch(
    message: AmqpMessage | Buffer,
    tag: any,
    options: SendOptions & EventHubProducerOptions = {},
    format?: number
  ): Promise<void> {

would solve the squiggles instead since then the compiler should see options always exists.

Edit: Though if that doesn't work, I'd choose the options && options.retryOptions route instead.

Copy link
Member Author

Choose a reason for hiding this comment

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

Updating the type had worked

@ramya0820 ramya0820 merged commit 40fe1af into Azure:master Jul 11, 2019
@ramya0820 ramya0820 changed the title [Event Hubs] Introduce operationTimeoutInMs [Event Hubs] Introduce timeoutInMs Jul 11, 2019
ramya0820 added a commit to ramya0820/azure-sdk-for-js that referenced this pull request Jul 11, 2019
ramya0820 added a commit that referenced this pull request Jul 11, 2019
* [Event Hubs] Introduce timeoutInMs on RetryOptions (#4239)

* Update event-hubs.api.md file
ramya0820 added a commit that referenced this pull request Jul 16, 2019
* [Event Hubs] Introduce timeoutInMs on RetryOptions (#4239)

* Update version in constants file
danieljurek pushed a commit that referenced this pull request Jul 24, 2019
* [Event Hubs] Introduce timeoutInMs on RetryOptions (#4239)

* Remove ENDPOINT env var

* Remove ENDPOINT var

* Update AAD env vars

* Revert "Update AAD env vars"

This reverts commit f6834cd.

* Remove ref from tests.yml
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.

4 participants