-
Notifications
You must be signed in to change notification settings - Fork 104
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!: Custom data converter #477
Conversation
… WorkerOptions.dataConverterPath (temporalio#430)"" This reverts commit 139550d.
export interface DataConverter { payloadConverterPath?: string; payloadCodec?: PayloadCodec; } export interface PayloadConverter { toPayload<T>(value: T): Payload; fromPayload<T>(payload: Payload): T; } export interface PayloadCodec { encode(payloads: Payload[]): Promise<Payload[]>; decode(payloads: Payload[]): Promise<Payload[]>; }
"@temporalio/workflow-common": "file:../workflow-common" | ||
}, | ||
"devDependencies": { | ||
"@temporalio/proto": "file:../proto" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this a dev dependency now? Is it even a dependency anymore?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added as devDep because we import type { coresdk }
in a few places in this package
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be a non dev dependency if we export any of those types or anything that uses those types (e.g. function signatures), to be safe, let's make it non dev.
docs/protobuf-libraries.md
Outdated
|
||
- Most popular lib (5M downloads/wk) | ||
- Fairly inactive maintainers (infrequent updates, many open PRs & issues) | ||
- Non-standard JSON serialization |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What makes it non-standard? I expect every message class to have a toJSON method (which I believe is basically toObject + JSON.stringify
) and a fromObject which can be used after JSON.parse
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Every class has a toJSON
method, but JSON.stringify()
doesn't match the spec:
https://developers.google.com/protocol-buffers/docs/proto3#json
Eg stringify
throws on BigInts and doesn't base64-encode binary. protobufjs hasn't implemented a number of the types that need custom encoding: protobufjs/protobuf.js#1304
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Eg stringify throws on BigInts and doesn't base64-encode binary.
Why use stringify? Doesn't the toJSON directly work with these? Is there an issue to follow?
protobufjs hasn't implemented a number of the types that need custom encoding: protobufjs/protobuf.js#1304
Makes sense. They just need better support for well known types. I wonder if we can contribute? Otherwise, I wonder if we can walk the object for WKT's and convert them ourselves.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The last commit in their repo was in last May, I fear contribution is not a viable option.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why use stringify? Doesn't the toJSON directly work with these? Is there an issue to follow?
I just meant that if toJSON
were implemented with JSON.stringify
, it wouldn't work. I made this issue: #481
I wonder if we can contribute? Otherwise, I wonder if we can walk the object for WKT's and convert them ourselves.
I'd like to try contributing. If converting ourselves, unless we fork protobufjs, we'd be doing what proto3-json-serializer
does, and would have the same requirement on how the user generates & provides their messages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 I am not sure it's reasonable to ask people to use our custom protoc. Ideally we can do this from the outside on protobufjs-generated classes/descriptors.
Having said that, this being the only one of our languages without a canonical, supported proto-JSON implementation, I'd support just erroring in data converters if protos are provided in either direction, but allow them to use a custom converter to pick their preferred conversion (or binary only, but we should still error on from-payload when we receive json/protobuf
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to ask people to use our custom protoc
We're still having them use the protobufjs generator (pbjs
). It may not be the way they're currently running it. If not, I think it's straightforward to switch or to do both—our way for temporal code and their way for the rest of their code. The main difference in use is doing Message.create()
instead of new Message()
.
If we think running the generator our way is too big an ask for some users, we could add support for just binary/protobuf
for them, without removing current functionality.
the only one of our languages without a canonical, supported proto-JSON implementation
I think the library we're using is well-maintained and from Google/canonical: https://github.com/googleapis/proto3-json-serializer-nodejs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main difference in use is doing Message.create() instead of new Message().
Can you document why in one of your docs? Is this a limitation of proto3-json-serializer
?
If we think running the generator our way is too big an ask for some user
I don't think it's too big of an ask, just offering the alternative of having json/protobuf
be opt-in instead of by default if it's too much trouble.
I think the library we're using is well-maintained and from Google/canonical: https://github.com/googleapis/proto3-json-serializer-nodejs
Sorry, to clarify, there's a reason that JS isn't listed at https://developers.google.com/protocol-buffers/docs/tutorials or in official docs. But I agree that JSON serializer works if we document how to use it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you document why in one of your docs? Is this a limitation of proto3-json-serializer?
Yes. Limitation of this way of running pbjs
.
Addressed review comments and:
where the first exports things you might want to use in your own common code (shared between client/worker/workflow) like data converters, failures, and errors. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like this new design! Didn't look to much into gritty details but just some comments on high-level stuff.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't have many comments, most of the critical ones I communicated on slack.
I want to try to use TS type checking to ensure that we always encode and decode payloads, but it doesn't block this PR.
I'm approving, this is good to merge as soon as you go over the comments.
}; | ||
await Promise.all([worker.run(), runAndShutdown()]); | ||
t.is(workflowLogs[0], 'encoded'); | ||
t.is(activityLogs[0], 'Activityencodedencoded'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: You can probably test this without the logger if you use a single codec for both encoding and decoding.
"@temporalio/workflow-common": "file:../workflow-common" | ||
}, | ||
"devDependencies": { | ||
"@temporalio/proto": "file:../proto" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be a non dev dependency if we export any of those types or anything that uses those types (e.g. function signatures), to be safe, let's make it non dev.
I'll update |
What was changed
common
package intocommon
(used everywhere but the workflow) andworkflow-common
(used everywhere) to reduce workflow bundle size.Sorry, I should have un-reverted in a subsequent PR so that it wouldn't be included in this PR diff. Here's a diff without that first un-revert commit:
lorensr/sdk-typescript@cc0d414...custom-data-converter
Checklist
Closes [Feature Request] Custom data converters #130
Closes [Feature Request] Protobuf payload converter support #237
How was this tested:
Draft PR: tests aren't passing yet, and I need to write more to cover codec.
Yep