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

[Service Bus] Allow timeout lesser than 60 seconds #8805

Merged
merged 16 commits into from
May 20, 2020

Conversation

HarshaNalluru
Copy link
Member

@HarshaNalluru HarshaNalluru commented May 8, 2020

Removed the getRetryAttemptTimeoutInMs from service-bus, made necessary changes at the SBC level itself.
Updated event-hubs' getRetryAttemptTimeoutInMs to be in sync with the new proposal.
Invalid and non-positive values default to the defaultOperationTimeout

@@ -26,6 +26,27 @@ function isDelivery(obj: any): boolean {
return result;
}

/**
* TODO: We should question whether it's even a legitimate way of setting the timeout
Copy link
Member

Choose a reason for hiding this comment

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

A faithful port, even of the TODO comment questioning the legitimacy of the function. ;)

* @param {(RetryOptions | undefined)} retryOptions
* @returns {number}
*/
export function getRetryAttemptTimeoutInMs(retryOptions: RetryOptions | undefined): number {
Copy link
Member

Choose a reason for hiding this comment

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

Are we just going to remove this function anyways though when you go through and obliterate the "must be 60 seconds or less"? Ie, should we just not bother doing this so we don't have to re-release core-amqp?

Copy link
Member

@richardpark-msft richardpark-msft left a comment

Choose a reason for hiding this comment

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

Do we even need to bother with this? I think you have another issue that will obviate this entire function's existence.

typeof retryOptions.timeoutInMs !== "number" ||
!isFinite(retryOptions.timeoutInMs) ||
// TODO: not sure what the justification is for always forcing at least 60 seconds.
retryOptions.timeoutInMs < Constants.defaultOperationTimeoutInMs
Copy link
Contributor

Choose a reason for hiding this comment

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

Now that we have decided to not put a min value of 60 seconds, the only thing we are doing is to replace invalid values with the default value. In most places before we get to using getRetryAttemptTimeoutInMs, we would have already defaulted to {} if there was no retry options. So, the invalid values being referred to are

  • not being a number
  • not being finite
  • not being 0 or less

Can we not make these checks in one single place i.e when user creates ServiceBusClient and remove the need for the helper altogether?

If we are going to have a helper method for this, then shouldnt other properties in the retry options also get that treatment?

Currently we dont, because the retry() method takes care of using the right defaults and timeout is the only retry option that is used outside of the retry() method.

What am getting to is that by looking at what is exposed from core-amqp, it is not clear why timeout is the special one that needs special handling.

Copy link
Member Author

@HarshaNalluru HarshaNalluru May 12, 2020

Choose a reason for hiding this comment

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

Can we not make these checks in one single place i.e when user creates ServiceBusClient and remove the need for the helper altogether?

Just did that for service-bus.

What am getting to is that by looking at what is exposed from core-amqp, it is not clear why timeout is the special one that needs special handling.

Un-done changes to core-amqp

@HarshaNalluru HarshaNalluru changed the title [Core AMQP] De-duplicating getRetryAttemptTimeoutInMs helper method [Core AMQP] Fix getRetryAttemptTimeoutInMs helper method May 12, 2020
* @internal
* @ignore
*/
export function normalizeRetryOptions(
Copy link
Member Author

Choose a reason for hiding this comment

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

Since this was already done at SBC level, I see no point in keeping it now.

@HarshaNalluru HarshaNalluru changed the title [Core AMQP] Fix getRetryAttemptTimeoutInMs helper method [Service Bus] Remove getRetryAttemptTimeoutInMs helper method May 12, 2020
@ramya-rao-a ramya-rao-a changed the title [Service Bus] Remove getRetryAttemptTimeoutInMs helper method [Service Bus][Event Hubs] Allow timeout lesser than 60 seconds May 13, 2020
@ramya-rao-a
Copy link
Contributor

Fixes #8193

this._clientOptions.retryOptions
);

// Invalid timeouts, non-positive timeouts are defaulted to the `Constants.defaultOperationTimeoutInMs`
Copy link
Member

Choose a reason for hiding this comment

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

Why is it that we don't just throw an Error?

// Invalid timeouts, non-positive timeouts are defaulted to the `Constants.defaultOperationTimeoutInMs`
const timeoutInMs = this._clientOptions.retryOptions.timeoutInMs;
this._clientOptions.retryOptions.timeoutInMs =
typeof timeoutInMs !== "number" || !isFinite(timeoutInMs) || timeoutInMs <= 0
Copy link
Member

Choose a reason for hiding this comment

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

Why would zero have to be mapped? It's valid?

Copy link
Member

@richardpark-msft richardpark-msft left a comment

Choose a reason for hiding this comment

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

This looks fine to me. I feel a little bit odd that we remap zero but I think it makes sense in that it's more like "0 is basically the uninitialized state, and should just use a default value".

It does seem like we should just throw in the face of other bogus input, however.

@ramya-rao-a
Copy link
Contributor

Based on offline discussions, the decision is to throw errors when the timeout value is 0 or -ve value

@ramya-rao-a
Copy link
Contributor

But now, would that be a breaking change? As someone passing -ve or 0 to event hubs would now get an error from the next update :(

@HarshaNalluru
Copy link
Member Author

But now, would that be a breaking change?

Only update service-bus to throw errors for the invalid timeouts and leave event-hubs as it is, take care of event-hubs at the next major update?

if (typeof timeoutInMs !== "number" || !isFinite(timeoutInMs) || timeoutInMs <= 0) {
throw new Error(`${timeoutInMs} is an invalid value for retryOptions.timeoutInMs`);
}
this._clientOptions.retryOptions.timeoutInMs = timeoutInMs;
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we have to set the timeout to the default value here? This forces us to use ! every time we want to use retryOptions.timeoutInMs in all other places.

Since the interface allows the timeout to not be set at all, I would suggest that we only do the error check here and copy over the timeoutInMs == undefined ? Constants.defaultOperationTimeoutInMs : timeoutInMs; to each place where the timeout is 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.

Updated messageSender with this, the other methods already have this. And thus avoided ! at all the places.

Copy link
Contributor

Choose a reason for hiding this comment

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

So, now that all consumers of retry options will check for undefined and fallback to the default value, do you need the above where you set this._clientOptions.retryOptions.timeoutInMs?

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah, if the timeout is undefined, typeof timeoutInMs !== "number" will be satisfied and an error is thrown. I thought it to be an overkill to allow undefined by placing more guards.

Copy link
Contributor

Choose a reason for hiding this comment

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

Then add the timeout != undefined to your if check

if (timeout != undefined && (typeof timeoutInMs !== "number" || !isFinite(timeoutInMs) || timeoutInMs <= 0))

Copy link
Member Author

Choose a reason for hiding this comment

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

Done!!

@@ -327,7 +327,7 @@ export class MessageSender extends LinkEntity {
if (this._sender!.sendable()) {
try {
this._sender!.sendTimeoutInSeconds =
(this._retryOptions.timeoutInMs - timeTakenByInit) / 1000;
(this._retryOptions.timeoutInMs! - timeTakenByInit) / 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 #8685, we added a guard to ensure this does not result in -ve value in Event Hubs. Can we include that in this PR for Service Bus

Copy link
Member Author

Choose a reason for hiding this comment

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

Added

@ramya-rao-a
Copy link
Contributor

ramya-rao-a commented May 18, 2020

Only update service-bus to throw errors for the invalid timeouts and leave event-hubs as it is, take care of event-hubs at the next major update?

That is fine by me, but in that case lets not make any changes to Event Hubs at all in this PR

@HarshaNalluru HarshaNalluru changed the title [Service Bus][Event Hubs] Allow timeout lesser than 60 seconds [Service Bus] Allow timeout lesser than 60 seconds May 18, 2020
Co-authored-by: Ramya Rao <ramya.rao.a@outlook.com>
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