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] Time duration type change from ISO-8601 "string" to "number" #9430

Closed

Conversation

HarshaNalluru
Copy link
Member

@HarshaNalluru HarshaNalluru commented Jun 10, 2020

Issue - #9375

Attributes that follow ISO-8601 time duration format (string type)

  • autoDeleteOnIdle
  • defaultMessageTtl
  • duplicateDetectionHistoryTimeWindow
  • lockDuration

This PR attempts to change the type to "number" with the time duration in seconds.
With that, "InSeconds" suffix would be added at the end of those four attributes.

Please provide reviews and let's finalize on the attributes.

@HarshaNalluru
Copy link
Member Author

/azp run js - servicebus - tests

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@HarshaNalluru HarshaNalluru marked this pull request as ready for review June 10, 2020 23:36
@@ -228,7 +228,7 @@ export interface PeekMessagesOptions extends OperationOptions {
// @public
export interface QueueDescription {
authorizationRules?: AuthorizationRule[];
autoDeleteOnIdle?: string;
autoDeleteOnIdleInSeconds?: number;
Copy link
Contributor

Choose a reason for hiding this comment

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

Wasnt the guidance to use milli seconds in general in our JS SDKs? What data type are other languages using?

Copy link
Member Author

Choose a reason for hiding this comment

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

I did think of it, but usual values for this would be in "days", did not make much sense to convert days into milliseconds.

Copy link
Member Author

@HarshaNalluru HarshaNalluru Jun 15, 2020

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

It seems fine to me to use seconds for 2 reasons:

  1. I think the ISO 8601 duration format only goes down to the second precision (though it does allow fractional seconds.)
  2. arm-servicebus has these properties as well (without the InSeconds suffix) as strings. If the fields are named differently, then I think there will be less confusion about why one package returns a string and another returns a number.

Copy link
Contributor

Choose a reason for hiding this comment

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

Assuming that these properties need to work with larger timeframes like years to smaller values of seconds, are we sure that dealing with numbers is indeed more user friendly than using the ISO-8601 format?

One requires to do math, the other requires prior knowledge of ISO-8601 format.

Given that arm package will not be changing, is it worthwhile having separate treatment of these properties?

Copy link
Member Author

Choose a reason for hiding this comment

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

One requires to do math, the other requires prior knowledge of ISO-8601 format.

I had the same dilemma while porting the tests in this PR.

are we sure that dealing with numbers is indeed more user friendly than using the ISO-8601 format?

I would prefer ISO-8601 duration format over numbers. I don't know if it is conventional or convenient for the users.
If we prefer ISO-8601 duration format, we can add the ISO_8601#Durations link in the docs for all the attributes that take ISO-8601 string inputs.
This would also be consistent with the arm package.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, I assumed that this had already been decided in an API review. If not then I'm also fine with keeping it as a string. When we get Temporal we can look at supporting that in the future.

Copy link
Contributor

Choose a reason for hiding this comment

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

The call to change this was quickly made in the .Net review, but I believe that was because they have a very convenient class Duration that is more user friendly than the ISO format.

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

After reflecting on this a bit more, it might be best to leave these as ISO strings until we get a better duration primitive to work with in JS.

sdk/servicebus/service-bus/review/service-bus.api.md Outdated Show resolved Hide resolved
@HarshaNalluru
Copy link
Member Author

/azp run js - servicebus - tests

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@HarshaNalluru
Copy link
Member Author

https://dev.azure.com/azure-sdk/internal/_build/results?buildId=427839&view=results

Green on Linux Node 8, Windows Node 10.
Failed on Mac Node 12 and on the browser with totally unrelated test failures.

@HarshaNalluru
Copy link
Member Author

/azp run js - servicebus - tests

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

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.

Looks good.

autoDeleteOnIdle: "P10675199DT2H48M5.4775807S",
defaultMessageTtl: "P10675199DT2H48M5.4775807S",
duplicateDetectionHistoryTimeWindow: "PT10M",
autoDeleteOnIdleInSeconds: 10675199 * 24 * 60 * 60 + 2 * 60 * 60 + 48 * 60 + 5.4775807, //"P10675199DT2H48M5.4775807S",
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm having a hard time telling...do the atomManagement tests actually test that a response with the string duration is deserialized into the correct number?

Copy link
Member Author

@HarshaNalluru HarshaNalluru Jun 18, 2020

Choose a reason for hiding this comment

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

These tests have historically been testing the response with the expected hard-coded output, my intention was just to migrate to the new type.

do the atomManagement tests actually test that a response with the string duration is deserialized into the correct number?

Not exactly, I have added separate unit tests for that - "string duration is deserialized into the correct number".

For this test, we do verify the response by matching it with this predefined output.
The response would contain the iso-8601 duration converted into seconds.
If the number from the response matches with the number here in the predefined output, the test would succeed and I would assume the string duration is deserialized into the correct number.

Copy link
Member

@xirzec xirzec left a comment

Choose a reason for hiding this comment

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

Some minor comments and some confusion on my end

export function getISO8601DurationFromSeconds(
timeInSeconds: number | undefined
): string | undefined {
if (timeInSeconds == null) {
Copy link
Member

Choose a reason for hiding this comment

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

can we make this more explicit?

Suggested change
if (timeInSeconds == null) {
if (timeInSeconds === undefined || timeInSeconds === null) {

Copy link
Member

Choose a reason for hiding this comment

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

This is interesting - why would we want to expand it? I was under the impression this was good practice?

https://basarat.gitbook.io/typescript/recap/null-undefined

Copy link
Member

Choose a reason for hiding this comment

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

Many developers are not familiar with the subtleties of non-strict comparisons, so they are often banned by lint rules. It's also easy to not notice a missing extra =.

Copy link
Member

Choose a reason for hiding this comment

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

And if you want to take it from Anders, we shouldn't ever use null in our code since it's not required by the language, but I'm not that much of a purist as to avoid it for use in sentinel values. ;)

Copy link
Member Author

Choose a reason for hiding this comment

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

Interesting.
timeInSeconds === undefined || timeInSeconds === null

To handle both null and undefined, we have been doing timeInSeconds == undefined check at other places.

if (timeInSeconds == null) {
return undefined;
}
if (typeof timeInSeconds != "number") {
Copy link
Member

Choose a reason for hiding this comment

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

nit: !==

if (timeInSeconds == null) {
return undefined;
}
if (typeof timeInSeconds != "number") {
Copy link
Member

Choose a reason for hiding this comment

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

what about if timeInSeconds is NaN? Or some other special value like Infinity?

let timeSeparatorAdded = false;
for (const { label, inSeconds } of [day, hour, minute, second]) {
const value =
label == second.label
Copy link
Member

Choose a reason for hiding this comment

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

nit: another non-strict comparison

const minute = { label: "M", inSeconds: 60 };
const hour = { label: "H", inSeconds: minute.inSeconds * 60 };
const day = { label: "D", inSeconds: hour.inSeconds * 24 };
const countDecimals =
Copy link
Member

Choose a reason for hiding this comment

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

I'm not really sure why we get how many decimal values there are, just to call toFixed of that value later. Are we trying to truncate it in a way that avoids floating point issues?

What's the case where this isn't true?

timeInSeconds.toString() === timeInSeconds.toFixed(timeInSeconds.toString().split(".")[1].length)

* Example: PT10M, P106DT2H48M5.47S
*
* This helper method is to convert the duration in seconds to ISO-8601 duration format.
*
Copy link
Member

Choose a reason for hiding this comment

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

Can we mention here that we don't support weeks/months/years because the service doesn't send that?

Copy link
Member Author

Choose a reason for hiding this comment

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

Good point. I've added it in the comments for one of the methods, I'll add it in the docs too.

* Example: PT10M, P106DT2H48M5.47S
*
* This helper method is to convert the duration in ISO-8601 format into seconds.
*
Copy link
Member

Choose a reason for hiding this comment

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

again a reference to not supporting years/months/weeks would be good

@HarshaNalluru
Copy link
Member Author

Waiting for #9430 (comment) discussion to be addressed to decide the fate of the PR.. either addressing the rest of the feedback and merge or discarding the PR.

@HarshaNalluru
Copy link
Member Author

Closing in favour of #9723

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

Successfully merging this pull request may close these issues.

5 participants