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

Normalise API int64 type across Node SDK #78

Closed
jwulf opened this issue Mar 21, 2024 · 6 comments
Closed

Normalise API int64 type across Node SDK #78

jwulf opened this issue Mar 21, 2024 · 6 comments
Assignees
Milestone

Comments

@jwulf
Copy link
Member

jwulf commented Mar 21, 2024

The JSON number value passed by the REST API for processInstanceKey (for example) is of type $int64.

This can't be reliably represented by the JavaScript number type, which is a 2^53 range floating point value.

This means that systems that are running for a long time can generate keys that cannot be represented by the SDK.

The gRPC library deals with this by parsing int64 to a string representation. Since we don't do arithmetic on keys, it might as well be a string.

The REST library that I am currently using, however, (got) represents these as number, leading to two issues:

  1. The imprecision issue that will become an L1 in production when a system hits key values that cannot be represented as the JS number type.

  2. The impedance mismatch that ZeebeGrpcClient returns long keys as type string, and the other APIs expect a number type as input; and vice versa.

I'm looking for alternative REST clients that can serialise long integer types as JavaScript string.

@jwulf jwulf self-assigned this Mar 21, 2024
@jwulf jwulf added this to the 8.5.0 milestone Mar 21, 2024
@jwulf
Copy link
Member Author

jwulf commented Mar 21, 2024

OK, got supports custom JSON parse/stringify functions:

https://github.com/sindresorhus/got/blob/main/documentation/2-options.md#parsejson

This library could be used:

https://github.com/josdejong/lossless-json

@jwulf
Copy link
Member Author

jwulf commented Mar 21, 2024

Hmmm, OK. I got it working. I can use a custom JSON parser with got to turn all numbers into LosslessNumbers.

ZeebeGrpc returns int64 types as type string, and leaves int32 numbers as number. This is consistent, and it is based on introspection of the protocol.

We can't detect the type of the field over REST. We know it is a number, but we don't know if it is an int32 or int64 field from the data itself.

I could encode this in the typing of the Dtos and use intellisense to determine whether the LosslessNumber should be marshalled to a string or to a number.

Going back the other way does not seem to be a problem.

Let me check if an API that takes an int64 number can accept a string. That could be a problem for the intellisense approach, because then we have two contracts to enforce - one with the API and the other with the application code.

@jwulf
Copy link
Member Author

jwulf commented Mar 21, 2024

REST fields that take an int64 can take a string.

So, how can we emulate the behaviour of the ZeebeGrpcClient, and marshal int64 values to string and int32 values to number?

There must be an I/O boundary library that allows you to define the schema and that generates both the Dto typings and the runtime serialisers. I'll look at that tomorrow.

Maybe this? https://github.com/JohnWeisz/TypedJSON

Or this? https://github.com/colinhacks/zod

@jwulf
Copy link
Member Author

jwulf commented Mar 21, 2024

OK, I have an approach for this.

A custom JSON parser that uses lossless-json to parse all JSON number types to a LosslessNumber.

The custom parser takes as an argument a Dto class. The class has decorated properties. The custom parser introspects the class and reads the type:Int32 and type:Int64 annotations, then uses those to convert the LosslessNumber to either a JS number or a JS string.

The class thus acts as both the metadata for the parser, via decorators on a Dto class, and also the type information for the consumer via the class interface.

@jwulf
Copy link
Member Author

jwulf commented Mar 21, 2024

I've extended this to deal with nested Dtos.

It's in lib/LosslessJsonParser.ts

@jwulf
Copy link
Member Author

jwulf commented Mar 28, 2024

This feature is now complete.

All known int64 type values are parsed to a JavaScript string type.

With unknown value types that come in via JSON number values, they are parsed to number unless they contain an unsafe int64 value, in which case the parser throws an exception.

A mapping Dto class can be provided that specifies mapping a JSON number field to either a string or bigint type. The parser will map the number value to this type, and the stringify function will do the reverse mapping.

@jwulf jwulf closed this as completed Mar 28, 2024
github-actions bot pushed a commit that referenced this issue Apr 4, 2024
# [8.5.0-alpha.1](v8.4.0...v8.5.0-alpha.1) (2024-04-04)

### Features

* **oauth:** support optional scope in OAuth request ([#25](#25)) ([0451b80](0451b80))
* **operate:** add multitenant support and lossless Json parsing ([#82](#82)) ([cf49a71](cf49a71)), closes [#78](#78) [#67](#67)
* **repo:** add enhanced debug output for http errors ([#88](#88)) ([881b039](881b039)), closes [#87](#87)
* **tasklist:** add multitenant support to tasklist ([#85](#85)) ([46bb564](46bb564))
* **zeebe:** add MigrateProcessInstance ([#97](#97)) ([2a9a123](2a9a123)), closes [#49](#49)
* **zeebe:** implement deleteResource ([#73](#73)) ([0cd08b7](0cd08b7))
* **zeebe:** implement lossless parsing of job payload ([#95](#95)) ([57f3ea8](57f3ea8)), closes [#81](#81)
* **zeebe:** normalise useragent, thread config ([#94](#94)) ([c1c4211](c1c4211))
* **zeebe:** remove deployProcess method ([#71](#71)) ([6cb98f0](6cb98f0))
jwulf added a commit that referenced this issue Apr 8, 2024
* ci(repo): create npm publish workflow (#100)

* Remove-docs (#101)

* docs(repo): remove docs

* docs(repo): add docs folder to .gitignore

* ci(repo): update publish workflow (#102)

* ci(repo): configure renovate to run against alpha branch (#103)

* ci(repo): configure renovate to run against alpha branch

* ci(repo): add workflow step to merge to alpha from main on release

* chore(release): 8.5.0-alpha.1 [skip ci]

# [8.5.0-alpha.1](v8.4.0...v8.5.0-alpha.1) (2024-04-04)

### Features

* **oauth:** support optional scope in OAuth request ([#25](#25)) ([0451b80](0451b80))
* **operate:** add multitenant support and lossless Json parsing ([#82](#82)) ([cf49a71](cf49a71)), closes [#78](#78) [#67](#67)
* **repo:** add enhanced debug output for http errors ([#88](#88)) ([881b039](881b039)), closes [#87](#87)
* **tasklist:** add multitenant support to tasklist ([#85](#85)) ([46bb564](46bb564))
* **zeebe:** add MigrateProcessInstance ([#97](#97)) ([2a9a123](2a9a123)), closes [#49](#49)
* **zeebe:** implement deleteResource ([#73](#73)) ([0cd08b7](0cd08b7))
* **zeebe:** implement lossless parsing of job payload ([#95](#95)) ([57f3ea8](57f3ea8)), closes [#81](#81)
* **zeebe:** normalise useragent, thread config ([#94](#94)) ([c1c4211](c1c4211))
* **zeebe:** remove deployProcess method ([#71](#71)) ([6cb98f0](6cb98f0))

* test(repo): skip jest global setup for unit tests (#106)


Fixes #105

* build(repo): parallelise publish workflow

* build(repo): fix parallelisation

* fix(repo): add note on "supported" (#107)

Fixes #70

* chore(release): 8.5.0-alpha.2 [skip ci]

# [8.5.0-alpha.2](v8.5.0-alpha.1...v8.5.0-alpha.2) (2024-04-05)

### Bug Fixes

* **repo:** add note on "supported" ([#107](#107)) ([fc45d61](fc45d61)), closes [#70](#70)

* fix(repo): only git commit on npm publish success

* chore(release): 8.5.0-alpha.3 [skip ci]

# [8.5.0-alpha.3](v8.5.0-alpha.2...v8.5.0-alpha.3) (2024-04-05)

### Bug Fixes

* **repo:** only git commit on npm publish success ([9012764](9012764))

* chore(release): 8.5.0-alpha.3 [skip ci]

# [8.5.0-alpha.3](v8.5.0-alpha.2...v8.5.0-alpha.3) (2024-04-05)

### Bug Fixes

* **repo:** only git commit on npm publish success ([9012764](9012764))

* build(repo): configure semantic release (#109)

fixes #108

* fix(repo): use ts-patch to transform module mapping in output (#112)

* fix(repo): use ts-patch to transform module mapping in output

fixes #110

* build(repo): add missing tsconfig-paths

* chore(release): 8.5.0-alpha.4 [skip ci]

# [8.5.0-alpha.4](v8.5.0-alpha.3...v8.5.0-alpha.4) (2024-04-05)

### Bug Fixes

* **repo:** use ts-patch to transform module mapping in output ([#112](#112)) ([7efdcf3](7efdcf3)), closes [#110](#110)

* chore(release): 8.5.0-alpha.4 [skip ci]

# [8.5.0-alpha.4](v8.5.0-alpha.3...v8.5.0-alpha.4) (2024-04-05)

### Bug Fixes

* **repo:** use ts-patch to transform module mapping in output ([#112](#112)) ([7efdcf3](7efdcf3)), closes [#110](#110)

* ci(repo): parallelise tests and use npm install in CI (#116)

fixes #115

* Jwulf/issue114 (#117)

* fix(repo): use relative paths in source

fixes #114

* test(repo): fix relative path in jest setup

* test(repo): fix relative path to zeebe

* test(repo): convert tests to relative paths

* revert(github): remove spurious commitlint config file

* fix(repo): make fix type commits release a new package

* ci(repo): wrap long lines in commit messages

* ci(repo): wrap footer lines at 100 characters in semantic-release config

* ci(repo): break commit msgs to 100 chars via husky hook

* ci(repo): disable husky during semantic-release

* chore(release): 8.5.0-alpha.5 [skip ci]

# [8.5.0-alpha.5](v8.5.0-alpha.4...v8.5.0-alpha.5) (2024-04-07)

### Bug Fixes

* **repo:** make fix type commits release a new package ([ded83cf](ded83cf))

* chore(release): 8.5.0-alpha.5 [skip ci]

# [8.5.0-alpha.5](v8.5.0-alpha.4...v8.5.0-alpha.5) (2024-04-07)

### Bug Fixes

* **repo:** make fix type commits release a new package ([ded83cf](ded83cf))

* Issue118 (#119)

* test(repo): add smoke test and type surface tests
fixes #118
* ci(repo): run smoke test in CI
* fix(camunda8): respect OAuth disabled flag

* fix(issue118): add smoke test and type surface tests

* test(repo): add smoke test and type surface tests
fixes #118
* ci(repo): run smoke test in CI
* fix(camunda8): respect OAuth disabled flag

* release(repo): trigger a new release

* chore(release): 8.5.0-alpha.6 [skip ci]

# [8.5.0-alpha.6](v8.5.0-alpha.5...v8.5.0-alpha.6) (2024-04-08)

### Bug Fixes

* **issue118:** add smoke test and type surface tests ([fe0c709](fe0c709)), closes [#118](#118)

* chore(release): 8.5.0-alpha.6 [skip ci]

# [8.5.0-alpha.6](v8.5.0-alpha.5...v8.5.0-alpha.6) (2024-04-08)

### Bug Fixes

* **issue118:** add smoke test and type surface tests ([fe0c709](fe0c709)), closes [#118](#118)

* ci(repo): add CodeQL scanning (#120)

fixes #51

---------

Co-authored-by: semantic-release-bot <semantic-release-bot@martynus.net>
github-actions bot pushed a commit that referenced this issue Apr 8, 2024
## [8.4.1](v8.4.0...v8.4.1) (2024-04-08)

### Features

* **oauth:** support optional scope in OAuth request ([#25](#25)) ([0451b80](0451b80))
* **operate:** add multitenant support and lossless Json parsing ([#82](#82)) ([cf49a71](cf49a71)), closes [#78](#78) [#67](#67)
* **repo:** add enhanced debug output for http errors ([#88](#88)) ([881b039](881b039)), closes [#87](#87)
* **tasklist:** add multitenant support to tasklist ([#85](#85)) ([46bb564](46bb564))
* **zeebe:** add MigrateProcessInstance ([#97](#97)) ([2a9a123](2a9a123)), closes [#49](#49)
* **zeebe:** implement deleteResource ([#73](#73)) ([0cd08b7](0cd08b7))
* **zeebe:** implement lossless parsing of job payload ([#95](#95)) ([57f3ea8](57f3ea8)), closes [#81](#81)
* **zeebe:** normalise useragent, thread config ([#94](#94)) ([c1c4211](c1c4211))
* **zeebe:** remove deployProcess method ([#71](#71)) ([6cb98f0](6cb98f0))
github-actions bot pushed a commit that referenced this issue Apr 8, 2024
## [8.4.1](v8.4.0...v8.4.1) (2024-04-08)

### Features

* **oauth:** support optional scope in OAuth request ([#25](#25)) ([0451b80](0451b80))
* **operate:** add multitenant support and lossless Json parsing ([#82](#82)) ([cf49a71](cf49a71)), closes [#78](#78) [#67](#67)
* **repo:** add enhanced debug output for http errors ([#88](#88)) ([881b039](881b039)), closes [#87](#87)
* **tasklist:** add multitenant support to tasklist ([#85](#85)) ([46bb564](46bb564))
* **zeebe:** add MigrateProcessInstance ([#97](#97)) ([2a9a123](2a9a123)), closes [#49](#49)
* **zeebe:** implement deleteResource ([#73](#73)) ([0cd08b7](0cd08b7))
* **zeebe:** implement lossless parsing of job payload ([#95](#95)) ([57f3ea8](57f3ea8)), closes [#81](#81)
* **zeebe:** normalise useragent, thread config ([#94](#94)) ([c1c4211](c1c4211))
* **zeebe:** remove deployProcess method ([#71](#71)) ([6cb98f0](6cb98f0))
jwulf added a commit that referenced this issue Apr 8, 2024
* Release 8.5.0 (#124)

* ci(repo): create npm publish workflow (#100)

* Remove-docs (#101)

* docs(repo): remove docs

* docs(repo): add docs folder to .gitignore

* ci(repo): update publish workflow (#102)

* ci(repo): configure renovate to run against alpha branch (#103)

* ci(repo): configure renovate to run against alpha branch

* ci(repo): add workflow step to merge to alpha from main on release

* chore(release): 8.5.0-alpha.1 [skip ci]

# [8.5.0-alpha.1](v8.4.0...v8.5.0-alpha.1) (2024-04-04)

### Features

* **oauth:** support optional scope in OAuth request ([#25](#25)) ([0451b80](0451b80))
* **operate:** add multitenant support and lossless Json parsing ([#82](#82)) ([cf49a71](cf49a71)), closes [#78](#78) [#67](#67)
* **repo:** add enhanced debug output for http errors ([#88](#88)) ([881b039](881b039)), closes [#87](#87)
* **tasklist:** add multitenant support to tasklist ([#85](#85)) ([46bb564](46bb564))
* **zeebe:** add MigrateProcessInstance ([#97](#97)) ([2a9a123](2a9a123)), closes [#49](#49)
* **zeebe:** implement deleteResource ([#73](#73)) ([0cd08b7](0cd08b7))
* **zeebe:** implement lossless parsing of job payload ([#95](#95)) ([57f3ea8](57f3ea8)), closes [#81](#81)
* **zeebe:** normalise useragent, thread config ([#94](#94)) ([c1c4211](c1c4211))
* **zeebe:** remove deployProcess method ([#71](#71)) ([6cb98f0](6cb98f0))

* test(repo): skip jest global setup for unit tests (#106)


Fixes #105

* build(repo): parallelise publish workflow

* build(repo): fix parallelisation

* fix(repo): add note on "supported" (#107)

Fixes #70

* chore(release): 8.5.0-alpha.2 [skip ci]

# [8.5.0-alpha.2](v8.5.0-alpha.1...v8.5.0-alpha.2) (2024-04-05)

### Bug Fixes

* **repo:** add note on "supported" ([#107](#107)) ([fc45d61](fc45d61)), closes [#70](#70)

* fix(repo): only git commit on npm publish success

* chore(release): 8.5.0-alpha.3 [skip ci]

# [8.5.0-alpha.3](v8.5.0-alpha.2...v8.5.0-alpha.3) (2024-04-05)

### Bug Fixes

* **repo:** only git commit on npm publish success ([9012764](9012764))

* chore(release): 8.5.0-alpha.3 [skip ci]

# [8.5.0-alpha.3](v8.5.0-alpha.2...v8.5.0-alpha.3) (2024-04-05)

### Bug Fixes

* **repo:** only git commit on npm publish success ([9012764](9012764))

* build(repo): configure semantic release (#109)

fixes #108

* fix(repo): use ts-patch to transform module mapping in output (#112)

* fix(repo): use ts-patch to transform module mapping in output

fixes #110

* build(repo): add missing tsconfig-paths

* chore(release): 8.5.0-alpha.4 [skip ci]

# [8.5.0-alpha.4](v8.5.0-alpha.3...v8.5.0-alpha.4) (2024-04-05)

### Bug Fixes

* **repo:** use ts-patch to transform module mapping in output ([#112](#112)) ([7efdcf3](7efdcf3)), closes [#110](#110)

* chore(release): 8.5.0-alpha.4 [skip ci]

# [8.5.0-alpha.4](v8.5.0-alpha.3...v8.5.0-alpha.4) (2024-04-05)

### Bug Fixes

* **repo:** use ts-patch to transform module mapping in output ([#112](#112)) ([7efdcf3](7efdcf3)), closes [#110](#110)

* ci(repo): parallelise tests and use npm install in CI (#116)

fixes #115

* Jwulf/issue114 (#117)

* fix(repo): use relative paths in source

fixes #114

* test(repo): fix relative path in jest setup

* test(repo): fix relative path to zeebe

* test(repo): convert tests to relative paths

* revert(github): remove spurious commitlint config file

* fix(repo): make fix type commits release a new package

* ci(repo): wrap long lines in commit messages

* ci(repo): wrap footer lines at 100 characters in semantic-release config

* ci(repo): break commit msgs to 100 chars via husky hook

* ci(repo): disable husky during semantic-release

* chore(release): 8.5.0-alpha.5 [skip ci]

# [8.5.0-alpha.5](v8.5.0-alpha.4...v8.5.0-alpha.5) (2024-04-07)

### Bug Fixes

* **repo:** make fix type commits release a new package ([ded83cf](ded83cf))

* chore(release): 8.5.0-alpha.5 [skip ci]

# [8.5.0-alpha.5](v8.5.0-alpha.4...v8.5.0-alpha.5) (2024-04-07)

### Bug Fixes

* **repo:** make fix type commits release a new package ([ded83cf](ded83cf))

* Issue118 (#119)

* test(repo): add smoke test and type surface tests
fixes #118
* ci(repo): run smoke test in CI
* fix(camunda8): respect OAuth disabled flag

* fix(issue118): add smoke test and type surface tests

* test(repo): add smoke test and type surface tests
fixes #118
* ci(repo): run smoke test in CI
* fix(camunda8): respect OAuth disabled flag

* release(repo): trigger a new release

* chore(release): 8.5.0-alpha.6 [skip ci]

# [8.5.0-alpha.6](v8.5.0-alpha.5...v8.5.0-alpha.6) (2024-04-08)

### Bug Fixes

* **issue118:** add smoke test and type surface tests ([fe0c709](fe0c709)), closes [#118](#118)

* chore(release): 8.5.0-alpha.6 [skip ci]

# [8.5.0-alpha.6](v8.5.0-alpha.5...v8.5.0-alpha.6) (2024-04-08)

### Bug Fixes

* **issue118:** add smoke test and type surface tests ([fe0c709](fe0c709)), closes [#118](#118)

* ci(repo): add CodeQL scanning (#120)

fixes #51

---------

Co-authored-by: semantic-release-bot <semantic-release-bot@martynus.net>

* release: trigger a new release

* chore(release): 8.4.1 [skip ci]

## [8.4.1](v8.4.0...v8.4.1) (2024-04-08)

### Features

* **oauth:** support optional scope in OAuth request ([#25](#25)) ([0451b80](0451b80))
* **operate:** add multitenant support and lossless Json parsing ([#82](#82)) ([cf49a71](cf49a71)), closes [#78](#78) [#67](#67)
* **repo:** add enhanced debug output for http errors ([#88](#88)) ([881b039](881b039)), closes [#87](#87)
* **tasklist:** add multitenant support to tasklist ([#85](#85)) ([46bb564](46bb564))
* **zeebe:** add MigrateProcessInstance ([#97](#97)) ([2a9a123](2a9a123)), closes [#49](#49)
* **zeebe:** implement deleteResource ([#73](#73)) ([0cd08b7](0cd08b7))
* **zeebe:** implement lossless parsing of job payload ([#95](#95)) ([57f3ea8](57f3ea8)), closes [#81](#81)
* **zeebe:** normalise useragent, thread config ([#94](#94)) ([c1c4211](c1c4211))
* **zeebe:** remove deployProcess method ([#71](#71)) ([6cb98f0](6cb98f0))

* chore(release): 8.4.1 [skip ci]

## [8.4.1](v8.4.0...v8.4.1) (2024-04-08)

### Features

* **oauth:** support optional scope in OAuth request ([#25](#25)) ([0451b80](0451b80))
* **operate:** add multitenant support and lossless Json parsing ([#82](#82)) ([cf49a71](cf49a71)), closes [#78](#78) [#67](#67)
* **repo:** add enhanced debug output for http errors ([#88](#88)) ([881b039](881b039)), closes [#87](#87)
* **tasklist:** add multitenant support to tasklist ([#85](#85)) ([46bb564](46bb564))
* **zeebe:** add MigrateProcessInstance ([#97](#97)) ([2a9a123](2a9a123)), closes [#49](#49)
* **zeebe:** implement deleteResource ([#73](#73)) ([0cd08b7](0cd08b7))
* **zeebe:** implement lossless parsing of job payload ([#95](#95)) ([57f3ea8](57f3ea8)), closes [#81](#81)
* **zeebe:** normalise useragent, thread config ([#94](#94)) ([c1c4211](c1c4211))
* **zeebe:** remove deployProcess method ([#71](#71)) ([6cb98f0](6cb98f0))

---------

Co-authored-by: semantic-release-bot <semantic-release-bot@martynus.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: ✅ Done
Development

No branches or pull requests

1 participant