From 3a8f11b67faab0a36195c6e84bc901e7f6f0712e Mon Sep 17 00:00:00 2001 From: chris ludden Date: Thu, 11 Jan 2024 22:49:43 -0700 Subject: [PATCH 1/2] fix: fixes enum cli flags --- internal/plugin/cli.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/plugin/cli.go b/internal/plugin/cli.go index 7628e483..2588cd09 100644 --- a/internal/plugin/cli.go +++ b/internal/plugin/cli.go @@ -853,7 +853,7 @@ func (svc *Service) genCliUnmarshalMessage(f *g.File, msg *protogen.Message) { g.Return(g.Nil(), g.Qual("fmt", "Errorf").Call(g.Lit(fmt.Sprintf("unsupported enum value for %q flag: %%q", flag)), g.Id("cmd").Dot("String").Call(g.Lit(flag)))), ) if oneof != nil { - b.Id("result").Dot(oneof.GoName).Op("=").Op("&").Id(field.GoIdent.GoName).Values(g.Id(goName).Op(":").Id("v")) + b.Id("result").Dot(oneof.GoName).Op("=").Op("&").Id(field.GoIdent.GoName).Values(g.Id(goName).Op(":").Id(field.Enum.GoIdent.GoName).Call(g.Id("v"))) return } b.Id("result").Dot(goName).Op("=").Id(field.Enum.GoIdent.GoName).Call(g.Id("v")) From 640d317dfacd61b8bbcae7361d9b93fa3dd74655 Mon Sep 17 00:00:00 2001 From: chris ludden Date: Thu, 11 Jan 2024 22:50:19 -0700 Subject: [PATCH 2/2] feat: adds experimental codec server support --- README.md | 101 +++- buf.gen.yaml | 2 +- example/main.go | 42 ++ gen/example/v1/example_temporal.pb.go | 22 +- .../examplev1xns/example_xns_temporal.pb.go | 2 +- gen/simple/simple.pb.go | 560 ++++++++++-------- gen/simple/simple_temporal.pb.go | 55 +- .../simplexns/simple_xns_temporal.pb.go | 2 +- internal/plugin/codec.go | 77 +++ internal/plugin/plugin.go | 5 + pkg/codec/codec.go | 225 +++++++ pkg/scheme/scheme.go | 70 +++ test/codec/codec_test.go | 159 +++++ test/simple/simple.proto | 7 + 14 files changed, 1081 insertions(+), 248 deletions(-) create mode 100644 internal/plugin/codec.go create mode 100644 pkg/codec/codec.go create mode 100644 pkg/scheme/scheme.go create mode 100644 test/codec/codec_test.go diff --git a/README.md b/README.md index 71b4b398..f61f3619 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ A protoc plugin for generating typed Temporal clients and workers in Go from pro - [CLI](#cli) - [Test Client](#test-client) - [Cross-Namespace (XNS)](#cross-namespace-xns) + - [Codec](#codec) - [Documentation](#documentation) - [License](#license) @@ -36,7 +37,6 @@ Generated **Client** with: - default `client.StartWorkflowOptions` and `client.UpdateWorkflowWithOptionsRequest` - dynamic workflow ids, update ids, and search attributes via [Bloblang expressions](#bloblang-expressions) - default timeouts, id reuse policies, retry policies, wait policies - - experimental [cross-namespace (xns)](#cross-namespace-xns) support Generated **Worker** resources with: @@ -54,6 +54,12 @@ Optional **CLI** with: - typed flags for conventiently specifying workflow, query, and signal inputs +Generated [Cross-Namespace (XNS)](#cross-namespace-xns) helpers: **[Experimental]** + - with support for invoking a service's workflows, queries, signals, and updates from workflows in a different temporal namespace + +Generated [Remote Codec Server](#codec) helpers **[Experimental]** + + ## Getting Started 1. Install [buf](https://docs.buf.build/installation) @@ -472,6 +478,7 @@ via: | cli-categories | `bool` | enables cli categories | `true` | | cli-enabled | `bool` | enables cli generation | `false` | | disable-workflow-input-rename | `bool` | disables renamed workflow input suffix | `false` | +| enable-codec | `bool` | enables [experimental codec-server support](#codec) | `false` | | enable-patch-support | `bool` | enables experimental support for [protoc-gen-go-patch](https://github.com/alta/protopatch) | `false` | | enable-xns | `bool` | enables [experimental cross-namespace support](#cross-namespace-xns) | `false` | | workflow-update-enabled | `bool` | enables experimental workflow update | `false` | @@ -648,6 +655,98 @@ The generated code includes resources that are compatible with the Temporal Go S This plugin provides experimental support for cross-namespace and/or cross-cluster integration by enabling the `enable-xns` plugin option. When enabled, the plugin will generate an additional `path/to/generated/code/xns` go package containing types, methods, and helpers for calling workflows, queries, signals, and updates from other Temporal workflows via activities. The activities use [heartbeating](https://docs.temporal.io/activities#activity-heartbeat) to maintain liveness for long-running workflows or updates, and their associated timeouts can be configured using the generated options helpers. For an example of xns integration, see the [example/external](./example/external/external.go) package. +## Codec + +*__Experimental__* + +Temporal's [default data converter](https://pkg.go.dev/go.temporal.io/sdk/converter#GetDefaultDataConverter) will serialize protobuf types using the `json/protobuf` encoding provided by the [ProtoJSONPayloadConverter](https://pkg.go.dev/go.temporal.io/sdk/converter#ProtoJSONPayloadConverter), which allows the Temporal UI to automatically decode the underlying payload and render it as JSON. If you'd prefer to take advantage of protobuf's binary format for smaller payloads, you can provide an alternative data converter to the Temporal client at initialization that prioritizes the [ProtoPayloadConverter](https://pkg.go.dev/go.temporal.io/sdk/converter#ProtoPayloadConverter) ahead of the `ProtoJSONPayloadConverter`. See below for an example. + +If you choose to use `binary/protobuf` encoding, you'll lose the ability to view decoded payloads in the Temporal UI unless you configure the [Remote Codec Server](https://docs.temporal.io/dataconversion#codec-server) integration. This plugin can generate helpers that simplify the process of implementing a remote codec server for use with the Temporal UI to support conversion between `binary/protobuf` and `json/protobuf` or `json/plain` payload encodings. See below for a simple example. For a more advanced example that supports different codecs per namespace, cors, and authentication, see the [codec-server](https://github.com/temporalio/samples-go/blob/main/codec-server/codec-server/main.go) go sample. + +**Example:** *custom data converter that uses `binary/protobuf` for encoding, but supports all of `binary/protobuf`, `json/protobuf`, and `json/plain` for decoding.* + +```go +package main + +import ( + "go.temporal.io/sdk/client" + "go.temporal.io/sdk/converter" +) +func main() { + client, _ := client.Dial(client.Options{ + DataConverter: converter.NewCompositeDataConverter( + // Order is important here, as the first match (ProtoPayload in this case) will always + // be used for serialization, and both ProtoJsonPayload and ProtoPayload converters + // check for the same proto.Message interface. + // Deserialization is controlled by metadata, therefore both converters can deserialize + // corresponding data format (JSON or binary proto). + converter.NewNilPayloadConverter(), + converter.NewByteSlicePayloadConverter(), + converter.NewProtoPayloadConverter(), + converter.NewProtoJSONPayloadConverterWithOptions(converter.ProtoJSONPayloadConverterOptions{ + AllowUnknownFields: true, // Prevent errors when the underlying protobuf payload has added fields + }), + converter.NewJSONPayloadConverter(), + ), + }) +} +``` + +**Example:** *basic Remote Codec Server implementation* + +```go +package main + +import ( + "context" + "errors" + "log" + "net/http" + "os" + "os/signal" + "syscall" + + examplev1 "github.com/cludden/protoc-gen-go-temporal/gen/example/v1" + "github.com/cludden/protoc-gen-go-temporal/pkg/codec" + "github.com/cludden/protoc-gen-go-temporal/pkg/scheme" + "go.temporal.io/sdk/converter" +) + +func main() { + // initialize codec handler using this plugin's `pkg/codec` and `pkg/scheme` packages + // along with the generated scheme helpers + handler := converter.NewPayloadCodecHTTPHandler( + codec.NewProtoJSONCodec( + scheme.New( + examplev1.WithExampleSchemeTypes(), + ), + ), + ) + + // initialize http server with codec handler + srv := &http.Server{ + Addr: "0.0.0.0:8080", + Handler: handler, + } + + // handle graceful shutdown + go func() { + shutdownCh := make(chan os.Signal, 1) + signal.Notify(shutdownCh, syscall.SIGINT, syscall.SIGTERM) + <-shutdownCh + + if err := srv.Shutdown(context.Background()); err != nil { + log.Fatalf("error shutting down server: %v", err) + } + }() + + // start remote codec server + if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { + log.Fatalf("server error: %v", err) + } +} +``` + ## Documentation - [Generated code reference](./docs/generated.md) diff --git a/buf.gen.yaml b/buf.gen.yaml index 62606c55..e7affef1 100644 --- a/buf.gen.yaml +++ b/buf.gen.yaml @@ -9,7 +9,7 @@ plugins: opt: plugin=go,paths=source_relative - plugin: go_temporal out: gen - opt: paths=source_relative,cli-enabled=true,cli-categories=true,workflow-update-enabled=true,enable-patch-support=true,enable-xns=true + opt: paths=source_relative,cli-enabled=true,cli-categories=true,workflow-update-enabled=true,enable-patch-support=true,enable-xns=true,enable-codec=true strategy: all - plugin: doc out: docs/api diff --git a/example/main.go b/example/main.go index d2cafd45..779e5907 100644 --- a/example/main.go +++ b/example/main.go @@ -2,16 +2,23 @@ package main import ( "context" + "errors" "fmt" "log" + "net/http" "os" + "os/signal" + "syscall" "github.com/cludden/protoc-gen-go-temporal/example/external" examplev1 "github.com/cludden/protoc-gen-go-temporal/gen/example/v1" "github.com/cludden/protoc-gen-go-temporal/gen/example/v1/examplev1xns" + "github.com/cludden/protoc-gen-go-temporal/pkg/codec" + "github.com/cludden/protoc-gen-go-temporal/pkg/scheme" "github.com/urfave/cli/v2" "go.temporal.io/sdk/activity" "go.temporal.io/sdk/client" + "go.temporal.io/sdk/converter" "go.temporal.io/sdk/worker" "go.temporal.io/sdk/workflow" logger "go.temporal.io/server/common/log" @@ -157,6 +164,41 @@ func main() { } app.Commands = append(app.Commands, external) + app.Commands = append(app.Commands, &cli.Command{ + Name: "codec", + Usage: "run remote codec server", + Action: func(cmd *cli.Context) error { + handler := converter.NewPayloadCodecHTTPHandler( + codec.NewProtoJSONCodec( + scheme.New( + examplev1.WithExampleSchemeTypes(), + examplev1.WithExternalSchemeTypes(), + ), + ), + ) + + srv := &http.Server{ + Addr: "0.0.0.0:8080", + Handler: handler, + } + + go func() { + sigChan := make(chan os.Signal, 1) + signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) + <-sigChan + + if err := srv.Shutdown(context.Background()); err != nil { + log.Fatalf("error shutting down server: %v", err) + } + }() + + if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { + log.Fatalf("server error: %v", err) + } + return nil + }, + }) + // run cli if err := app.Run(os.Args); err != nil { log.Fatal(err) diff --git a/gen/example/v1/example_temporal.pb.go b/gen/example/v1/example_temporal.pb.go index 45f055bd..b6027cd9 100644 --- a/gen/example/v1/example_temporal.pb.go +++ b/gen/example/v1/example_temporal.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go_temporal. DO NOT EDIT. // versions: // -// protoc-gen-go_temporal 1.5.4-next (0bf71e70511e0dc934e818941d042f640434fb00) +// protoc-gen-go_temporal 1.6.1-next (d4aa571c65defba7c1853c6d86735fadf40a4cf8) // go go1.21.5 // protoc (unknown) // @@ -16,6 +16,7 @@ import ( "fmt" expression "github.com/cludden/protoc-gen-go-temporal/pkg/expression" helpers "github.com/cludden/protoc-gen-go-temporal/pkg/helpers" + scheme "github.com/cludden/protoc-gen-go-temporal/pkg/scheme" testutil "github.com/cludden/protoc-gen-go-temporal/pkg/testutil" gohomedir "github.com/mitchellh/go-homedir" v2 "github.com/urfave/cli/v2" @@ -1667,6 +1668,17 @@ func UnmarshalCliFlagsToCreateFooInput(cmd *v2.Context) (*CreateFooInput, error) return &result, nil } +// WithExampleSchemeTypes registers all Example protobuf types with the given scheme +func WithExampleSchemeTypes() scheme.Option { + return func(s *scheme.Scheme) { + s.RegisterType(File_example_v1_example_proto.Messages().ByName("NotifyRequest")) + s.RegisterType(File_example_v1_example_proto.Messages().ByName("GetFooProgressResponse")) + s.RegisterType(File_example_v1_example_proto.Messages().ByName("SetFooProgressRequest")) + s.RegisterType(File_example_v1_example_proto.Messages().ByName("CreateFooRequest")) + s.RegisterType(File_example_v1_example_proto.Messages().ByName("CreateFooResponse")) + } +} + // ExternalTaskQueue= is the default task-queue for a example.v1.External worker const ExternalTaskQueue = "external-v1" @@ -2305,3 +2317,11 @@ func UnmarshalCliFlagsToProvisionFooInput(cmd *v2.Context) (*ProvisionFooInput, } return &result, nil } + +// WithExternalSchemeTypes registers all External protobuf types with the given scheme +func WithExternalSchemeTypes() scheme.Option { + return func(s *scheme.Scheme) { + s.RegisterType(File_example_v1_example_proto.Messages().ByName("ProvisionFooRequest")) + s.RegisterType(File_example_v1_example_proto.Messages().ByName("ProvisionFooResponse")) + } +} diff --git a/gen/example/v1/examplev1xns/example_xns_temporal.pb.go b/gen/example/v1/examplev1xns/example_xns_temporal.pb.go index 16895ac3..b6eb191d 100644 --- a/gen/example/v1/examplev1xns/example_xns_temporal.pb.go +++ b/gen/example/v1/examplev1xns/example_xns_temporal.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go_temporal. DO NOT EDIT. // versions: // -// protoc-gen-go_temporal 1.5.4-next (0bf71e70511e0dc934e818941d042f640434fb00) +// protoc-gen-go_temporal 1.6.1-next (d4aa571c65defba7c1853c6d86735fadf40a4cf8) // go go1.21.5 // protoc (unknown) // diff --git a/gen/simple/simple.pb.go b/gen/simple/simple.pb.go index 6bebc7a3..6194d842 100644 --- a/gen/simple/simple.pb.go +++ b/gen/simple/simple.pb.go @@ -26,6 +26,55 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +type OtherEnum int32 + +const ( + OtherEnum_OTHER_UNSPECIFIED OtherEnum = 0 + OtherEnum_OTHER_FOO OtherEnum = 1 + OtherEnum_OTHER_BAR OtherEnum = 2 +) + +// Enum value maps for OtherEnum. +var ( + OtherEnum_name = map[int32]string{ + 0: "OTHER_UNSPECIFIED", + 1: "OTHER_FOO", + 2: "OTHER_BAR", + } + OtherEnum_value = map[string]int32{ + "OTHER_UNSPECIFIED": 0, + "OTHER_FOO": 1, + "OTHER_BAR": 2, + } +) + +func (x OtherEnum) Enum() *OtherEnum { + p := new(OtherEnum) + *p = x + return p +} + +func (x OtherEnum) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (OtherEnum) Descriptor() protoreflect.EnumDescriptor { + return file_simple_simple_proto_enumTypes[0].Descriptor() +} + +func (OtherEnum) Type() protoreflect.EnumType { + return &file_simple_simple_proto_enumTypes[0] +} + +func (x OtherEnum) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use OtherEnum.Descriptor instead. +func (OtherEnum) EnumDescriptor() ([]byte, []int) { + return file_simple_simple_proto_rawDescGZIP(), []int{0} +} + type SomeWorkflow1Request struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -730,6 +779,7 @@ type OtherWorkflowRequest struct { // *OtherWorkflowRequest_ExampleDuration // *OtherWorkflowRequest_ExampleEmpty // *OtherWorkflowRequest_ExampleTimestamp + // *OtherWorkflowRequest_ExampleEnum ExampleOneof isOtherWorkflowRequest_ExampleOneof `protobuf_oneof:"example_oneof"` } @@ -933,6 +983,13 @@ func (x *OtherWorkflowRequest) GetExampleTimestamp() *timestamppb.Timestamp { return nil } +func (x *OtherWorkflowRequest) GetExampleEnum() OtherEnum { + if x, ok := x.GetExampleOneof().(*OtherWorkflowRequest_ExampleEnum); ok { + return x.ExampleEnum + } + return OtherEnum_OTHER_UNSPECIFIED +} + type isOtherWorkflowRequest_ExampleOneof interface { isOtherWorkflowRequest_ExampleOneof() } @@ -1017,6 +1074,10 @@ type OtherWorkflowRequest_ExampleTimestamp struct { ExampleTimestamp *timestamppb.Timestamp `protobuf:"bytes,23,opt,name=example_timestamp,json=exampleTimestamp,proto3,oneof"` } +type OtherWorkflowRequest_ExampleEnum struct { + ExampleEnum OtherEnum `protobuf:"varint,24,opt,name=example_enum,json=exampleEnum,proto3,enum=mycompany.simple.OtherEnum,oneof"` +} + func (*OtherWorkflowRequest_Foo) isOtherWorkflowRequest_ExampleOneof() {} func (*OtherWorkflowRequest_Bar_) isOtherWorkflowRequest_ExampleOneof() {} @@ -1057,6 +1118,8 @@ func (*OtherWorkflowRequest_ExampleEmpty) isOtherWorkflowRequest_ExampleOneof() func (*OtherWorkflowRequest_ExampleTimestamp) isOtherWorkflowRequest_ExampleOneof() {} +func (*OtherWorkflowRequest_ExampleEnum) isOtherWorkflowRequest_ExampleOneof() {} + type OtherWorkflowResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1573,8 +1636,8 @@ var file_simple_simple_proto_rawDesc = []byte{ 0x74, 0x56, 0x61, 0x6c, 0x22, 0x38, 0x0a, 0x13, 0x53, 0x6f, 0x6d, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x31, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0b, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x61, 0x6c, 0x22, 0xec, - 0x08, 0x0a, 0x14, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, + 0x09, 0x52, 0x0b, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x61, 0x6c, 0x22, 0xae, + 0x09, 0x0a, 0x14, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x6f, 0x6d, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x6f, 0x6d, 0x65, 0x56, 0x61, 0x6c, 0x12, 0x3c, 0x0a, 0x03, 0x62, 0x61, 0x7a, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, @@ -1640,176 +1703,184 @@ var file_simple_simple_proto_rawDesc = []byte{ 0x74, 0x61, 0x6d, 0x70, 0x18, 0x17, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x48, 0x00, 0x52, 0x10, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, - 0x65, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x1a, 0x17, 0x0a, 0x03, 0x42, 0x61, - 0x72, 0x12, 0x10, 0x0a, 0x03, 0x62, 0x61, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x62, 0x61, 0x72, 0x1a, 0x17, 0x0a, 0x03, 0x42, 0x61, 0x7a, 0x12, 0x10, 0x0a, 0x03, 0x62, 0x61, - 0x7a, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x62, 0x61, 0x7a, 0x42, 0x0f, 0x0a, 0x0d, - 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x22, 0x17, 0x0a, - 0x15, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, 0x0a, 0x12, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, - 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x22, 0x28, 0x0a, 0x12, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x28, - 0x0a, 0x12, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x22, 0x15, 0x0a, 0x13, 0x4f, 0x74, 0x68, 0x65, - 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x17, 0x0a, 0x03, 0x46, 0x6f, 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x6f, 0x6f, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x66, 0x6f, 0x6f, 0x22, 0x17, 0x0a, 0x03, 0x51, 0x75, 0x78, 0x12, - 0x10, 0x0a, 0x03, 0x71, 0x75, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x71, 0x75, - 0x78, 0x22, 0x21, 0x0a, 0x0b, 0x57, 0x68, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6c, 0x61, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x62, 0x6c, 0x61, 0x68, 0x32, 0xf0, 0x0b, 0x0a, 0x06, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x12, - 0xec, 0x01, 0x0a, 0x0d, 0x53, 0x6f, 0x6d, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, - 0x31, 0x12, 0x26, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, + 0x65, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x40, 0x0a, 0x0c, 0x65, 0x78, + 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x18, 0x18, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x1b, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, + 0x70, 0x6c, 0x65, 0x2e, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x45, 0x6e, 0x75, 0x6d, 0x48, 0x00, 0x52, + 0x0b, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x1a, 0x17, 0x0a, 0x03, + 0x42, 0x61, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x62, 0x61, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x62, 0x61, 0x72, 0x1a, 0x17, 0x0a, 0x03, 0x42, 0x61, 0x7a, 0x12, 0x10, 0x0a, 0x03, + 0x62, 0x61, 0x7a, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x62, 0x61, 0x7a, 0x42, 0x0f, + 0x0a, 0x0d, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x22, + 0x17, 0x0a, 0x15, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, 0x0a, 0x12, 0x4f, 0x74, 0x68, 0x65, + 0x72, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, + 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0x28, 0x0a, 0x12, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x53, + 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x22, 0x28, 0x0a, 0x12, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x22, 0x15, 0x0a, 0x13, 0x4f, 0x74, + 0x68, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x17, 0x0a, 0x03, 0x46, 0x6f, 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x6f, 0x6f, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x66, 0x6f, 0x6f, 0x22, 0x17, 0x0a, 0x03, 0x51, 0x75, + 0x78, 0x12, 0x10, 0x0a, 0x03, 0x71, 0x75, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x71, 0x75, 0x78, 0x22, 0x21, 0x0a, 0x0b, 0x57, 0x68, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6c, 0x61, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x62, 0x6c, 0x61, 0x68, 0x2a, 0x40, 0x0a, 0x09, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x45, + 0x6e, 0x75, 0x6d, 0x12, 0x15, 0x0a, 0x11, 0x4f, 0x54, 0x48, 0x45, 0x52, 0x5f, 0x55, 0x4e, 0x53, + 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4f, 0x54, + 0x48, 0x45, 0x52, 0x5f, 0x46, 0x4f, 0x4f, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x4f, 0x54, 0x48, + 0x45, 0x52, 0x5f, 0x42, 0x41, 0x52, 0x10, 0x02, 0x32, 0xf0, 0x0b, 0x0a, 0x06, 0x53, 0x69, 0x6d, + 0x70, 0x6c, 0x65, 0x12, 0xec, 0x01, 0x0a, 0x0d, 0x53, 0x6f, 0x6d, 0x65, 0x57, 0x6f, 0x72, 0x6b, + 0x66, 0x6c, 0x6f, 0x77, 0x31, 0x12, 0x26, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, + 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x53, 0x6f, 0x6d, 0x65, 0x57, 0x6f, 0x72, + 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x31, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, + 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, + 0x2e, 0x53, 0x6f, 0x6d, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x31, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x89, 0x01, 0x8a, 0xc4, 0x03, 0x84, 0x01, 0x0a, 0x0c, + 0x0a, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x31, 0x0a, 0x0c, 0x0a, 0x0a, + 0x53, 0x6f, 0x6d, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x32, 0x12, 0x0d, 0x0a, 0x0b, 0x53, 0x6f, + 0x6d, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x31, 0x12, 0x0d, 0x0a, 0x0b, 0x53, 0x6f, 0x6d, + 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x32, 0x2a, 0x28, 0x73, 0x6f, 0x6d, 0x65, 0x2d, 0x77, + 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x2d, 0x31, 0x2f, 0x24, 0x7b, 0x21, 0x20, 0x69, 0x64, + 0x20, 0x7d, 0x2f, 0x24, 0x7b, 0x21, 0x20, 0x75, 0x75, 0x69, 0x64, 0x5f, 0x76, 0x34, 0x28, 0x29, + 0x20, 0x7d, 0x72, 0x1e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x53, 0x6f, 0x6d, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, - 0x77, 0x31, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x6d, 0x79, 0x63, 0x6f, + 0x77, 0x31, 0x12, 0x85, 0x01, 0x0a, 0x0d, 0x53, 0x6f, 0x6d, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, + 0x6c, 0x6f, 0x77, 0x32, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x22, 0x44, 0x8a, 0xc4, 0x03, 0x40, 0x12, 0x0f, 0x0a, 0x0b, 0x53, 0x6f, + 0x6d, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x31, 0x10, 0x01, 0x1a, 0x0d, 0x0a, 0x0b, 0x53, + 0x6f, 0x6d, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x31, 0x72, 0x1e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x53, 0x6f, 0x6d, - 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x31, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x89, 0x01, 0x8a, 0xc4, 0x03, 0x84, 0x01, 0x0a, 0x0c, 0x0a, 0x0a, 0x53, 0x6f, - 0x6d, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x31, 0x0a, 0x0c, 0x0a, 0x0a, 0x53, 0x6f, 0x6d, 0x65, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x32, 0x12, 0x0d, 0x0a, 0x0b, 0x53, 0x6f, 0x6d, 0x65, 0x53, 0x69, - 0x67, 0x6e, 0x61, 0x6c, 0x31, 0x12, 0x0d, 0x0a, 0x0b, 0x53, 0x6f, 0x6d, 0x65, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x6c, 0x32, 0x2a, 0x28, 0x73, 0x6f, 0x6d, 0x65, 0x2d, 0x77, 0x6f, 0x72, 0x6b, 0x66, - 0x6c, 0x6f, 0x77, 0x2d, 0x31, 0x2f, 0x24, 0x7b, 0x21, 0x20, 0x69, 0x64, 0x20, 0x7d, 0x2f, 0x24, - 0x7b, 0x21, 0x20, 0x75, 0x75, 0x69, 0x64, 0x5f, 0x76, 0x34, 0x28, 0x29, 0x20, 0x7d, 0x72, 0x1e, - 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, - 0x2e, 0x53, 0x6f, 0x6d, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x31, 0x12, 0x85, - 0x01, 0x0a, 0x0d, 0x53, 0x6f, 0x6d, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x32, + 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x32, 0x12, 0xad, 0x01, 0x0a, 0x0d, 0x53, + 0x6f, 0x6d, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x33, 0x12, 0x26, 0x2e, 0x6d, + 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, + 0x53, 0x6f, 0x6d, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x33, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x5c, 0x8a, 0xc4, + 0x03, 0x58, 0x12, 0x0f, 0x0a, 0x0b, 0x53, 0x6f, 0x6d, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, + 0x32, 0x10, 0x01, 0x22, 0x03, 0x08, 0x90, 0x1c, 0x2a, 0x29, 0x73, 0x6f, 0x6d, 0x65, 0x2d, 0x77, + 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x2d, 0x33, 0x2f, 0x24, 0x7b, 0x21, 0x20, 0x69, 0x64, + 0x20, 0x7d, 0x2f, 0x24, 0x7b, 0x21, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x61, + 0x6c, 0x20, 0x7d, 0x30, 0x01, 0x4a, 0x02, 0x20, 0x02, 0x5a, 0x0f, 0x6d, 0x79, 0x2d, 0x74, 0x61, + 0x73, 0x6b, 0x2d, 0x71, 0x75, 0x65, 0x75, 0x65, 0x2d, 0x32, 0x12, 0x65, 0x0a, 0x0d, 0x53, 0x6f, + 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x31, 0x12, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x24, 0x92, 0xc4, 0x03, + 0x20, 0x3a, 0x1e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, + 0x70, 0x6c, 0x65, 0x2e, 0x53, 0x6f, 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, + 0x31, 0x12, 0x5f, 0x0a, 0x0d, 0x53, 0x6f, 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, + 0x79, 0x32, 0x12, 0x26, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x73, + 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x53, 0x6f, 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, + 0x74, 0x79, 0x32, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x22, 0x0e, 0x92, 0xc4, 0x03, 0x0a, 0x22, 0x02, 0x08, 0x0a, 0x32, 0x04, 0x1a, 0x02, + 0x08, 0x1e, 0x12, 0x6e, 0x0a, 0x0d, 0x53, 0x6f, 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, + 0x74, 0x79, 0x33, 0x12, 0x26, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, + 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x53, 0x6f, 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, + 0x69, 0x74, 0x79, 0x33, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x6d, 0x79, + 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x53, + 0x6f, 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x33, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x92, 0xc4, 0x03, 0x08, 0x22, 0x02, 0x08, 0x0a, 0x32, 0x02, + 0x20, 0x05, 0x12, 0x50, 0x0a, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x31, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x22, 0x44, 0x8a, 0xc4, 0x03, 0x40, 0x12, 0x0f, 0x0a, 0x0b, 0x53, 0x6f, 0x6d, 0x65, 0x53, 0x69, - 0x67, 0x6e, 0x61, 0x6c, 0x31, 0x10, 0x01, 0x1a, 0x0d, 0x0a, 0x0b, 0x53, 0x6f, 0x6d, 0x65, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x31, 0x72, 0x1e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, - 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x53, 0x6f, 0x6d, 0x65, 0x57, 0x6f, 0x72, - 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x32, 0x12, 0xad, 0x01, 0x0a, 0x0d, 0x53, 0x6f, 0x6d, 0x65, 0x57, - 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x33, 0x12, 0x26, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x24, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x53, 0x6f, 0x6d, 0x65, - 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x33, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x5c, 0x8a, 0xc4, 0x03, 0x58, 0x12, 0x0f, - 0x0a, 0x0b, 0x53, 0x6f, 0x6d, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x32, 0x10, 0x01, 0x22, - 0x03, 0x08, 0x90, 0x1c, 0x2a, 0x29, 0x73, 0x6f, 0x6d, 0x65, 0x2d, 0x77, 0x6f, 0x72, 0x6b, 0x66, - 0x6c, 0x6f, 0x77, 0x2d, 0x33, 0x2f, 0x24, 0x7b, 0x21, 0x20, 0x69, 0x64, 0x20, 0x7d, 0x2f, 0x24, - 0x7b, 0x21, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x20, 0x7d, 0x30, - 0x01, 0x4a, 0x02, 0x20, 0x02, 0x5a, 0x0f, 0x6d, 0x79, 0x2d, 0x74, 0x61, 0x73, 0x6b, 0x2d, 0x71, - 0x75, 0x65, 0x75, 0x65, 0x2d, 0x32, 0x12, 0x65, 0x0a, 0x0d, 0x53, 0x6f, 0x6d, 0x65, 0x41, 0x63, - 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x31, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, - 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x24, 0x92, 0xc4, 0x03, 0x20, 0x3a, 0x1e, 0x6d, - 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, - 0x53, 0x6f, 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x31, 0x12, 0x5f, 0x0a, - 0x0d, 0x53, 0x6f, 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x32, 0x12, 0x26, - 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, - 0x65, 0x2e, 0x53, 0x6f, 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x32, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x0e, - 0x92, 0xc4, 0x03, 0x0a, 0x22, 0x02, 0x08, 0x0a, 0x32, 0x04, 0x1a, 0x02, 0x08, 0x1e, 0x12, 0x6e, - 0x0a, 0x0d, 0x53, 0x6f, 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x33, 0x12, - 0x26, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, - 0x6c, 0x65, 0x2e, 0x53, 0x6f, 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x33, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, - 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x53, 0x6f, 0x6d, 0x65, 0x41, - 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x33, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x0c, 0x92, 0xc4, 0x03, 0x08, 0x22, 0x02, 0x08, 0x0a, 0x32, 0x02, 0x20, 0x05, 0x12, 0x50, - 0x0a, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x31, 0x12, 0x16, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x24, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, - 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x53, 0x6f, 0x6d, 0x65, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x31, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x04, 0x9a, 0xc4, 0x03, 0x00, - 0x12, 0x5d, 0x0a, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x32, 0x12, 0x23, - 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, - 0x65, 0x2e, 0x53, 0x6f, 0x6d, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x32, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, - 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x53, 0x6f, 0x6d, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, - 0x32, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x04, 0x9a, 0xc4, 0x03, 0x00, 0x12, - 0x4b, 0x0a, 0x0b, 0x53, 0x6f, 0x6d, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x31, 0x12, 0x16, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x0c, - 0x92, 0xc4, 0x03, 0x04, 0x22, 0x02, 0x08, 0x0a, 0xa2, 0xc4, 0x03, 0x00, 0x12, 0x59, 0x0a, 0x0b, - 0x53, 0x6f, 0x6d, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x32, 0x12, 0x24, 0x2e, 0x6d, 0x79, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x31, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x04, + 0x9a, 0xc4, 0x03, 0x00, 0x12, 0x5d, 0x0a, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x51, 0x75, 0x65, 0x72, + 0x79, 0x32, 0x12, 0x23, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x73, + 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x53, 0x6f, 0x6d, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x32, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, + 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x53, 0x6f, 0x6d, 0x65, 0x51, + 0x75, 0x65, 0x72, 0x79, 0x32, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x04, 0x9a, + 0xc4, 0x03, 0x00, 0x12, 0x4b, 0x0a, 0x0b, 0x53, 0x6f, 0x6d, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, + 0x6c, 0x31, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x22, 0x0c, 0x92, 0xc4, 0x03, 0x04, 0x22, 0x02, 0x08, 0x0a, 0xa2, 0xc4, 0x03, 0x00, + 0x12, 0x59, 0x0a, 0x0b, 0x53, 0x6f, 0x6d, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x32, 0x12, + 0x24, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, + 0x6c, 0x65, 0x2e, 0x53, 0x6f, 0x6d, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x32, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x0c, 0x92, + 0xc4, 0x03, 0x04, 0x22, 0x02, 0x08, 0x0a, 0xa2, 0xc4, 0x03, 0x00, 0x12, 0x68, 0x0a, 0x0b, 0x53, + 0x6f, 0x6d, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x33, 0x12, 0x24, 0x2e, 0x6d, 0x79, 0x63, + 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x53, 0x6f, + 0x6d, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x33, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x25, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, + 0x70, 0x6c, 0x65, 0x2e, 0x53, 0x6f, 0x6d, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x33, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x92, 0xc4, 0x03, 0x04, 0x22, 0x02, 0x08, + 0x0a, 0xa2, 0xc4, 0x03, 0x00, 0x12, 0xae, 0x01, 0x0a, 0x0b, 0x53, 0x6f, 0x6d, 0x65, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x31, 0x12, 0x24, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, + 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x53, 0x6f, 0x6d, 0x65, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x31, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x53, - 0x6f, 0x6d, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x32, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x0c, 0x92, 0xc4, 0x03, 0x04, 0x22, - 0x02, 0x08, 0x0a, 0xa2, 0xc4, 0x03, 0x00, 0x12, 0x68, 0x0a, 0x0b, 0x53, 0x6f, 0x6d, 0x65, 0x53, - 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x33, 0x12, 0x24, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, - 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x53, 0x6f, 0x6d, 0x65, 0x53, 0x69, - 0x67, 0x6e, 0x61, 0x6c, 0x33, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6d, - 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, - 0x53, 0x6f, 0x6d, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x33, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x92, 0xc4, 0x03, 0x04, 0x22, 0x02, 0x08, 0x0a, 0xa2, 0xc4, 0x03, - 0x00, 0x12, 0xae, 0x01, 0x0a, 0x0b, 0x53, 0x6f, 0x6d, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x31, 0x12, 0x24, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, - 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x53, 0x6f, 0x6d, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x31, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, - 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x53, 0x6f, 0x6d, 0x65, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x31, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x52, - 0x92, 0xc4, 0x03, 0x04, 0x22, 0x02, 0x08, 0x0a, 0xaa, 0xc4, 0x03, 0x46, 0x0a, 0x40, 0x73, 0x6f, - 0x6d, 0x65, 0x2d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2f, 0x24, 0x7b, 0x21, 0x20, 0x72, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x2e, 0x6e, 0x6f, 0x74, 0x5f, 0x65, 0x6d, 0x70, - 0x74, 0x79, 0x28, 0x29, 0x2e, 0x63, 0x61, 0x74, 0x63, 0x68, 0x28, 0x22, 0x64, 0x65, 0x66, 0x61, - 0x75, 0x6c, 0x74, 0x22, 0x29, 0x2e, 0x73, 0x6c, 0x75, 0x67, 0x28, 0x29, 0x20, 0x7d, 0x10, 0x01, - 0x18, 0x03, 0x1a, 0x13, 0x8a, 0xc4, 0x03, 0x0f, 0x0a, 0x0d, 0x6d, 0x79, 0x2d, 0x74, 0x61, 0x73, - 0x6b, 0x2d, 0x71, 0x75, 0x65, 0x75, 0x65, 0x32, 0xd7, 0x03, 0x0a, 0x05, 0x4f, 0x74, 0x68, 0x65, - 0x72, 0x12, 0x8c, 0x01, 0x0a, 0x0d, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, - 0x6c, 0x6f, 0x77, 0x12, 0x26, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, - 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, - 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x6d, 0x79, - 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x4f, - 0x74, 0x68, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x8a, 0xc4, 0x03, 0x1e, 0x2a, 0x1c, 0x6f, 0x74, 0x68, 0x65, - 0x72, 0x2d, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x2f, 0x24, 0x7b, 0x21, 0x75, 0x75, - 0x69, 0x64, 0x5f, 0x76, 0x34, 0x28, 0x29, 0x7d, 0x92, 0xc4, 0x03, 0x04, 0x22, 0x02, 0x08, 0x1e, - 0x12, 0x50, 0x0a, 0x0a, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x16, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x24, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, - 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x04, 0x9a, 0xc4, - 0x03, 0x00, 0x12, 0x57, 0x0a, 0x0b, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x53, 0x69, 0x67, 0x6e, 0x61, - 0x6c, 0x12, 0x24, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, - 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, - 0x0a, 0xa2, 0xc4, 0x03, 0x00, 0xb2, 0xc4, 0x03, 0x02, 0x08, 0x01, 0x12, 0x7c, 0x0a, 0x0b, 0x4f, - 0x74, 0x68, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x24, 0x2e, 0x6d, 0x79, 0x63, + 0x6f, 0x6d, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x31, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x52, 0x92, 0xc4, 0x03, 0x04, 0x22, 0x02, 0x08, 0x0a, 0xaa, 0xc4, 0x03, 0x46, + 0x0a, 0x40, 0x73, 0x6f, 0x6d, 0x65, 0x2d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2f, 0x24, 0x7b, + 0x21, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x2e, 0x6e, 0x6f, 0x74, + 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x28, 0x29, 0x2e, 0x63, 0x61, 0x74, 0x63, 0x68, 0x28, 0x22, + 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x22, 0x29, 0x2e, 0x73, 0x6c, 0x75, 0x67, 0x28, 0x29, + 0x20, 0x7d, 0x10, 0x01, 0x18, 0x03, 0x1a, 0x13, 0x8a, 0xc4, 0x03, 0x0f, 0x0a, 0x0d, 0x6d, 0x79, + 0x2d, 0x74, 0x61, 0x73, 0x6b, 0x2d, 0x71, 0x75, 0x65, 0x75, 0x65, 0x32, 0xd7, 0x03, 0x0a, 0x05, + 0x4f, 0x74, 0x68, 0x65, 0x72, 0x12, 0x8c, 0x01, 0x0a, 0x0d, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x57, + 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x26, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, + 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x4f, 0x74, 0x68, 0x65, 0x72, + 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x27, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, + 0x6c, 0x65, 0x2e, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x8a, 0xc4, 0x03, 0x1e, 0x2a, 0x1c, + 0x6f, 0x74, 0x68, 0x65, 0x72, 0x2d, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x2f, 0x24, + 0x7b, 0x21, 0x75, 0x75, 0x69, 0x64, 0x5f, 0x76, 0x34, 0x28, 0x29, 0x7d, 0x92, 0xc4, 0x03, 0x04, + 0x22, 0x02, 0x08, 0x1e, 0x12, 0x50, 0x0a, 0x0a, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x51, 0x75, 0x65, + 0x72, 0x79, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x24, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x4f, 0x74, - 0x68, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x25, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, - 0x70, 0x6c, 0x65, 0x2e, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0xaa, 0xc4, 0x03, 0x1c, 0x0a, 0x1a, 0x6f, - 0x74, 0x68, 0x65, 0x72, 0x2d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2f, 0x24, 0x7b, 0x21, 0x75, - 0x75, 0x69, 0x64, 0x5f, 0x76, 0x34, 0x28, 0x29, 0x7d, 0x1a, 0x16, 0x8a, 0xc4, 0x03, 0x12, 0x0a, - 0x10, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x2d, 0x74, 0x61, 0x73, 0x6b, 0x2d, 0x71, 0x75, 0x65, 0x75, - 0x65, 0x32, 0x40, 0x0a, 0x07, 0x4e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x12, 0x35, 0x0a, 0x03, - 0x46, 0x6f, 0x6f, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, + 0x68, 0x65, 0x72, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x04, 0x9a, 0xc4, 0x03, 0x00, 0x12, 0x57, 0x0a, 0x0b, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x53, + 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x12, 0x24, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, + 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x53, 0x69, + 0x67, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x32, 0x68, 0x0a, 0x07, 0x49, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x64, 0x12, 0x55, - 0x0a, 0x04, 0x57, 0x68, 0x61, 0x74, 0x12, 0x1d, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, - 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x57, 0x68, 0x61, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x16, 0x8a, - 0xc4, 0x03, 0x12, 0x2a, 0x10, 0x77, 0x68, 0x61, 0x74, 0x2f, 0x24, 0x7b, 0x21, 0x6b, 0x73, 0x75, - 0x69, 0x64, 0x28, 0x29, 0x7d, 0x1a, 0x06, 0x92, 0xc4, 0x03, 0x02, 0x08, 0x01, 0x42, 0xba, 0x01, - 0x0a, 0x14, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, - 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x42, 0x0b, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x50, 0x72, - 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x63, 0x6c, 0x75, 0x64, 0x64, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, - 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x67, 0x6f, 0x2d, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x6c, - 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0xa2, 0x02, 0x03, 0x4d, 0x53, - 0x58, 0xaa, 0x02, 0x10, 0x4d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x53, 0x69, - 0x6d, 0x70, 0x6c, 0x65, 0xca, 0x02, 0x10, 0x4d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, - 0x5c, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0xe2, 0x02, 0x1c, 0x4d, 0x79, 0x63, 0x6f, 0x6d, 0x70, - 0x61, 0x6e, 0x79, 0x5c, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x11, 0x4d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, - 0x6e, 0x79, 0x3a, 0x3a, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x70, 0x74, 0x79, 0x22, 0x0a, 0xa2, 0xc4, 0x03, 0x00, 0xb2, 0xc4, 0x03, 0x02, 0x08, 0x01, 0x12, + 0x7c, 0x0a, 0x0b, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x24, + 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, + 0x65, 0x2e, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, + 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0xaa, 0xc4, 0x03, + 0x1c, 0x0a, 0x1a, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x2d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2f, + 0x24, 0x7b, 0x21, 0x75, 0x75, 0x69, 0x64, 0x5f, 0x76, 0x34, 0x28, 0x29, 0x7d, 0x1a, 0x16, 0x8a, + 0xc4, 0x03, 0x12, 0x0a, 0x10, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x2d, 0x74, 0x61, 0x73, 0x6b, 0x2d, + 0x71, 0x75, 0x65, 0x75, 0x65, 0x32, 0x40, 0x0a, 0x07, 0x4e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, + 0x12, 0x35, 0x0a, 0x03, 0x46, 0x6f, 0x6f, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x32, 0x68, 0x0a, 0x07, 0x49, 0x67, 0x6e, 0x6f, 0x72, + 0x65, 0x64, 0x12, 0x55, 0x0a, 0x04, 0x57, 0x68, 0x61, 0x74, 0x12, 0x1d, 0x2e, 0x6d, 0x79, 0x63, + 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x57, 0x68, + 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x22, 0x16, 0x8a, 0xc4, 0x03, 0x12, 0x2a, 0x10, 0x77, 0x68, 0x61, 0x74, 0x2f, 0x24, 0x7b, + 0x21, 0x6b, 0x73, 0x75, 0x69, 0x64, 0x28, 0x29, 0x7d, 0x1a, 0x06, 0x92, 0xc4, 0x03, 0x02, 0x08, + 0x01, 0x42, 0xba, 0x01, 0x0a, 0x14, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x79, 0x63, 0x6f, 0x6d, 0x70, + 0x61, 0x6e, 0x79, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x42, 0x0b, 0x53, 0x69, 0x6d, 0x70, + 0x6c, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6c, 0x75, 0x64, 0x64, 0x65, 0x6e, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x67, 0x6f, 0x2d, 0x74, 0x65, 0x6d, 0x70, + 0x6f, 0x72, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0xa2, + 0x02, 0x03, 0x4d, 0x53, 0x58, 0xaa, 0x02, 0x10, 0x4d, 0x79, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, + 0x79, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0xca, 0x02, 0x10, 0x4d, 0x79, 0x63, 0x6f, 0x6d, + 0x70, 0x61, 0x6e, 0x79, 0x5c, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0xe2, 0x02, 0x1c, 0x4d, 0x79, + 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x5c, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x5c, 0x47, + 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x11, 0x4d, 0x79, 0x63, + 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x3a, 0x3a, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1824,86 +1895,89 @@ func file_simple_simple_proto_rawDescGZIP() []byte { return file_simple_simple_proto_rawDescData } +var file_simple_simple_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_simple_simple_proto_msgTypes = make([]protoimpl.MessageInfo, 25) var file_simple_simple_proto_goTypes = []interface{}{ - (*SomeWorkflow1Request)(nil), // 0: mycompany.simple.SomeWorkflow1Request - (*SomeWorkflow1Response)(nil), // 1: mycompany.simple.SomeWorkflow1Response - (*SomeWorkflow3Request)(nil), // 2: mycompany.simple.SomeWorkflow3Request - (*SomeActivity2Request)(nil), // 3: mycompany.simple.SomeActivity2Request - (*SomeActivity3Request)(nil), // 4: mycompany.simple.SomeActivity3Request - (*SomeActivity3Response)(nil), // 5: mycompany.simple.SomeActivity3Response - (*SomeQuery1Response)(nil), // 6: mycompany.simple.SomeQuery1Response - (*SomeQuery2Request)(nil), // 7: mycompany.simple.SomeQuery2Request - (*SomeQuery2Response)(nil), // 8: mycompany.simple.SomeQuery2Response - (*SomeSignal2Request)(nil), // 9: mycompany.simple.SomeSignal2Request - (*SomeSignal3Request)(nil), // 10: mycompany.simple.SomeSignal3Request - (*SomeSignal3Response)(nil), // 11: mycompany.simple.SomeSignal3Response - (*SomeUpdate1Request)(nil), // 12: mycompany.simple.SomeUpdate1Request - (*SomeUpdate1Response)(nil), // 13: mycompany.simple.SomeUpdate1Response - (*OtherWorkflowRequest)(nil), // 14: mycompany.simple.OtherWorkflowRequest - (*OtherWorkflowResponse)(nil), // 15: mycompany.simple.OtherWorkflowResponse - (*OtherQueryResponse)(nil), // 16: mycompany.simple.OtherQueryResponse - (*OtherSignalRequest)(nil), // 17: mycompany.simple.OtherSignalRequest - (*OtherUpdateRequest)(nil), // 18: mycompany.simple.OtherUpdateRequest - (*OtherUpdateResponse)(nil), // 19: mycompany.simple.OtherUpdateResponse - (*Foo)(nil), // 20: mycompany.simple.Foo - (*Qux)(nil), // 21: mycompany.simple.Qux - (*WhatRequest)(nil), // 22: mycompany.simple.WhatRequest - (*OtherWorkflowRequest_Bar)(nil), // 23: mycompany.simple.OtherWorkflowRequest.Bar - (*OtherWorkflowRequest_Baz)(nil), // 24: mycompany.simple.OtherWorkflowRequest.Baz - (*durationpb.Duration)(nil), // 25: google.protobuf.Duration - (*emptypb.Empty)(nil), // 26: google.protobuf.Empty - (*timestamppb.Timestamp)(nil), // 27: google.protobuf.Timestamp + (OtherEnum)(0), // 0: mycompany.simple.OtherEnum + (*SomeWorkflow1Request)(nil), // 1: mycompany.simple.SomeWorkflow1Request + (*SomeWorkflow1Response)(nil), // 2: mycompany.simple.SomeWorkflow1Response + (*SomeWorkflow3Request)(nil), // 3: mycompany.simple.SomeWorkflow3Request + (*SomeActivity2Request)(nil), // 4: mycompany.simple.SomeActivity2Request + (*SomeActivity3Request)(nil), // 5: mycompany.simple.SomeActivity3Request + (*SomeActivity3Response)(nil), // 6: mycompany.simple.SomeActivity3Response + (*SomeQuery1Response)(nil), // 7: mycompany.simple.SomeQuery1Response + (*SomeQuery2Request)(nil), // 8: mycompany.simple.SomeQuery2Request + (*SomeQuery2Response)(nil), // 9: mycompany.simple.SomeQuery2Response + (*SomeSignal2Request)(nil), // 10: mycompany.simple.SomeSignal2Request + (*SomeSignal3Request)(nil), // 11: mycompany.simple.SomeSignal3Request + (*SomeSignal3Response)(nil), // 12: mycompany.simple.SomeSignal3Response + (*SomeUpdate1Request)(nil), // 13: mycompany.simple.SomeUpdate1Request + (*SomeUpdate1Response)(nil), // 14: mycompany.simple.SomeUpdate1Response + (*OtherWorkflowRequest)(nil), // 15: mycompany.simple.OtherWorkflowRequest + (*OtherWorkflowResponse)(nil), // 16: mycompany.simple.OtherWorkflowResponse + (*OtherQueryResponse)(nil), // 17: mycompany.simple.OtherQueryResponse + (*OtherSignalRequest)(nil), // 18: mycompany.simple.OtherSignalRequest + (*OtherUpdateRequest)(nil), // 19: mycompany.simple.OtherUpdateRequest + (*OtherUpdateResponse)(nil), // 20: mycompany.simple.OtherUpdateResponse + (*Foo)(nil), // 21: mycompany.simple.Foo + (*Qux)(nil), // 22: mycompany.simple.Qux + (*WhatRequest)(nil), // 23: mycompany.simple.WhatRequest + (*OtherWorkflowRequest_Bar)(nil), // 24: mycompany.simple.OtherWorkflowRequest.Bar + (*OtherWorkflowRequest_Baz)(nil), // 25: mycompany.simple.OtherWorkflowRequest.Baz + (*durationpb.Duration)(nil), // 26: google.protobuf.Duration + (*emptypb.Empty)(nil), // 27: google.protobuf.Empty + (*timestamppb.Timestamp)(nil), // 28: google.protobuf.Timestamp } var file_simple_simple_proto_depIdxs = []int32{ - 24, // 0: mycompany.simple.OtherWorkflowRequest.baz:type_name -> mycompany.simple.OtherWorkflowRequest.Baz - 21, // 1: mycompany.simple.OtherWorkflowRequest.qux:type_name -> mycompany.simple.Qux - 20, // 2: mycompany.simple.OtherWorkflowRequest.foo:type_name -> mycompany.simple.Foo - 23, // 3: mycompany.simple.OtherWorkflowRequest.bar:type_name -> mycompany.simple.OtherWorkflowRequest.Bar - 25, // 4: mycompany.simple.OtherWorkflowRequest.example_duration:type_name -> google.protobuf.Duration - 26, // 5: mycompany.simple.OtherWorkflowRequest.example_empty:type_name -> google.protobuf.Empty - 27, // 6: mycompany.simple.OtherWorkflowRequest.example_timestamp:type_name -> google.protobuf.Timestamp - 0, // 7: mycompany.simple.Simple.SomeWorkflow1:input_type -> mycompany.simple.SomeWorkflow1Request - 26, // 8: mycompany.simple.Simple.SomeWorkflow2:input_type -> google.protobuf.Empty - 2, // 9: mycompany.simple.Simple.SomeWorkflow3:input_type -> mycompany.simple.SomeWorkflow3Request - 26, // 10: mycompany.simple.Simple.SomeActivity1:input_type -> google.protobuf.Empty - 3, // 11: mycompany.simple.Simple.SomeActivity2:input_type -> mycompany.simple.SomeActivity2Request - 4, // 12: mycompany.simple.Simple.SomeActivity3:input_type -> mycompany.simple.SomeActivity3Request - 26, // 13: mycompany.simple.Simple.SomeQuery1:input_type -> google.protobuf.Empty - 7, // 14: mycompany.simple.Simple.SomeQuery2:input_type -> mycompany.simple.SomeQuery2Request - 26, // 15: mycompany.simple.Simple.SomeSignal1:input_type -> google.protobuf.Empty - 9, // 16: mycompany.simple.Simple.SomeSignal2:input_type -> mycompany.simple.SomeSignal2Request - 10, // 17: mycompany.simple.Simple.SomeSignal3:input_type -> mycompany.simple.SomeSignal3Request - 12, // 18: mycompany.simple.Simple.SomeUpdate1:input_type -> mycompany.simple.SomeUpdate1Request - 14, // 19: mycompany.simple.Other.OtherWorkflow:input_type -> mycompany.simple.OtherWorkflowRequest - 26, // 20: mycompany.simple.Other.OtherQuery:input_type -> google.protobuf.Empty - 17, // 21: mycompany.simple.Other.OtherSignal:input_type -> mycompany.simple.OtherSignalRequest - 18, // 22: mycompany.simple.Other.OtherUpdate:input_type -> mycompany.simple.OtherUpdateRequest - 26, // 23: mycompany.simple.Nothing.Foo:input_type -> google.protobuf.Empty - 22, // 24: mycompany.simple.Ignored.What:input_type -> mycompany.simple.WhatRequest - 1, // 25: mycompany.simple.Simple.SomeWorkflow1:output_type -> mycompany.simple.SomeWorkflow1Response - 26, // 26: mycompany.simple.Simple.SomeWorkflow2:output_type -> google.protobuf.Empty - 26, // 27: mycompany.simple.Simple.SomeWorkflow3:output_type -> google.protobuf.Empty - 26, // 28: mycompany.simple.Simple.SomeActivity1:output_type -> google.protobuf.Empty - 26, // 29: mycompany.simple.Simple.SomeActivity2:output_type -> google.protobuf.Empty - 5, // 30: mycompany.simple.Simple.SomeActivity3:output_type -> mycompany.simple.SomeActivity3Response - 6, // 31: mycompany.simple.Simple.SomeQuery1:output_type -> mycompany.simple.SomeQuery1Response - 8, // 32: mycompany.simple.Simple.SomeQuery2:output_type -> mycompany.simple.SomeQuery2Response - 26, // 33: mycompany.simple.Simple.SomeSignal1:output_type -> google.protobuf.Empty - 26, // 34: mycompany.simple.Simple.SomeSignal2:output_type -> google.protobuf.Empty - 11, // 35: mycompany.simple.Simple.SomeSignal3:output_type -> mycompany.simple.SomeSignal3Response - 13, // 36: mycompany.simple.Simple.SomeUpdate1:output_type -> mycompany.simple.SomeUpdate1Response - 15, // 37: mycompany.simple.Other.OtherWorkflow:output_type -> mycompany.simple.OtherWorkflowResponse - 16, // 38: mycompany.simple.Other.OtherQuery:output_type -> mycompany.simple.OtherQueryResponse - 26, // 39: mycompany.simple.Other.OtherSignal:output_type -> google.protobuf.Empty - 19, // 40: mycompany.simple.Other.OtherUpdate:output_type -> mycompany.simple.OtherUpdateResponse - 26, // 41: mycompany.simple.Nothing.Foo:output_type -> google.protobuf.Empty - 26, // 42: mycompany.simple.Ignored.What:output_type -> google.protobuf.Empty - 25, // [25:43] is the sub-list for method output_type - 7, // [7:25] is the sub-list for method input_type - 7, // [7:7] is the sub-list for extension type_name - 7, // [7:7] is the sub-list for extension extendee - 0, // [0:7] is the sub-list for field type_name + 25, // 0: mycompany.simple.OtherWorkflowRequest.baz:type_name -> mycompany.simple.OtherWorkflowRequest.Baz + 22, // 1: mycompany.simple.OtherWorkflowRequest.qux:type_name -> mycompany.simple.Qux + 21, // 2: mycompany.simple.OtherWorkflowRequest.foo:type_name -> mycompany.simple.Foo + 24, // 3: mycompany.simple.OtherWorkflowRequest.bar:type_name -> mycompany.simple.OtherWorkflowRequest.Bar + 26, // 4: mycompany.simple.OtherWorkflowRequest.example_duration:type_name -> google.protobuf.Duration + 27, // 5: mycompany.simple.OtherWorkflowRequest.example_empty:type_name -> google.protobuf.Empty + 28, // 6: mycompany.simple.OtherWorkflowRequest.example_timestamp:type_name -> google.protobuf.Timestamp + 0, // 7: mycompany.simple.OtherWorkflowRequest.example_enum:type_name -> mycompany.simple.OtherEnum + 1, // 8: mycompany.simple.Simple.SomeWorkflow1:input_type -> mycompany.simple.SomeWorkflow1Request + 27, // 9: mycompany.simple.Simple.SomeWorkflow2:input_type -> google.protobuf.Empty + 3, // 10: mycompany.simple.Simple.SomeWorkflow3:input_type -> mycompany.simple.SomeWorkflow3Request + 27, // 11: mycompany.simple.Simple.SomeActivity1:input_type -> google.protobuf.Empty + 4, // 12: mycompany.simple.Simple.SomeActivity2:input_type -> mycompany.simple.SomeActivity2Request + 5, // 13: mycompany.simple.Simple.SomeActivity3:input_type -> mycompany.simple.SomeActivity3Request + 27, // 14: mycompany.simple.Simple.SomeQuery1:input_type -> google.protobuf.Empty + 8, // 15: mycompany.simple.Simple.SomeQuery2:input_type -> mycompany.simple.SomeQuery2Request + 27, // 16: mycompany.simple.Simple.SomeSignal1:input_type -> google.protobuf.Empty + 10, // 17: mycompany.simple.Simple.SomeSignal2:input_type -> mycompany.simple.SomeSignal2Request + 11, // 18: mycompany.simple.Simple.SomeSignal3:input_type -> mycompany.simple.SomeSignal3Request + 13, // 19: mycompany.simple.Simple.SomeUpdate1:input_type -> mycompany.simple.SomeUpdate1Request + 15, // 20: mycompany.simple.Other.OtherWorkflow:input_type -> mycompany.simple.OtherWorkflowRequest + 27, // 21: mycompany.simple.Other.OtherQuery:input_type -> google.protobuf.Empty + 18, // 22: mycompany.simple.Other.OtherSignal:input_type -> mycompany.simple.OtherSignalRequest + 19, // 23: mycompany.simple.Other.OtherUpdate:input_type -> mycompany.simple.OtherUpdateRequest + 27, // 24: mycompany.simple.Nothing.Foo:input_type -> google.protobuf.Empty + 23, // 25: mycompany.simple.Ignored.What:input_type -> mycompany.simple.WhatRequest + 2, // 26: mycompany.simple.Simple.SomeWorkflow1:output_type -> mycompany.simple.SomeWorkflow1Response + 27, // 27: mycompany.simple.Simple.SomeWorkflow2:output_type -> google.protobuf.Empty + 27, // 28: mycompany.simple.Simple.SomeWorkflow3:output_type -> google.protobuf.Empty + 27, // 29: mycompany.simple.Simple.SomeActivity1:output_type -> google.protobuf.Empty + 27, // 30: mycompany.simple.Simple.SomeActivity2:output_type -> google.protobuf.Empty + 6, // 31: mycompany.simple.Simple.SomeActivity3:output_type -> mycompany.simple.SomeActivity3Response + 7, // 32: mycompany.simple.Simple.SomeQuery1:output_type -> mycompany.simple.SomeQuery1Response + 9, // 33: mycompany.simple.Simple.SomeQuery2:output_type -> mycompany.simple.SomeQuery2Response + 27, // 34: mycompany.simple.Simple.SomeSignal1:output_type -> google.protobuf.Empty + 27, // 35: mycompany.simple.Simple.SomeSignal2:output_type -> google.protobuf.Empty + 12, // 36: mycompany.simple.Simple.SomeSignal3:output_type -> mycompany.simple.SomeSignal3Response + 14, // 37: mycompany.simple.Simple.SomeUpdate1:output_type -> mycompany.simple.SomeUpdate1Response + 16, // 38: mycompany.simple.Other.OtherWorkflow:output_type -> mycompany.simple.OtherWorkflowResponse + 17, // 39: mycompany.simple.Other.OtherQuery:output_type -> mycompany.simple.OtherQueryResponse + 27, // 40: mycompany.simple.Other.OtherSignal:output_type -> google.protobuf.Empty + 20, // 41: mycompany.simple.Other.OtherUpdate:output_type -> mycompany.simple.OtherUpdateResponse + 27, // 42: mycompany.simple.Nothing.Foo:output_type -> google.protobuf.Empty + 27, // 43: mycompany.simple.Ignored.What:output_type -> google.protobuf.Empty + 26, // [26:44] is the sub-list for method output_type + 8, // [8:26] is the sub-list for method input_type + 8, // [8:8] is the sub-list for extension type_name + 8, // [8:8] is the sub-list for extension extendee + 0, // [0:8] is the sub-list for field type_name } func init() { file_simple_simple_proto_init() } @@ -2234,19 +2308,21 @@ func file_simple_simple_proto_init() { (*OtherWorkflowRequest_ExampleDuration)(nil), (*OtherWorkflowRequest_ExampleEmpty)(nil), (*OtherWorkflowRequest_ExampleTimestamp)(nil), + (*OtherWorkflowRequest_ExampleEnum)(nil), } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_simple_simple_proto_rawDesc, - NumEnums: 0, + NumEnums: 1, NumMessages: 25, NumExtensions: 0, NumServices: 4, }, GoTypes: file_simple_simple_proto_goTypes, DependencyIndexes: file_simple_simple_proto_depIdxs, + EnumInfos: file_simple_simple_proto_enumTypes, MessageInfos: file_simple_simple_proto_msgTypes, }.Build() File_simple_simple_proto = out.File diff --git a/gen/simple/simple_temporal.pb.go b/gen/simple/simple_temporal.pb.go index d74fc4f3..6bf371c3 100644 --- a/gen/simple/simple_temporal.pb.go +++ b/gen/simple/simple_temporal.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go_temporal. DO NOT EDIT. // versions: // -// protoc-gen-go_temporal 1.5.4-next (0bf71e70511e0dc934e818941d042f640434fb00) +// protoc-gen-go_temporal 1.6.1-next (d4aa571c65defba7c1853c6d86735fadf40a4cf8) // go go1.21.5 // protoc (unknown) // @@ -17,6 +17,7 @@ import ( "fmt" expression "github.com/cludden/protoc-gen-go-temporal/pkg/expression" helpers "github.com/cludden/protoc-gen-go-temporal/pkg/helpers" + scheme "github.com/cludden/protoc-gen-go-temporal/pkg/scheme" testutil "github.com/cludden/protoc-gen-go-temporal/pkg/testutil" gohomedir "github.com/mitchellh/go-homedir" v2 "github.com/urfave/cli/v2" @@ -3987,6 +3988,26 @@ func UnmarshalCliFlagsToSomeWorkflow3Request(cmd *v2.Context) (*SomeWorkflow3Req return &result, nil } +// WithSimpleSchemeTypes registers all Simple protobuf types with the given scheme +func WithSimpleSchemeTypes() scheme.Option { + return func(s *scheme.Scheme) { + s.RegisterType(File_simple_simple_proto.Messages().ByName("SomeActivity2Request")) + s.RegisterType(File_simple_simple_proto.Messages().ByName("SomeActivity3Request")) + s.RegisterType(File_simple_simple_proto.Messages().ByName("SomeActivity3Response")) + s.RegisterType(File_simple_simple_proto.Messages().ByName("SomeSignal2Request")) + s.RegisterType(File_simple_simple_proto.Messages().ByName("SomeSignal3Request")) + s.RegisterType(File_simple_simple_proto.Messages().ByName("SomeSignal3Response")) + s.RegisterType(File_simple_simple_proto.Messages().ByName("SomeUpdate1Request")) + s.RegisterType(File_simple_simple_proto.Messages().ByName("SomeUpdate1Response")) + s.RegisterType(File_simple_simple_proto.Messages().ByName("SomeQuery1Response")) + s.RegisterType(File_simple_simple_proto.Messages().ByName("SomeQuery2Request")) + s.RegisterType(File_simple_simple_proto.Messages().ByName("SomeQuery2Response")) + s.RegisterType(File_simple_simple_proto.Messages().ByName("SomeWorkflow1Request")) + s.RegisterType(File_simple_simple_proto.Messages().ByName("SomeWorkflow1Response")) + s.RegisterType(File_simple_simple_proto.Messages().ByName("SomeWorkflow3Request")) + } +} + // OtherTaskQueue= is the default task-queue for a mycompany.simple.Other worker const OtherTaskQueue = "other-task-queue" @@ -5238,6 +5259,11 @@ func newOtherCommands(options ...*OtherCliOptions) ([]*v2.Command, error) { Usage: "set the value of the operation's \"ExampleTimestamp\" parameter (e.g. \"2017-01-15T01:30:15.01Z\")", Category: "INPUT", }, + &v2.StringFlag{ + Name: "example-enum", + Usage: "set the value of the operation's \"ExampleEnum\" parameter (OTHER_UNSPECIFIED, OTHER_FOO, OTHER_BAR)", + Category: "INPUT", + }, }, Action: func(cmd *v2.Context) error { c, err := opts.clientForCommand(cmd) @@ -5478,12 +5504,32 @@ func UnmarshalCliFlagsToOtherWorkflowRequest(cmd *v2.Context) (*OtherWorkflowReq } result.ExampleOneof = &OtherWorkflowRequest_ExampleTimestamp{ExampleTimestamp: timestamppb.New(v)} } + if cmd.IsSet("example-enum") { + hasValues = true + v, ok := OtherEnum_value[cmd.String("example-enum")] + if !ok { + return nil, fmt.Errorf("unsupported enum value for \"example-enum\" flag: %q", cmd.String("example-enum")) + } + result.ExampleOneof = &OtherWorkflowRequest_ExampleEnum{ExampleEnum: OtherEnum(v)} + } if !hasValues { return nil, nil } return &result, nil } +// WithOtherSchemeTypes registers all Other protobuf types with the given scheme +func WithOtherSchemeTypes() scheme.Option { + return func(s *scheme.Scheme) { + s.RegisterType(File_simple_simple_proto.Messages().ByName("OtherWorkflowRequest")) + s.RegisterType(File_simple_simple_proto.Messages().ByName("OtherWorkflowResponse")) + s.RegisterType(File_simple_simple_proto.Messages().ByName("OtherQueryResponse")) + s.RegisterType(File_simple_simple_proto.Messages().ByName("OtherSignalRequest")) + s.RegisterType(File_simple_simple_proto.Messages().ByName("OtherUpdateRequest")) + s.RegisterType(File_simple_simple_proto.Messages().ByName("OtherUpdateResponse")) + } +} + // mycompany.simple.Ignored workflow names const ( WhatWorkflowName = "mycompany.simple.Ignored.What" @@ -5901,3 +5947,10 @@ func (r *testWhatRun) RunID() string { func (r *testWhatRun) Terminate(ctx context.Context, reason string, details ...interface{}) error { return r.client.TerminateWorkflow(ctx, r.ID(), r.RunID(), reason, details...) } + +// WithIgnoredSchemeTypes registers all Ignored protobuf types with the given scheme +func WithIgnoredSchemeTypes() scheme.Option { + return func(s *scheme.Scheme) { + s.RegisterType(File_simple_simple_proto.Messages().ByName("WhatRequest")) + } +} diff --git a/gen/simple/simplexns/simple_xns_temporal.pb.go b/gen/simple/simplexns/simple_xns_temporal.pb.go index f7425926..3c024b88 100644 --- a/gen/simple/simplexns/simple_xns_temporal.pb.go +++ b/gen/simple/simplexns/simple_xns_temporal.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go_temporal. DO NOT EDIT. // versions: // -// protoc-gen-go_temporal 1.5.4-next (0bf71e70511e0dc934e818941d042f640434fb00) +// protoc-gen-go_temporal 1.6.1-next (d4aa571c65defba7c1853c6d86735fadf40a4cf8) // go go1.21.5 // protoc (unknown) // diff --git a/internal/plugin/codec.go b/internal/plugin/codec.go new file mode 100644 index 00000000..3dc2675a --- /dev/null +++ b/internal/plugin/codec.go @@ -0,0 +1,77 @@ +package plugin + +import ( + "fmt" + + g "github.com/dave/jennifer/jen" + "google.golang.org/protobuf/compiler/protogen" +) + +const ( + schemePkg = "github.com/cludden/protoc-gen-go-temporal/pkg/scheme" +) + +func (svc *Service) renderCodec(f *g.File) { + optName := toCamel("With%sSchemeTypes", svc.GoName) + + f.Commentf("%s registers all %s protobuf types with the given scheme", optName, svc.GoName) + f.Func(). + Id(optName). + Params(). + Qual(schemePkg, "Option"). + Block( + g.Return( + g.Func(). + Params(g.Id("s").Op("*").Qual(schemePkg, "Scheme")). + BlockFunc(func(fn *g.Group) { + types := make(map[string]struct{}) + for _, a := range svc.activitiesOrdered { + method := svc.methods[a] + registerType(svc.Plugin, fn, types, method.Input) + registerType(svc.Plugin, fn, types, method.Output) + } + for _, q := range svc.queriesOrdered { + method := svc.methods[q] + registerType(svc.Plugin, fn, types, method.Input) + registerType(svc.Plugin, fn, types, method.Output) + } + for _, s := range svc.signalsOrdered { + method := svc.methods[s] + registerType(svc.Plugin, fn, types, method.Input) + registerType(svc.Plugin, fn, types, method.Output) + } + for _, u := range svc.updatesOrdered { + method := svc.methods[u] + registerType(svc.Plugin, fn, types, method.Input) + registerType(svc.Plugin, fn, types, method.Output) + } + for _, w := range svc.workflowsOrdered { + method := svc.methods[w] + registerType(svc.Plugin, fn, types, method.Input) + registerType(svc.Plugin, fn, types, method.Output) + } + }), + ), + ) +} + +func registerType(p *protogen.Plugin, fn *g.Group, cache map[string]struct{}, msg *protogen.Message) { + if _, ok := cache[string(msg.Desc.FullName())]; ok || isEmpty(msg) { + return + } + f, ok := p.FilesByPath[msg.Desc.ParentFile().Path()] + if !ok { + p.Error(fmt.Errorf("unable to locate parent file for msg: %s", msg.Desc.ParentFile().Path())) + return + } + fn.Id("s"). + Dot("RegisterType"). + Call( + g.Id(f.GoDescriptorIdent.GoName). + Dot("Messages"). + Call(). + Dot("ByName"). + Call(g.Lit(string(msg.Desc.FullName().Name()))), + ) + cache[string(msg.Desc.FullName())] = struct{}{} +} diff --git a/internal/plugin/plugin.go b/internal/plugin/plugin.go index 54337c48..9c3e66c2 100644 --- a/internal/plugin/plugin.go +++ b/internal/plugin/plugin.go @@ -15,6 +15,7 @@ type Config struct { CliCategories bool CliEnabled bool DisableWorkflowInputRename bool + EnableCodec bool EnablePatchSupport bool EnableXNS bool WorkflowUpdateEnabled bool @@ -37,6 +38,7 @@ func New(commit, version string) *Plugin { flags.BoolVar(&cfg.CliEnabled, "cli-enabled", false, "enable cli generation") flags.BoolVar(&cfg.CliCategories, "cli-categories", true, "enable cli categories") flags.BoolVar(&cfg.DisableWorkflowInputRename, "disable-workflow-input-rename", false, "disable renaming of \"WorkflowInput\"") + flags.BoolVar(&cfg.EnableCodec, "enable-codec", false, "enables experimental codec support") flags.BoolVar(&cfg.EnablePatchSupport, "enable-patch-support", false, "enables support for alta/protopatch renaming") flags.BoolVar(&cfg.EnableXNS, "enable-xns", false, "enable experimental cross-namespace workflow client") flags.BoolVar(&cfg.WorkflowUpdateEnabled, "workflow-update-enabled", false, "enable experimental workflow update") @@ -102,6 +104,9 @@ func (p *Plugin) Run(plugin *protogen.Plugin) error { svc.renderXNS(xns) hasXNS = true } + if svc.cfg.EnableCodec { + svc.renderCodec(f) + } hasContent = true } diff --git a/pkg/codec/codec.go b/pkg/codec/codec.go new file mode 100644 index 00000000..26c82f89 --- /dev/null +++ b/pkg/codec/codec.go @@ -0,0 +1,225 @@ +package codec + +import ( + "github.com/cludden/protoc-gen-go-temporal/pkg/scheme" + "go.temporal.io/api/common/v1" + "go.temporal.io/sdk/converter" + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" +) + +// ProtoJSONCodec implements a converter.PayloadCodec that provides conversion between +// binary/protobuf and json/protobuf encodings. It can be used in conjunction +// with converter.NewPayloadCodecHTTPHandler to implement a Remote Codec Server. +type ProtoJSONCodec struct { + scheme *scheme.Scheme +} + +// NewProtoJSONCodec initializes a new Codec value from one or more Scheme values +func NewProtoJSONCodec(schemes ...*scheme.Scheme) converter.PayloadCodec { + c := &ProtoJSONCodec{ + scheme: scheme.New(), + } + for _, scheme := range schemes { + c.scheme.Merge(scheme) + } + return c +} + +// Decode converts all binary/protobuf encoded payloads with registered +// message types to json/protobuf encoding to support Temporal UI automatic +// decoding. Any payloads with other encoding, or unregistered types are +// left unmodified. +func (c *ProtoJSONCodec) Decode(payloads []*common.Payload) ([]*common.Payload, error) { + results := make([]*common.Payload, len(payloads)) + for i, p := range payloads { + // skip non binary/protobuf payloads + if encoding, ok := p.GetMetadata()[converter.MetadataEncoding]; !ok || string(encoding) != converter.MetadataEncodingProto { + results[i] = p + continue + } + // skip payloads missing a message type header + t, ok := p.GetMetadata()[converter.MetadataMessageType] + if !ok { + results[i] = p + continue + } + // skip payloads with unregistered types + out, err := c.scheme.New(string(t)) + if err != nil || out == nil { + results[i] = p + continue + } + // skip payloads with invalid binary payload + if err := proto.Unmarshal(p.GetData(), out); err != nil { + results[i] = p + continue + } + // skip payloads that fail to serialize to json + b, err := protojson.Marshal(out) + if err != nil { + results[i] = p + continue + } + results[i] = &common.Payload{ + Data: b, + Metadata: map[string][]byte{ + converter.MetadataEncoding: []byte(converter.MetadataEncodingProtoJSON), + converter.MetadataMessageType: t, + }, + } + } + return results, nil +} + +// Encode converts all json/protobuf encoded payloads with registered message +// types to binary/protobuf encoding prior to being forwarded to Temporal. +func (c *ProtoJSONCodec) Encode(payloads []*common.Payload) ([]*common.Payload, error) { + results := make([]*common.Payload, len(payloads)) + for i, p := range payloads { + // skip non binary/protobuf payloads + if encoding, ok := p.GetMetadata()[converter.MetadataEncoding]; !ok || string(encoding) != converter.MetadataEncodingProtoJSON { + results[i] = p + continue + } + // skip payloads missing a message type header + t, ok := p.GetMetadata()[converter.MetadataMessageType] + if !ok { + results[i] = p + continue + } + // skip payloads with unregistered types + out, err := c.scheme.New(string(t)) + if err != nil || out == nil { + results[i] = p + continue + } + // skip payloads with invalid binary payload + if err := protojson.Unmarshal(p.GetData(), out); err != nil { + results[i] = p + continue + } + // skip payloads that fail to serialize to json + b, err := proto.Marshal(out) + if err != nil { + results[i] = p + continue + } + results[i] = &common.Payload{ + Data: b, + Metadata: map[string][]byte{ + converter.MetadataEncoding: []byte(converter.MetadataEncodingProto), + converter.MetadataMessageType: t, + }, + } + } + return results, nil +} + +// JSONCodec implements a converter.PayloadCodec that provides conversion between +// binary/protobuf and json/plain encodings. It can be used in conjunction +// with converter.NewPayloadCodecHTTPHandler to implement a Remote Codec Server. +type JSONCodec struct { + scheme *scheme.Scheme +} + +// NewJSONCodec initializes a new Codec value from one or more Scheme values +func NewJSONCodec(schemes ...*scheme.Scheme) converter.PayloadCodec { + c := &JSONCodec{ + scheme: scheme.New(), + } + for _, scheme := range schemes { + c.scheme.Merge(scheme) + } + return c +} + +// Decode converts all binary/protobuf encoded payloads with registered +// message types to json/protobuf encoding to support Temporal UI automatic +// decoding. Any payloads with other encoding, or unregistered types are +// left unmodified. +func (c *JSONCodec) Decode(payloads []*common.Payload) ([]*common.Payload, error) { + results := make([]*common.Payload, len(payloads)) + for i, p := range payloads { + // skip non binary/protobuf payloads + if encoding, ok := p.GetMetadata()[converter.MetadataEncoding]; !ok || string(encoding) != converter.MetadataEncodingProto { + results[i] = p + continue + } + // skip payloads missing a message type header + t, ok := p.GetMetadata()[converter.MetadataMessageType] + if !ok { + results[i] = p + continue + } + // skip payloads with unregistered types + out, err := c.scheme.New(string(t)) + if err != nil || out == nil { + results[i] = p + continue + } + // skip payloads with invalid binary payload + if err := proto.Unmarshal(p.GetData(), out); err != nil { + results[i] = p + continue + } + // skip payloads that fail to serialize to json + b, err := protojson.Marshal(out) + if err != nil { + results[i] = p + continue + } + results[i] = &common.Payload{ + Data: b, + Metadata: map[string][]byte{ + converter.MetadataEncoding: []byte(converter.MetadataEncodingJSON), + converter.MetadataMessageType: t, + }, + } + } + return results, nil +} + +// Encode converts all json/plain encoded payloads with registered message +// types to binary/protobuf encoding prior to being forwarded to Temporal. +func (c *JSONCodec) Encode(payloads []*common.Payload) ([]*common.Payload, error) { + results := make([]*common.Payload, len(payloads)) + for i, p := range payloads { + // skip non binary/protobuf payloads + if encoding, ok := p.GetMetadata()[converter.MetadataEncoding]; !ok || string(encoding) != converter.MetadataEncodingJSON { + results[i] = p + continue + } + // skip payloads missing a message type header + t, ok := p.GetMetadata()[converter.MetadataMessageType] + if !ok { + results[i] = p + continue + } + // skip payloads with unregistered types + out, err := c.scheme.New(string(t)) + if err != nil || out == nil { + results[i] = p + continue + } + // skip payloads with invalid binary payload + if err := protojson.Unmarshal(p.GetData(), out); err != nil { + results[i] = p + continue + } + // skip payloads that fail to serialize to json + b, err := proto.Marshal(out) + if err != nil { + results[i] = p + continue + } + results[i] = &common.Payload{ + Data: b, + Metadata: map[string][]byte{ + converter.MetadataEncoding: []byte(converter.MetadataEncodingProto), + converter.MetadataMessageType: t, + }, + } + } + return results, nil +} diff --git a/pkg/scheme/scheme.go b/pkg/scheme/scheme.go new file mode 100644 index 00000000..2e9e6964 --- /dev/null +++ b/pkg/scheme/scheme.go @@ -0,0 +1,70 @@ +package scheme + +import ( + "errors" + "sync" + + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/types/dynamicpb" +) + +// Option describes a functional configuration option for a Scheme value +type Option func(*Scheme) + +// From can initialize a new Scheme value from one or more existing Scheme values +func From(schemes ...*Scheme) Option { + return func(s *Scheme) { + s.Merge(schemes...) + } +} + +// Scheme implements a protobuf type registry that can be used to initialize +// dynamic messages by name +type Scheme struct { + m sync.Mutex + types map[string]protoreflect.MessageDescriptor +} + +// New initializes a new Scheme value. A given Scheme value can include +// multiple service type registrations. +func New(opts ...Option) *Scheme { + s := &Scheme{ + types: map[string]protoreflect.MessageDescriptor{}, + } + for _, opt := range opts { + opt(s) + } + return s +} + +// RegisterType registers the specified message with the current Scheme +func (s *Scheme) RegisterType(desc protoreflect.MessageDescriptor) { + if s == nil { + s = New() + } + s.m.Lock() + defer s.m.Unlock() + s.types[string(desc.FullName())] = desc +} + +// New initializes a new proto message of the given type +func (s *Scheme) New(t string) (protoreflect.ProtoMessage, error) { + if t, ok := s.types[t]; ok && t != nil { + return dynamicpb.NewMessage(t).Interface(), nil + } + return nil, errors.New("not found") +} + +// Merge can be used to merge multiple schemes into one +func (s *Scheme) Merge(schemes ...*Scheme) { + if s == nil { + s = &Scheme{} + } + for _, scheme := range schemes { + scheme.m.Lock() + defer scheme.m.Unlock() + for _, t := range scheme.types { + s.RegisterType(t) + } + } +} diff --git a/test/codec/codec_test.go b/test/codec/codec_test.go new file mode 100644 index 00000000..b404bd08 --- /dev/null +++ b/test/codec/codec_test.go @@ -0,0 +1,159 @@ +package codec + +import ( + "net/http/httptest" + "testing" + + "github.com/cludden/protoc-gen-go-temporal/gen/simple" + "github.com/cludden/protoc-gen-go-temporal/pkg/codec" + "github.com/cludden/protoc-gen-go-temporal/pkg/scheme" + "github.com/stretchr/testify/require" + "go.temporal.io/api/common/v1" + "go.temporal.io/sdk/converter" + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" +) + +func TestJSONCodec(t *testing.T) { + require := require.New(t) + + // initialize protobuf message value + msg := &simple.OtherWorkflowRequest{ + SomeVal: "example", + ExampleOneof: &simple.OtherWorkflowRequest_ExampleEnum{ + ExampleEnum: simple.OtherEnum_OTHER_FOO, + }, + } + + // initialize scheme + scheme := scheme.New( + simple.WithIgnoredSchemeTypes(), + simple.WithOtherSchemeTypes(), + simple.WithSimpleSchemeTypes(), + ) + var payloads []*common.Payload + + // marshal json/protobuf payload + protojsondc := converter.NewProtoJSONPayloadConverterWithOptions(converter.ProtoJSONPayloadConverterOptions{ + AllowUnknownFields: true, + }) + protojsonp, err := protojsondc.ToPayload(msg) + require.NoError(err) + require.Equal(string(converter.MetadataEncodingProtoJSON), string(protojsonp.Metadata[converter.MetadataEncoding])) + payloads = append(payloads, protojsonp) + + // marshal json/plain payload + jsondc := converter.NewJSONPayloadConverter() + jsonp, err := jsondc.ToPayload(msg) + require.NoError(err) + require.Equal(string(converter.MetadataEncodingJSON), string(jsonp.Metadata[converter.MetadataEncoding])) + payloads = append(payloads, jsonp) + + // marshal binary/protobuf payload + protodc := converter.NewProtoPayloadConverter() + protop, err := protodc.ToPayload(msg) + require.NoError(err) + require.Equal(string(converter.MetadataEncodingProto), string(protop.Metadata[converter.MetadataEncoding])) + payloads = append(payloads, protop) + + // verify decode successful + c := codec.NewJSONCodec(scheme) + results, err := c.Decode(payloads) + require.NoError(err) + require.Len(results, len(payloads)) + + // verify json/protobuf payload unchanged + require.Equal(protojsonp.Data, results[0].Data) + require.Equal(string(protojsonp.Metadata[converter.MetadataEncoding]), string(results[0].Metadata[converter.MetadataEncoding])) + require.Equal(string(protojsonp.Metadata[converter.MetadataMessageType]), string(results[0].Metadata[converter.MetadataMessageType])) + + // verify json/plain payload unchanged + require.Equal(jsonp.Data, results[1].Data) + require.Equal(string(jsonp.Metadata[converter.MetadataEncoding]), string(results[1].Metadata[converter.MetadataEncoding])) + + // verify binary/protobuf payload conversion to binary/protobuf + require.NotEqual(protop.Data, results[2].Data) + require.Equal(string(converter.MetadataEncodingJSON), string(results[2].Metadata[converter.MetadataEncoding])) + require.Equal(string(protop.Metadata[converter.MetadataMessageType]), string(results[2].Metadata[converter.MetadataMessageType])) + require.JSONEq(`{"someVal":"example","exampleEnum":"OTHER_FOO"}`, string(results[2].Data)) + + // verify conversion back to proto message value + var out simple.OtherWorkflowRequest + require.NoError(protojson.Unmarshal(results[2].Data, &out)) + require.True(proto.Equal(msg, &out)) + + handler := converter.NewPayloadCodecHTTPHandler(c) + srv := httptest.NewServer(handler) + defer srv.Close() + dc := converter.NewRemoteDataConverter(converter.NewCompositeDataConverter(jsondc), converter.RemoteDataConverterOptions{ + Endpoint: srv.URL, + }) + + jsonout := make(map[string]any) + require.NoError(dc.FromPayload(protop, &jsonout)) + require.Equal("example", jsonout["someVal"]) + require.Equal("OTHER_FOO", jsonout["exampleEnum"]) +} + +func TestProtoJSONCodec(t *testing.T) { + require := require.New(t) + + // initialize protobuf message value + msg := &simple.OtherWorkflowRequest{ + SomeVal: "example", + ExampleOneof: &simple.OtherWorkflowRequest_ExampleEnum{ + ExampleEnum: simple.OtherEnum_OTHER_FOO, + }, + } + + // initialize scheme + scheme := scheme.New( + simple.WithIgnoredSchemeTypes(), + simple.WithOtherSchemeTypes(), + simple.WithSimpleSchemeTypes(), + ) + var payloads []*common.Payload + + // marshal binary/protobuf payload + protodc := converter.NewProtoPayloadConverter() + protop, err := protodc.ToPayload(msg) + require.NoError(err) + require.Equal(string(converter.MetadataEncodingProto), string(protop.Metadata[converter.MetadataEncoding])) + payloads = append(payloads, protop) + + // verify decode successful + c := codec.NewProtoJSONCodec(scheme) + results, err := c.Decode(payloads) + require.NoError(err) + require.Len(results, len(payloads)) + + // verify binary/protobuf payload conversion to binary/protobuf + require.NotEqual(protop.Data, results[0].Data) + require.Equal(string(converter.MetadataEncodingProtoJSON), string(results[0].Metadata[converter.MetadataEncoding])) + require.Equal(string(protop.Metadata[converter.MetadataMessageType]), string(results[0].Metadata[converter.MetadataMessageType])) + require.JSONEq(`{"someVal":"example","exampleEnum":"OTHER_FOO"}`, string(results[0].Data)) + + // verify conversion back to proto message value + var out simple.OtherWorkflowRequest + require.NoError(protojson.Unmarshal(results[0].Data, &out)) + require.True(proto.Equal(msg, &out)) + + handler := converter.NewPayloadCodecHTTPHandler(c) + srv := httptest.NewServer(handler) + defer srv.Close() + dc := converter.NewRemoteDataConverter( + converter.NewCompositeDataConverter( + converter.NewProtoJSONPayloadConverterWithOptions(converter.ProtoJSONPayloadConverterOptions{ + AllowUnknownFields: true, + }), + ), + converter.RemoteDataConverterOptions{ + Endpoint: srv.URL, + }, + ) + + out = simple.OtherWorkflowRequest{} + require.NoError(dc.FromPayload(protop, &out)) + require.Equal(msg.SomeVal, out.SomeVal) + require.True(proto.Equal(msg, &out)) +} diff --git a/test/simple/simple.proto b/test/simple/simple.proto index 80d9bb73..b2e24d44 100644 --- a/test/simple/simple.proto +++ b/test/simple/simple.proto @@ -235,6 +235,7 @@ message OtherWorkflowRequest { google.protobuf.Duration example_duration = 21; google.protobuf.Empty example_empty = 22; google.protobuf.Timestamp example_timestamp = 23; + OtherEnum example_enum = 24; } message Bar { string bar = 1; @@ -260,6 +261,12 @@ message OtherUpdateRequest { message OtherUpdateResponse {} +enum OtherEnum { + OTHER_UNSPECIFIED = 0; + OTHER_FOO = 1; + OTHER_BAR = 2; +} + message Foo { string foo = 1; }