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

feat!: throw error with out of bounds integer values instead of truncating, add custom 'integerValue' type cast option #488

Closed
wants to merge 22 commits into from

Conversation

AVaksman
Copy link
Contributor

@AVaksman AVaksman commented Sep 5, 2019

Fixes #147

  • Tests and linter pass
  • Code coverage does not decrease (if any source code was changed)
  • Appropriate docs were updated (if necessary)

As per discussion, implementation follows design in the document

  • On default detect if value is out of bounds of Number
  • Allow user to pass a custom typeCastFunction to be used to convert integer values
    • Give user an option to specify property names to be converted by typeCastFunction

@googlebot googlebot added the cla: yes This human has signed the Contributor License Agreement. label Sep 5, 2019
@AVaksman AVaksman changed the title feat: throw error with out of bounds integer values, add custom 'integerValue' type cast option (BREAKING CHANGE) feat: throw error with out of bounds integer values, add custom 'integerValue' type cast option Sep 5, 2019
@codecov
Copy link

codecov bot commented Sep 5, 2019

Codecov Report

Merging #488 into master will increase coverage by 0.04%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #488      +/-   ##
==========================================
+ Coverage   98.22%   98.27%   +0.04%     
==========================================
  Files           6        6              
  Lines         734      753      +19     
  Branches      172      178       +6     
==========================================
+ Hits          721      740      +19     
  Misses          2        2              
  Partials       11       11
Impacted Files Coverage Δ
src/query.ts 95.83% <ø> (ø) ⬆️
src/entity.ts 98.76% <100%> (+0.07%) ⬆️
src/request.ts 99.54% <100%> (ø) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 3022c65...4b7cb3e. Read the comment docs.

@AVaksman AVaksman added the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Sep 5, 2019
@kokoro-team kokoro-team removed the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Sep 5, 2019
@AVaksman AVaksman added the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Sep 5, 2019
@kokoro-team kokoro-team removed the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Sep 5, 2019
@AVaksman AVaksman marked this pull request as ready for review September 5, 2019 15:47
@bcoe bcoe changed the title (BREAKING CHANGE) feat: throw error with out of bounds integer values, add custom 'integerValue' type cast option feat!: throw error with out of bounds integer values, add custom 'integerValue' type cast option Sep 5, 2019
@bcoe
Copy link
Contributor

bcoe commented Sep 5, 2019

@crwilcox were we comfortable with making this a major release of datastore? I know we're trying to keep major bumps infrequent, but this seems like a reasonably useful refactor to consider one.

Copy link
Contributor

@callmehiphop callmehiphop left a comment

Choose a reason for hiding this comment

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

So just a general note, I didn't realize that the type cast function would only apply to integers. Not sure if I missed a separate conversation leading to this PR, but I think this would be useful for all data types, not just integers.

src/entity.ts Outdated Show resolved Hide resolved
@AVaksman
Copy link
Contributor Author

AVaksman commented Sep 6, 2019

So just a general note, I didn't realize that the type cast function would only apply to integers. Not sure if I missed a separate conversation leading to this PR, but I think this would be useful for all data types, not just integers.

My logic here is, that library doesn't have an issue with correctly obtaining all other value types and if any conversions/manipulations are required, the user can do them after getting the values from this library.

With regards to numeric types there is an issue of obtaining accurate large integer values.

Another point is, I wouldn't want to incorporate third party code more than I have to. Not to subjugate the library to performance impact, bugs, etc... from third party.

@callmehiphop
Copy link
Contributor

@AVaksman makes sense, I might be bikeshedding but if this only applies to integers we might want to revisit the name? Though if no one else feels the same way I don't feel super strongly about it 😄

@AVaksman
Copy link
Contributor Author

AVaksman commented Sep 9, 2019

Refactored to
typeCastConfig => integerTypeCastOptions
typeCastFunction => integerTypeCastFunction

Copy link
Contributor

@JustinBeckwith JustinBeckwith left a comment

Choose a reason for hiding this comment

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

Based on the PR description, I can't really figure out what the breaking change is. Can you add a really clear message in there for the release notes, including before code and after code?

@AVaksman
Copy link
Contributor Author

Based on the PR description, I can't really figure out what the breaking change is. Can you add a really clear message in there for the release notes, including before code and after code?

The breaking part is that now in case of integerValue is out of bounds of Number the API will throw an error instead of truncating the value as before.

Users who needed to accurately obtain out of bounds integer values, couldn't. So they probably didn't use this functionality, hence practically speaking this is not breaking change.

@AVaksman AVaksman changed the title feat!: throw error with out of bounds integer values, add custom 'integerValue' type cast option feat!: throw error with out of bounds integer values instead of truncating, add custom 'integerValue' type cast option Sep 12, 2019
@@ -372,7 +435,7 @@ export namespace entity {
}

case 'integerValue': {
return Number(value);
return decodeIntegerValue(valueProto, integerTypeCastOptions);
Copy link
Contributor

Choose a reason for hiding this comment

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

This is definitely a more robust option, but was just returning the DS.Int type considered?

Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry, I mixed up Datastore's "Int" with Spanner's: https://github.com/googleapis/nodejs-spanner/blob/f8ad0ece28e99dd9c6d7e985de56bd1b376f4712/src/codec.ts#L139 -- for simplicity's sake, would it be worth considering using that format instead? When a value is out of bounds, it will throw. The value is accessible via the "value" property in string form.

Copy link
Contributor Author

@AVaksman AVaksman Sep 12, 2019

Choose a reason for hiding this comment

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

  • I do like the ability to still access the value in string form without extra network call in case of value is out of balance.
  • it will definitely be a breaking change.
  • IMO it will add complexity to the user's code.
    will need to try=>catch for valueOf and if error still pass the value to custom typeCastFunction.
  • Is it overkill to combine these two approaches?
    • return Spanner's style object for integerValue.
    • for valueOf on default throw in case of out of bounds.
    • able to pass integerTypeCastFunction and valueOf will return the custom function result.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

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

  • I do like the ability to still access the value in string form without extra network call in case of value is out of balance.

Sorry if I misunderstand. Neither of the solutions make an extra network call, do they?

  • it will definitely be a breaking change.

I think the throwing behavior is identical to what is in this PR. It will first try to just use it as a number, but if it's out of bounds when called upon, it throws. Or, is it because the new "Int" wrapper isn't technically a Number? Lots of gray area in determining a breaking change 😕

  • Is it overkill to combine these two approaches?

I quite like that approach! Maybe @callmehiphop has a thought on this, too.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for clearing that up for me! For the Number vs customer "Int" type issue, they can at least be used interchangeably, the only difference would be typeof checks for Number wouldn't pass... unless Int extended Number? Curious to hear other thoughts on the best way to go forward.

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 ever make progress on this, maybe in another chat?

Copy link
Contributor Author

@AVaksman AVaksman Sep 19, 2019

Choose a reason for hiding this comment

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

Quick summary
Would like to hear the thoughts on the approach

  1. Throw on default, let user pass integerTypeCastFunction (currently implemented in this PR)
  2. Return an object Integer similar to Spanner, where
    • #valueOf would try to convert to Number and throw if out of bounds
    • #value returns string representation of the value
  3. Combine tow approaches above
    • do return an Integer object
    • let user provide integerTypeCast function to be used by #valueOf
    • still return string via #value

Copy link
Contributor

Choose a reason for hiding this comment

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

My vote would go for #­3. Ping to @callmehiphop and @bcoe for more votes.

Copy link
Contributor

Choose a reason for hiding this comment

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

My vote is starting simple with option 1, as a breaking change, and we can move towards an object representation in the future, if there's good reason.

@JustinBeckwith
Copy link
Contributor

@AVaksman ah in that case - can you drop the ! from the commit title and PR title?

@AVaksman AVaksman changed the title feat!: throw error with out of bounds integer values instead of truncating, add custom 'integerValue' type cast option feat: throw error with out of bounds integer values instead of truncating, add custom 'integerValue' type cast option Sep 12, 2019
@AVaksman
Copy link
Contributor Author

Roger that

@JustinBeckwith JustinBeckwith requested review from JustinBeckwith and removed request for JustinBeckwith September 12, 2019 18:07
@JustinBeckwith JustinBeckwith dismissed their stale review September 12, 2019 18:07

deferring to others

@bcoe bcoe changed the title feat: throw error with out of bounds integer values instead of truncating, add custom 'integerValue' type cast option feat!: throw error with out of bounds integer values instead of truncating, add custom 'integerValue' type cast option Sep 16, 2019
Copy link
Contributor

@bcoe bcoe left a comment

Choose a reason for hiding this comment

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

Let's call this feature out in the README.md, specifically explaining how to setup a typecast function to avoid an out of bounds.

src/entity.ts Outdated Show resolved Hide resolved
src/entity.ts Outdated Show resolved Hide resolved
src/entity.ts Outdated Show resolved Hide resolved
src/entity.ts Outdated Show resolved Hide resolved
@BenWhitehead
Copy link
Contributor

@jkwlui Does everything look good here for you after the latest fixes?

@AVaksman
Copy link
Contributor Author

AVaksman commented Oct 2, 2019

Quick summary
Would like to hear the thoughts on the approach

  1. Throw on default, let user pass integerTypeCastFunction (currently implemented in this PR)
  2. Return an object Integer similar to Spanner, where
    • #valueOf would try to convert to Number and throw if out of bounds
    • #value returns string representation of the value
  3. Combine tow approaches above
    • do return an Integer object
    • let user provide integerTypeCast function to be used by #valueOf
    • still return string via #value

from @stephenplusplus

My vote would go for #­3.

@stephenplusplus
Copy link
Contributor

@AVaksman maybe it'll just be us deciding 😆 What is your preference?

@AVaksman
Copy link
Contributor Author

AVaksman commented Oct 3, 2019

@stephenplusplus I do like option 3 as well, @bcoe 's vote goes to # 1

@JustinBeckwith
Copy link
Contributor

@AVaksman @stephenplusplus @bcoe what's the next steps here?

@AVaksman
Copy link
Contributor Author

The next step would be to decide between approach in this PR vs #516

@stephenplusplus
Copy link
Contributor

I don't see us going back to this after where we landed in #516, so I'll just close for now to avoid any confusion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: yes This human has signed the Contributor License Agreement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Inconsistent processing of large numbers from other languages.
9 participants