diff --git a/CHANGELOG.md b/CHANGELOG.md index b7068ae7..38ca128b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,41 +5,42 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). -## Unreleased +# Unreleased ### Added - -- [#62](https://github.com/cludden/protoc-gen-go-temporal/pull/62) add individual option override methods ### Changed ### Fixed -- [#65](https://github.com/cludden/protoc-gen-go-temporal/pull/65) wrap expression evaluation in local activities inside workflow contexts ([Patch Version 64](https://cludden.github.io/protoc-gen-go-temporal/docs/guides/patches#pv_64-expression-evaluation-local-activity)) -- [#66](https://github.com/cludden/protoc-gen-go-temporal/pull/66) fix cancellation propagation in xns activities +- [#68](https://github.com/cludden/protoc-gen-go-temporal/pull/68) prevent xns cancellation propagation on worker close -## [1.13.0](https://github.com/cludden/protoc-gen-go-temporal/releases/tag/v1.13.0) - 2024-05-03 -### Added + +# [1.13.0](https://github.com/cludden/protoc-gen-go-temporal/releases/tag/v1.13.0) - 2024-05-03 + +## Added - [#62](https://github.com/cludden/protoc-gen-go-temporal/pull/62) add individual option override methods -### Fixed +## Fixed - [#65](https://github.com/cludden/protoc-gen-go-temporal/pull/65) wrap expression evaluation in local activities inside workflow contexts ([Patch Version 64](https://cludden.github.io/protoc-gen-go-temporal/docs/guides/patches#pv_64-expression-evaluation-local-activity)) - [#66](https://github.com/cludden/protoc-gen-go-temporal/pull/66) fix cancellation propagation in xns activities -## [1.12.0](https://github.com/cludden/protoc-gen-go-temporal/releases/tag/v1.12.0) - 2024-04-19 + + +# [1.12.0](https://github.com/cludden/protoc-gen-go-temporal/releases/tag/v1.12.0) - 2024-04-19 -### Added +## Added - [0182d7b](https://github.com/cludden/protoc-gen-go-temporal/commit/0182d7bec153fb71636592bbf3a266937fe8bc97) add generated WorkflowFunction helpers - [#57](https://github.com/cludden/protoc-gen-go-temporal/pull/57) add missing WaitForCancellation for activity options -### Changed +## Changed - [#60](https://github.com/cludden/protoc-gen-go-temporal/pull/60) add additional details to expression evaluation errors -### Fixed +## Fixed - [84342c6](https://github.com/cludden/protoc-gen-go-temporal/commit/84342c6e9d6907bf080666572b100561964a4715) support brackets in bloblang expressions diff --git a/gen/example/helloworld/v1/example.pb.go b/gen/example/helloworld/v1/example.pb.go index e4c27b0b..7bc459b9 100644 --- a/gen/example/helloworld/v1/example.pb.go +++ b/gen/example/helloworld/v1/example.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.34.1 // protoc (unknown) // source: example/helloworld/v1/example.proto diff --git a/gen/example/helloworld/v1/example_temporal.pb.go b/gen/example/helloworld/v1/example_temporal.pb.go index b70b8830..0d6a440f 100644 --- a/gen/example/helloworld/v1/example_temporal.pb.go +++ b/gen/example/helloworld/v1/example_temporal.pb.go @@ -1,8 +1,8 @@ // Code generated by protoc-gen-go_temporal. DO NOT EDIT. // versions: // -// protoc-gen-go_temporal 1.12.1-next (ec80fd34c1a9a69042c74c5d3da0091b91ac2e0c) -// go go1.22.1 +// protoc-gen-go_temporal 1.13.1-next (fc19a4c83a5c93edb1c0e750533a8a5a3c44094e) +// go go1.22.3 // protoc (unknown) // // source: example/helloworld/v1/example.proto diff --git a/gen/example/helloworld/v1/helloworldv1xns/example_xns_temporal.pb.go b/gen/example/helloworld/v1/helloworldv1xns/example_xns_temporal.pb.go index 1019e138..e067cd03 100644 --- a/gen/example/helloworld/v1/helloworldv1xns/example_xns_temporal.pb.go +++ b/gen/example/helloworld/v1/helloworldv1xns/example_xns_temporal.pb.go @@ -1,8 +1,8 @@ // Code generated by protoc-gen-go_temporal. DO NOT EDIT. // versions: // -// protoc-gen-go_temporal 1.12.1-next (ec80fd34c1a9a69042c74c5d3da0091b91ac2e0c) -// go go1.22.1 +// protoc-gen-go_temporal 1.13.1-next (fc19a4c83a5c93edb1c0e750533a8a5a3c44094e) +// go go1.22.3 // protoc (unknown) // // source: example/helloworld/v1/example.proto @@ -13,10 +13,12 @@ import ( "errors" "fmt" v1 "github.com/cludden/protoc-gen-go-temporal/gen/example/helloworld/v1" - v11 "github.com/cludden/protoc-gen-go-temporal/gen/temporal/xns/v1" + v12 "github.com/cludden/protoc-gen-go-temporal/gen/temporal/v1" + v13 "github.com/cludden/protoc-gen-go-temporal/gen/temporal/xns/v1" expression "github.com/cludden/protoc-gen-go-temporal/pkg/expression" xns "github.com/cludden/protoc-gen-go-temporal/pkg/xns" uuid "github.com/google/uuid" + v11 "go.temporal.io/api/enums/v1" activity "go.temporal.io/sdk/activity" client "go.temporal.io/sdk/client" temporal "go.temporal.io/sdk/temporal" @@ -100,6 +102,7 @@ type HelloWorkflowOptions struct { ActivityOptions *workflow.ActivityOptions Detached bool HeartbeatInterval time.Duration + ParentClosePolicy v11.ParentClosePolicy StartWorkflowOptions *client.StartWorkflowOptions } @@ -126,6 +129,12 @@ func (opts *HelloWorkflowOptions) WithHeartbeatInterval(d time.Duration) *HelloW return opts } +// WithParentClosePolicy can be used to customize the cancellation propagation behavior +func (opts *HelloWorkflowOptions) WithParentClosePolicy(policy v11.ParentClosePolicy) *HelloWorkflowOptions { + opts.ParentClosePolicy = policy + return opts +} + // WithStartWorkflowOptions can be used to customize the start workflow options func (opts *HelloWorkflowOptions) WithStartWorkflow(swo client.StartWorkflowOptions) *HelloWorkflowOptions { opts.StartWorkflowOptions = &swo @@ -290,13 +299,24 @@ func HelloAsync(ctx workflow.Context, req *v1.HelloRequest, opts ...*HelloWorkfl return nil, fmt.Errorf("error marshalling workflow request: %w", err) } + var parentClosePolicy v12.ParentClosePolicy + switch opt.ParentClosePolicy { + case v11.PARENT_CLOSE_POLICY_ABANDON: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON + case v11.PARENT_CLOSE_POLICY_REQUEST_CANCEL: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL + case v11.PARENT_CLOSE_POLICY_TERMINATE: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_TERMINATE + } + ctx, cancel := workflow.WithCancel(ctx) return &helloRun{ cancel: cancel, id: wo.ID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.WorkflowRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.WorkflowRequest{ Detached: opt.Detached, HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), + ParentClosePolicy: parentClosePolicy, Request: wreq, StartWorkflowOptions: swo, }), @@ -415,7 +435,7 @@ func GoodbyeAsync(ctx workflow.Context, workflowID string, runID string, req *v1 ctx, cancel := workflow.WithCancel(ctx) return &goodbyeSignalHandle{ cancel: cancel, - future: workflow.ExecuteActivity(ctx, activityName, &v11.SignalRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.SignalRequest{ HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), WorkflowId: workflowID, RunId: runID, @@ -460,7 +480,7 @@ func (a *exampleActivities) CancelWorkflow(ctx context.Context, workflowID strin } // Hello executes a(n) example.v1.Hello workflow via an activity -func (a *exampleActivities) Hello(ctx context.Context, input *v11.WorkflowRequest) (resp *v1.HelloResponse, err error) { +func (a *exampleActivities) Hello(ctx context.Context, input *v13.WorkflowRequest) (resp *v1.HelloResponse, err error) { // unmarshal workflow request var req v1.HelloRequest if err := input.Request.UnmarshalTo(&req); err != nil { @@ -494,21 +514,48 @@ func (a *exampleActivities) Hello(ctx context.Context, input *v11.WorkflowReques heartbeatInterval := input.GetHeartbeatInterval().AsDuration() if heartbeatInterval == 0 { - heartbeatInterval = time.Minute + heartbeatInterval = time.Second * 30 } // heartbeat activity while waiting for workflow execution to complete for { select { + // send heartbeats periodically case <-time.After(heartbeatInterval): activity.RecordHeartbeat(ctx, run.ID()) + + // return retryable error on worker close + case <-activity.GetWorkerStopChannel(ctx): + return nil, temporal.NewApplicationError("worker is stopping", "WorkerStopped") + + // catch parent activity context cancellation. in most cases, this should indicate a + // server-sent cancellation, but there's a non-zero possibility that this cancellation + // is received due to the worker stopping, prior to detecting the closing of the worker + // stop channel. to give us an opportunity to detect a cancellation stemming from the + // worker closing, we again check to see if the worker stop channel is closed before + // propagating the cancellation case <-ctx.Done(): - disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) - defer cancel() - if err := run.Cancel(disconnectedCtx); err != nil { - return nil, exampleOptions.convertError(err) + select { + case <-activity.GetWorkerStopChannel(ctx): + return nil, temporal.NewApplicationError("worker is stopping", "WorkerStopped") + default: + parentClosePolicy := input.GetParentClosePolicy() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL || parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON { + disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) + defer cancel() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL { + err = run.Cancel(disconnectedCtx) + } else { + err = run.Terminate(disconnectedCtx, "xns activity cancellation received", "error", ctx.Err()) + } + if err != nil { + return nil, exampleOptions.convertError(err) + } + } + return nil, exampleOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) } - return nil, exampleOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) + + // handle workflow completion case <-doneCh: return resp, exampleOptions.convertError(err) } @@ -516,7 +563,7 @@ func (a *exampleActivities) Hello(ctx context.Context, input *v11.WorkflowReques } // Goodbye executes a(n) example.helloworld.v1.Example.Goodbye signal via an activity -func (a *exampleActivities) Goodbye(ctx context.Context, input *v11.SignalRequest) (err error) { +func (a *exampleActivities) Goodbye(ctx context.Context, input *v13.SignalRequest) (err error) { // unmarshal signal request var req v1.GoodbyeRequest if err := input.Request.UnmarshalTo(&req); err != nil { diff --git a/gen/example/mutex/v1/mutex.pb.go b/gen/example/mutex/v1/mutex.pb.go index 280a46db..64f58cc1 100644 --- a/gen/example/mutex/v1/mutex.pb.go +++ b/gen/example/mutex/v1/mutex.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.34.1 // protoc (unknown) // source: example/mutex/v1/mutex.proto diff --git a/gen/example/mutex/v1/mutex_temporal.pb.go b/gen/example/mutex/v1/mutex_temporal.pb.go index fbd14ef0..b2e729bb 100644 --- a/gen/example/mutex/v1/mutex_temporal.pb.go +++ b/gen/example/mutex/v1/mutex_temporal.pb.go @@ -1,8 +1,8 @@ // Code generated by protoc-gen-go_temporal. DO NOT EDIT. // versions: // -// protoc-gen-go_temporal 1.12.1-next (ec80fd34c1a9a69042c74c5d3da0091b91ac2e0c) -// go go1.22.1 +// protoc-gen-go_temporal 1.13.1-next (fc19a4c83a5c93edb1c0e750533a8a5a3c44094e) +// go go1.22.3 // protoc (unknown) // // source: example/mutex/v1/mutex.proto diff --git a/gen/example/mutex/v1/mutexv1xns/mutex_xns_temporal.pb.go b/gen/example/mutex/v1/mutexv1xns/mutex_xns_temporal.pb.go index 8b6a0ff9..39cec9df 100644 --- a/gen/example/mutex/v1/mutexv1xns/mutex_xns_temporal.pb.go +++ b/gen/example/mutex/v1/mutexv1xns/mutex_xns_temporal.pb.go @@ -1,8 +1,8 @@ // Code generated by protoc-gen-go_temporal. DO NOT EDIT. // versions: // -// protoc-gen-go_temporal 1.12.1-next (ec80fd34c1a9a69042c74c5d3da0091b91ac2e0c) -// go go1.22.1 +// protoc-gen-go_temporal 1.13.1-next (fc19a4c83a5c93edb1c0e750533a8a5a3c44094e) +// go go1.22.3 // protoc (unknown) // // source: example/mutex/v1/mutex.proto @@ -13,10 +13,12 @@ import ( "errors" "fmt" v1 "github.com/cludden/protoc-gen-go-temporal/gen/example/mutex/v1" - v11 "github.com/cludden/protoc-gen-go-temporal/gen/temporal/xns/v1" + v12 "github.com/cludden/protoc-gen-go-temporal/gen/temporal/v1" + v13 "github.com/cludden/protoc-gen-go-temporal/gen/temporal/xns/v1" expression "github.com/cludden/protoc-gen-go-temporal/pkg/expression" xns "github.com/cludden/protoc-gen-go-temporal/pkg/xns" uuid "github.com/google/uuid" + v11 "go.temporal.io/api/enums/v1" activity "go.temporal.io/sdk/activity" client "go.temporal.io/sdk/client" temporal "go.temporal.io/sdk/temporal" @@ -112,6 +114,7 @@ type MutexWorkflowOptions struct { ActivityOptions *workflow.ActivityOptions Detached bool HeartbeatInterval time.Duration + ParentClosePolicy v11.ParentClosePolicy StartWorkflowOptions *client.StartWorkflowOptions } @@ -138,6 +141,12 @@ func (opts *MutexWorkflowOptions) WithHeartbeatInterval(d time.Duration) *MutexW return opts } +// WithParentClosePolicy can be used to customize the cancellation propagation behavior +func (opts *MutexWorkflowOptions) WithParentClosePolicy(policy v11.ParentClosePolicy) *MutexWorkflowOptions { + opts.ParentClosePolicy = policy + return opts +} + // WithStartWorkflowOptions can be used to customize the start workflow options func (opts *MutexWorkflowOptions) WithStartWorkflow(swo client.StartWorkflowOptions) *MutexWorkflowOptions { opts.StartWorkflowOptions = &swo @@ -317,13 +326,24 @@ func MutexAsync(ctx workflow.Context, req *v1.MutexInput, opts ...*MutexWorkflow return nil, fmt.Errorf("error marshalling workflow request: %w", err) } + var parentClosePolicy v12.ParentClosePolicy + switch opt.ParentClosePolicy { + case v11.PARENT_CLOSE_POLICY_ABANDON: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON + case v11.PARENT_CLOSE_POLICY_REQUEST_CANCEL: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL + case v11.PARENT_CLOSE_POLICY_TERMINATE: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_TERMINATE + } + ctx, cancel := workflow.WithCancel(ctx) return &mutexRun{ cancel: cancel, id: wo.ID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.WorkflowRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.WorkflowRequest{ Detached: opt.Detached, HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), + ParentClosePolicy: parentClosePolicy, Request: wreq, StartWorkflowOptions: swo, }), @@ -429,7 +449,7 @@ func MutexWithAcquireLockAsync(ctx workflow.Context, req *v1.MutexInput, signal return &mutexRun{ cancel: cancel, id: wo.ID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.WorkflowRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.WorkflowRequest{ Detached: opt.Detached, HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), Request: wreq, @@ -444,6 +464,7 @@ type SampleWorkflowWithMutexWorkflowOptions struct { ActivityOptions *workflow.ActivityOptions Detached bool HeartbeatInterval time.Duration + ParentClosePolicy v11.ParentClosePolicy StartWorkflowOptions *client.StartWorkflowOptions } @@ -470,6 +491,12 @@ func (opts *SampleWorkflowWithMutexWorkflowOptions) WithHeartbeatInterval(d time return opts } +// WithParentClosePolicy can be used to customize the cancellation propagation behavior +func (opts *SampleWorkflowWithMutexWorkflowOptions) WithParentClosePolicy(policy v11.ParentClosePolicy) *SampleWorkflowWithMutexWorkflowOptions { + opts.ParentClosePolicy = policy + return opts +} + // WithStartWorkflowOptions can be used to customize the start workflow options func (opts *SampleWorkflowWithMutexWorkflowOptions) WithStartWorkflow(swo client.StartWorkflowOptions) *SampleWorkflowWithMutexWorkflowOptions { opts.StartWorkflowOptions = &swo @@ -633,13 +660,24 @@ func SampleWorkflowWithMutexAsync(ctx workflow.Context, req *v1.SampleWorkflowWi return nil, fmt.Errorf("error marshalling workflow request: %w", err) } + var parentClosePolicy v12.ParentClosePolicy + switch opt.ParentClosePolicy { + case v11.PARENT_CLOSE_POLICY_ABANDON: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON + case v11.PARENT_CLOSE_POLICY_REQUEST_CANCEL: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL + case v11.PARENT_CLOSE_POLICY_TERMINATE: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_TERMINATE + } + ctx, cancel := workflow.WithCancel(ctx) return &sampleWorkflowWithMutexRun{ cancel: cancel, id: wo.ID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.WorkflowRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.WorkflowRequest{ Detached: opt.Detached, HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), + ParentClosePolicy: parentClosePolicy, Request: wreq, StartWorkflowOptions: swo, }), @@ -758,7 +796,7 @@ func AcquireLockAsync(ctx workflow.Context, workflowID string, runID string, req ctx, cancel := workflow.WithCancel(ctx) return &acquireLockSignalHandle{ cancel: cancel, - future: workflow.ExecuteActivity(ctx, activityName, &v11.SignalRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.SignalRequest{ HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), WorkflowId: workflowID, RunId: runID, @@ -879,7 +917,7 @@ func LockAcquiredAsync(ctx workflow.Context, workflowID string, runID string, re ctx, cancel := workflow.WithCancel(ctx) return &lockAcquiredSignalHandle{ cancel: cancel, - future: workflow.ExecuteActivity(ctx, activityName, &v11.SignalRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.SignalRequest{ HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), WorkflowId: workflowID, RunId: runID, @@ -1000,7 +1038,7 @@ func ReleaseLockAsync(ctx workflow.Context, workflowID string, runID string, req ctx, cancel := workflow.WithCancel(ctx) return &releaseLockSignalHandle{ cancel: cancel, - future: workflow.ExecuteActivity(ctx, activityName, &v11.SignalRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.SignalRequest{ HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), WorkflowId: workflowID, RunId: runID, @@ -1045,7 +1083,7 @@ func (a *exampleActivities) CancelWorkflow(ctx context.Context, workflowID strin } // Mutex executes a(n) example.mutex.v1.Example.Mutex workflow via an activity -func (a *exampleActivities) Mutex(ctx context.Context, input *v11.WorkflowRequest) (err error) { +func (a *exampleActivities) Mutex(ctx context.Context, input *v13.WorkflowRequest) (err error) { // unmarshal workflow request var req v1.MutexInput if err := input.Request.UnmarshalTo(&req); err != nil { @@ -1079,21 +1117,48 @@ func (a *exampleActivities) Mutex(ctx context.Context, input *v11.WorkflowReques heartbeatInterval := input.GetHeartbeatInterval().AsDuration() if heartbeatInterval == 0 { - heartbeatInterval = time.Minute + heartbeatInterval = time.Second * 30 } // heartbeat activity while waiting for workflow execution to complete for { select { + // send heartbeats periodically case <-time.After(heartbeatInterval): activity.RecordHeartbeat(ctx, run.ID()) + + // return retryable error on worker close + case <-activity.GetWorkerStopChannel(ctx): + return temporal.NewApplicationError("worker is stopping", "WorkerStopped") + + // catch parent activity context cancellation. in most cases, this should indicate a + // server-sent cancellation, but there's a non-zero possibility that this cancellation + // is received due to the worker stopping, prior to detecting the closing of the worker + // stop channel. to give us an opportunity to detect a cancellation stemming from the + // worker closing, we again check to see if the worker stop channel is closed before + // propagating the cancellation case <-ctx.Done(): - disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) - defer cancel() - if err := run.Cancel(disconnectedCtx); err != nil { - return exampleOptions.convertError(err) + select { + case <-activity.GetWorkerStopChannel(ctx): + return temporal.NewApplicationError("worker is stopping", "WorkerStopped") + default: + parentClosePolicy := input.GetParentClosePolicy() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL || parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON { + disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) + defer cancel() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL { + err = run.Cancel(disconnectedCtx) + } else { + err = run.Terminate(disconnectedCtx, "xns activity cancellation received", "error", ctx.Err()) + } + if err != nil { + return exampleOptions.convertError(err) + } + } + return exampleOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) } - return exampleOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) + + // handle workflow completion case <-doneCh: return exampleOptions.convertError(err) } @@ -1101,7 +1166,7 @@ func (a *exampleActivities) Mutex(ctx context.Context, input *v11.WorkflowReques } // MutexWithAcquireLock sends a(n) example.mutex.v1.Example.AcquireLock signal to a(n) example.mutex.v1.Example.Mutex workflow via an activity -func (a *exampleActivities) MutexWithAcquireLock(ctx context.Context, input *v11.WorkflowRequest) (err error) { +func (a *exampleActivities) MutexWithAcquireLock(ctx context.Context, input *v13.WorkflowRequest) (err error) { // unmarshal workflow request var req v1.MutexInput if err := input.Request.UnmarshalTo(&req); err != nil { @@ -1167,7 +1232,7 @@ func (a *exampleActivities) MutexWithAcquireLock(ctx context.Context, input *v11 } // SampleWorkflowWithMutex executes a(n) example.mutex.v1.Example.SampleWorkflowWithMutex workflow via an activity -func (a *exampleActivities) SampleWorkflowWithMutex(ctx context.Context, input *v11.WorkflowRequest) (err error) { +func (a *exampleActivities) SampleWorkflowWithMutex(ctx context.Context, input *v13.WorkflowRequest) (err error) { // unmarshal workflow request var req v1.SampleWorkflowWithMutexInput if err := input.Request.UnmarshalTo(&req); err != nil { @@ -1201,21 +1266,48 @@ func (a *exampleActivities) SampleWorkflowWithMutex(ctx context.Context, input * heartbeatInterval := input.GetHeartbeatInterval().AsDuration() if heartbeatInterval == 0 { - heartbeatInterval = time.Minute + heartbeatInterval = time.Second * 30 } // heartbeat activity while waiting for workflow execution to complete for { select { + // send heartbeats periodically case <-time.After(heartbeatInterval): activity.RecordHeartbeat(ctx, run.ID()) + + // return retryable error on worker close + case <-activity.GetWorkerStopChannel(ctx): + return temporal.NewApplicationError("worker is stopping", "WorkerStopped") + + // catch parent activity context cancellation. in most cases, this should indicate a + // server-sent cancellation, but there's a non-zero possibility that this cancellation + // is received due to the worker stopping, prior to detecting the closing of the worker + // stop channel. to give us an opportunity to detect a cancellation stemming from the + // worker closing, we again check to see if the worker stop channel is closed before + // propagating the cancellation case <-ctx.Done(): - disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) - defer cancel() - if err := run.Cancel(disconnectedCtx); err != nil { - return exampleOptions.convertError(err) + select { + case <-activity.GetWorkerStopChannel(ctx): + return temporal.NewApplicationError("worker is stopping", "WorkerStopped") + default: + parentClosePolicy := input.GetParentClosePolicy() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL || parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON { + disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) + defer cancel() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL { + err = run.Cancel(disconnectedCtx) + } else { + err = run.Terminate(disconnectedCtx, "xns activity cancellation received", "error", ctx.Err()) + } + if err != nil { + return exampleOptions.convertError(err) + } + } + return exampleOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) } - return exampleOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) + + // handle workflow completion case <-doneCh: return exampleOptions.convertError(err) } @@ -1223,7 +1315,7 @@ func (a *exampleActivities) SampleWorkflowWithMutex(ctx context.Context, input * } // AcquireLock executes a(n) example.mutex.v1.Example.AcquireLock signal via an activity -func (a *exampleActivities) AcquireLock(ctx context.Context, input *v11.SignalRequest) (err error) { +func (a *exampleActivities) AcquireLock(ctx context.Context, input *v13.SignalRequest) (err error) { // unmarshal signal request var req v1.AcquireLockInput if err := input.Request.UnmarshalTo(&req); err != nil { @@ -1259,7 +1351,7 @@ func (a *exampleActivities) AcquireLock(ctx context.Context, input *v11.SignalRe } // LockAcquired executes a(n) example.mutex.v1.Example.LockAcquired signal via an activity -func (a *exampleActivities) LockAcquired(ctx context.Context, input *v11.SignalRequest) (err error) { +func (a *exampleActivities) LockAcquired(ctx context.Context, input *v13.SignalRequest) (err error) { // unmarshal signal request var req v1.LockAcquiredInput if err := input.Request.UnmarshalTo(&req); err != nil { @@ -1295,7 +1387,7 @@ func (a *exampleActivities) LockAcquired(ctx context.Context, input *v11.SignalR } // ReleaseLock executes a(n) example.mutex.v1.Example.ReleaseLock signal via an activity -func (a *exampleActivities) ReleaseLock(ctx context.Context, input *v11.SignalRequest) (err error) { +func (a *exampleActivities) ReleaseLock(ctx context.Context, input *v13.SignalRequest) (err error) { // unmarshal signal request var req v1.ReleaseLockInput if err := input.Request.UnmarshalTo(&req); err != nil { diff --git a/gen/example/searchattributes/v1/searchattributes.pb.go b/gen/example/searchattributes/v1/searchattributes.pb.go index b8d986df..32e09930 100644 --- a/gen/example/searchattributes/v1/searchattributes.pb.go +++ b/gen/example/searchattributes/v1/searchattributes.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.34.1 // protoc (unknown) // source: example/searchattributes/v1/searchattributes.proto diff --git a/gen/example/searchattributes/v1/searchattributes_temporal.pb.go b/gen/example/searchattributes/v1/searchattributes_temporal.pb.go index 626b1960..c7ccc574 100644 --- a/gen/example/searchattributes/v1/searchattributes_temporal.pb.go +++ b/gen/example/searchattributes/v1/searchattributes_temporal.pb.go @@ -1,8 +1,8 @@ // Code generated by protoc-gen-go_temporal. DO NOT EDIT. // versions: // -// protoc-gen-go_temporal 1.12.1-next (ec80fd34c1a9a69042c74c5d3da0091b91ac2e0c) -// go go1.22.1 +// protoc-gen-go_temporal 1.13.1-next (fc19a4c83a5c93edb1c0e750533a8a5a3c44094e) +// go go1.22.3 // protoc (unknown) // // source: example/searchattributes/v1/searchattributes.proto diff --git a/gen/example/searchattributes/v1/searchattributesv1xns/searchattributes_xns_temporal.pb.go b/gen/example/searchattributes/v1/searchattributesv1xns/searchattributes_xns_temporal.pb.go index 52deca05..c33593ca 100644 --- a/gen/example/searchattributes/v1/searchattributesv1xns/searchattributes_xns_temporal.pb.go +++ b/gen/example/searchattributes/v1/searchattributesv1xns/searchattributes_xns_temporal.pb.go @@ -1,8 +1,8 @@ // Code generated by protoc-gen-go_temporal. DO NOT EDIT. // versions: // -// protoc-gen-go_temporal 1.12.1-next (ec80fd34c1a9a69042c74c5d3da0091b91ac2e0c) -// go go1.22.1 +// protoc-gen-go_temporal 1.13.1-next (fc19a4c83a5c93edb1c0e750533a8a5a3c44094e) +// go go1.22.3 // protoc (unknown) // // source: example/searchattributes/v1/searchattributes.proto @@ -13,10 +13,12 @@ import ( "errors" "fmt" v1 "github.com/cludden/protoc-gen-go-temporal/gen/example/searchattributes/v1" - v11 "github.com/cludden/protoc-gen-go-temporal/gen/temporal/xns/v1" + v12 "github.com/cludden/protoc-gen-go-temporal/gen/temporal/v1" + v13 "github.com/cludden/protoc-gen-go-temporal/gen/temporal/xns/v1" expression "github.com/cludden/protoc-gen-go-temporal/pkg/expression" xns "github.com/cludden/protoc-gen-go-temporal/pkg/xns" uuid "github.com/google/uuid" + v11 "go.temporal.io/api/enums/v1" activity "go.temporal.io/sdk/activity" client "go.temporal.io/sdk/client" temporal "go.temporal.io/sdk/temporal" @@ -97,6 +99,7 @@ type SearchAttributesWorkflowOptions struct { ActivityOptions *workflow.ActivityOptions Detached bool HeartbeatInterval time.Duration + ParentClosePolicy v11.ParentClosePolicy StartWorkflowOptions *client.StartWorkflowOptions } @@ -123,6 +126,12 @@ func (opts *SearchAttributesWorkflowOptions) WithHeartbeatInterval(d time.Durati return opts } +// WithParentClosePolicy can be used to customize the cancellation propagation behavior +func (opts *SearchAttributesWorkflowOptions) WithParentClosePolicy(policy v11.ParentClosePolicy) *SearchAttributesWorkflowOptions { + opts.ParentClosePolicy = policy + return opts +} + // WithStartWorkflowOptions can be used to customize the start workflow options func (opts *SearchAttributesWorkflowOptions) WithStartWorkflow(swo client.StartWorkflowOptions) *SearchAttributesWorkflowOptions { opts.StartWorkflowOptions = &swo @@ -270,13 +279,24 @@ func SearchAttributesAsync(ctx workflow.Context, req *v1.SearchAttributesInput, return nil, fmt.Errorf("error marshalling workflow request: %w", err) } + var parentClosePolicy v12.ParentClosePolicy + switch opt.ParentClosePolicy { + case v11.PARENT_CLOSE_POLICY_ABANDON: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON + case v11.PARENT_CLOSE_POLICY_REQUEST_CANCEL: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL + case v11.PARENT_CLOSE_POLICY_TERMINATE: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_TERMINATE + } + ctx, cancel := workflow.WithCancel(ctx) return &searchAttributesRun{ cancel: cancel, id: wo.ID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.WorkflowRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.WorkflowRequest{ Detached: opt.Detached, HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), + ParentClosePolicy: parentClosePolicy, Request: wreq, StartWorkflowOptions: swo, }), @@ -319,7 +339,7 @@ func (a *exampleActivities) CancelWorkflow(ctx context.Context, workflowID strin } // SearchAttributes executes a(n) example.searchattributes.v1.Example.SearchAttributes workflow via an activity -func (a *exampleActivities) SearchAttributes(ctx context.Context, input *v11.WorkflowRequest) (err error) { +func (a *exampleActivities) SearchAttributes(ctx context.Context, input *v13.WorkflowRequest) (err error) { // unmarshal workflow request var req v1.SearchAttributesInput if err := input.Request.UnmarshalTo(&req); err != nil { @@ -353,21 +373,48 @@ func (a *exampleActivities) SearchAttributes(ctx context.Context, input *v11.Wor heartbeatInterval := input.GetHeartbeatInterval().AsDuration() if heartbeatInterval == 0 { - heartbeatInterval = time.Minute + heartbeatInterval = time.Second * 30 } // heartbeat activity while waiting for workflow execution to complete for { select { + // send heartbeats periodically case <-time.After(heartbeatInterval): activity.RecordHeartbeat(ctx, run.ID()) + + // return retryable error on worker close + case <-activity.GetWorkerStopChannel(ctx): + return temporal.NewApplicationError("worker is stopping", "WorkerStopped") + + // catch parent activity context cancellation. in most cases, this should indicate a + // server-sent cancellation, but there's a non-zero possibility that this cancellation + // is received due to the worker stopping, prior to detecting the closing of the worker + // stop channel. to give us an opportunity to detect a cancellation stemming from the + // worker closing, we again check to see if the worker stop channel is closed before + // propagating the cancellation case <-ctx.Done(): - disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) - defer cancel() - if err := run.Cancel(disconnectedCtx); err != nil { - return exampleOptions.convertError(err) + select { + case <-activity.GetWorkerStopChannel(ctx): + return temporal.NewApplicationError("worker is stopping", "WorkerStopped") + default: + parentClosePolicy := input.GetParentClosePolicy() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL || parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON { + disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) + defer cancel() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL { + err = run.Cancel(disconnectedCtx) + } else { + err = run.Terminate(disconnectedCtx, "xns activity cancellation received", "error", ctx.Err()) + } + if err != nil { + return exampleOptions.convertError(err) + } + } + return exampleOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) } - return exampleOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) + + // handle workflow completion case <-doneCh: return exampleOptions.convertError(err) } diff --git a/gen/example/updatabletimer/v1/updatabletimer.pb.go b/gen/example/updatabletimer/v1/updatabletimer.pb.go index 9ff6731a..560f9ca7 100644 --- a/gen/example/updatabletimer/v1/updatabletimer.pb.go +++ b/gen/example/updatabletimer/v1/updatabletimer.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.34.1 // protoc (unknown) // source: example/updatabletimer/v1/updatabletimer.proto diff --git a/gen/example/updatabletimer/v1/updatabletimer_temporal.pb.go b/gen/example/updatabletimer/v1/updatabletimer_temporal.pb.go index 7cead292..7a129e6a 100644 --- a/gen/example/updatabletimer/v1/updatabletimer_temporal.pb.go +++ b/gen/example/updatabletimer/v1/updatabletimer_temporal.pb.go @@ -1,8 +1,8 @@ // Code generated by protoc-gen-go_temporal. DO NOT EDIT. // versions: // -// protoc-gen-go_temporal 1.12.1-next (ec80fd34c1a9a69042c74c5d3da0091b91ac2e0c) -// go go1.22.1 +// protoc-gen-go_temporal 1.13.1-next (fc19a4c83a5c93edb1c0e750533a8a5a3c44094e) +// go go1.22.3 // protoc (unknown) // // source: example/updatabletimer/v1/updatabletimer.proto diff --git a/gen/example/updatabletimer/v1/updatabletimerv1xns/updatabletimer_xns_temporal.pb.go b/gen/example/updatabletimer/v1/updatabletimerv1xns/updatabletimer_xns_temporal.pb.go index 39ca23cb..ede98356 100644 --- a/gen/example/updatabletimer/v1/updatabletimerv1xns/updatabletimer_xns_temporal.pb.go +++ b/gen/example/updatabletimer/v1/updatabletimerv1xns/updatabletimer_xns_temporal.pb.go @@ -1,8 +1,8 @@ // Code generated by protoc-gen-go_temporal. DO NOT EDIT. // versions: // -// protoc-gen-go_temporal 1.12.1-next (ec80fd34c1a9a69042c74c5d3da0091b91ac2e0c) -// go go1.22.1 +// protoc-gen-go_temporal 1.13.1-next (fc19a4c83a5c93edb1c0e750533a8a5a3c44094e) +// go go1.22.3 // protoc (unknown) // // source: example/updatabletimer/v1/updatabletimer.proto @@ -13,10 +13,12 @@ import ( "errors" "fmt" v1 "github.com/cludden/protoc-gen-go-temporal/gen/example/updatabletimer/v1" - v11 "github.com/cludden/protoc-gen-go-temporal/gen/temporal/xns/v1" + v12 "github.com/cludden/protoc-gen-go-temporal/gen/temporal/v1" + v13 "github.com/cludden/protoc-gen-go-temporal/gen/temporal/xns/v1" expression "github.com/cludden/protoc-gen-go-temporal/pkg/expression" xns "github.com/cludden/protoc-gen-go-temporal/pkg/xns" uuid "github.com/google/uuid" + v11 "go.temporal.io/api/enums/v1" activity "go.temporal.io/sdk/activity" client "go.temporal.io/sdk/client" temporal "go.temporal.io/sdk/temporal" @@ -103,6 +105,7 @@ type UpdatableTimerWorkflowOptions struct { ActivityOptions *workflow.ActivityOptions Detached bool HeartbeatInterval time.Duration + ParentClosePolicy v11.ParentClosePolicy StartWorkflowOptions *client.StartWorkflowOptions } @@ -129,6 +132,12 @@ func (opts *UpdatableTimerWorkflowOptions) WithHeartbeatInterval(d time.Duration return opts } +// WithParentClosePolicy can be used to customize the cancellation propagation behavior +func (opts *UpdatableTimerWorkflowOptions) WithParentClosePolicy(policy v11.ParentClosePolicy) *UpdatableTimerWorkflowOptions { + opts.ParentClosePolicy = policy + return opts +} + // WithStartWorkflowOptions can be used to customize the start workflow options func (opts *UpdatableTimerWorkflowOptions) WithStartWorkflow(swo client.StartWorkflowOptions) *UpdatableTimerWorkflowOptions { opts.StartWorkflowOptions = &swo @@ -308,13 +317,24 @@ func UpdatableTimerAsync(ctx workflow.Context, req *v1.UpdatableTimerInput, opts return nil, fmt.Errorf("error marshalling workflow request: %w", err) } + var parentClosePolicy v12.ParentClosePolicy + switch opt.ParentClosePolicy { + case v11.PARENT_CLOSE_POLICY_ABANDON: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON + case v11.PARENT_CLOSE_POLICY_REQUEST_CANCEL: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL + case v11.PARENT_CLOSE_POLICY_TERMINATE: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_TERMINATE + } + ctx, cancel := workflow.WithCancel(ctx) return &updatableTimerRun{ cancel: cancel, id: wo.ID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.WorkflowRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.WorkflowRequest{ Detached: opt.Detached, HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), + ParentClosePolicy: parentClosePolicy, Request: wreq, StartWorkflowOptions: swo, }), @@ -433,7 +453,7 @@ func GetWakeUpTimeAsync(ctx workflow.Context, workflowID string, runID string, o ctx, cancel := workflow.WithCancel(ctx) return &getWakeUpTimeQueryHandle{ cancel: cancel, - future: workflow.ExecuteActivity(ctx, activityName, &v11.QueryRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.QueryRequest{ HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), WorkflowId: workflowID, RunId: runID, @@ -553,7 +573,7 @@ func UpdateWakeUpTimeAsync(ctx workflow.Context, workflowID string, runID string ctx, cancel := workflow.WithCancel(ctx) return &updateWakeUpTimeSignalHandle{ cancel: cancel, - future: workflow.ExecuteActivity(ctx, activityName, &v11.SignalRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.SignalRequest{ HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), WorkflowId: workflowID, RunId: runID, @@ -598,7 +618,7 @@ func (a *exampleActivities) CancelWorkflow(ctx context.Context, workflowID strin } // UpdatableTimer executes a(n) UpdatableTimer workflow via an activity -func (a *exampleActivities) UpdatableTimer(ctx context.Context, input *v11.WorkflowRequest) (err error) { +func (a *exampleActivities) UpdatableTimer(ctx context.Context, input *v13.WorkflowRequest) (err error) { // unmarshal workflow request var req v1.UpdatableTimerInput if err := input.Request.UnmarshalTo(&req); err != nil { @@ -632,21 +652,48 @@ func (a *exampleActivities) UpdatableTimer(ctx context.Context, input *v11.Workf heartbeatInterval := input.GetHeartbeatInterval().AsDuration() if heartbeatInterval == 0 { - heartbeatInterval = time.Minute + heartbeatInterval = time.Second * 30 } // heartbeat activity while waiting for workflow execution to complete for { select { + // send heartbeats periodically case <-time.After(heartbeatInterval): activity.RecordHeartbeat(ctx, run.ID()) + + // return retryable error on worker close + case <-activity.GetWorkerStopChannel(ctx): + return temporal.NewApplicationError("worker is stopping", "WorkerStopped") + + // catch parent activity context cancellation. in most cases, this should indicate a + // server-sent cancellation, but there's a non-zero possibility that this cancellation + // is received due to the worker stopping, prior to detecting the closing of the worker + // stop channel. to give us an opportunity to detect a cancellation stemming from the + // worker closing, we again check to see if the worker stop channel is closed before + // propagating the cancellation case <-ctx.Done(): - disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) - defer cancel() - if err := run.Cancel(disconnectedCtx); err != nil { - return exampleOptions.convertError(err) + select { + case <-activity.GetWorkerStopChannel(ctx): + return temporal.NewApplicationError("worker is stopping", "WorkerStopped") + default: + parentClosePolicy := input.GetParentClosePolicy() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL || parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON { + disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) + defer cancel() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL { + err = run.Cancel(disconnectedCtx) + } else { + err = run.Terminate(disconnectedCtx, "xns activity cancellation received", "error", ctx.Err()) + } + if err != nil { + return exampleOptions.convertError(err) + } + } + return exampleOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) } - return exampleOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) + + // handle workflow completion case <-doneCh: return exampleOptions.convertError(err) } @@ -654,7 +701,7 @@ func (a *exampleActivities) UpdatableTimer(ctx context.Context, input *v11.Workf } // GetWakeUpTime executes a(n) example.updatabletimer.v1.Example.GetWakeUpTime query via an activity -func (a *exampleActivities) GetWakeUpTime(ctx context.Context, input *v11.QueryRequest) (resp *v1.GetWakeUpTimeOutput, err error) { +func (a *exampleActivities) GetWakeUpTime(ctx context.Context, input *v13.QueryRequest) (resp *v1.GetWakeUpTimeOutput, err error) { // execute signal in child goroutine doneCh := make(chan struct{}) go func() { @@ -681,7 +728,7 @@ func (a *exampleActivities) GetWakeUpTime(ctx context.Context, input *v11.QueryR } // UpdateWakeUpTime executes a(n) example.updatabletimer.v1.Example.UpdateWakeUpTime signal via an activity -func (a *exampleActivities) UpdateWakeUpTime(ctx context.Context, input *v11.SignalRequest) (err error) { +func (a *exampleActivities) UpdateWakeUpTime(ctx context.Context, input *v13.SignalRequest) (err error) { // unmarshal signal request var req v1.UpdateWakeUpTimeInput if err := input.Request.UnmarshalTo(&req); err != nil { diff --git a/gen/example/v1/example.pb.go b/gen/example/v1/example.pb.go index 060cb515..130117bf 100644 --- a/gen/example/v1/example.pb.go +++ b/gen/example/v1/example.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.34.1 // protoc (unknown) // source: example/v1/example.proto diff --git a/gen/example/v1/example_temporal.pb.go b/gen/example/v1/example_temporal.pb.go index 89bd91cb..43fc824a 100644 --- a/gen/example/v1/example_temporal.pb.go +++ b/gen/example/v1/example_temporal.pb.go @@ -1,8 +1,8 @@ // Code generated by protoc-gen-go_temporal. DO NOT EDIT. // versions: // -// protoc-gen-go_temporal 1.12.1-next (ec80fd34c1a9a69042c74c5d3da0091b91ac2e0c) -// go go1.22.1 +// protoc-gen-go_temporal 1.13.1-next (fc19a4c83a5c93edb1c0e750533a8a5a3c44094e) +// go go1.22.3 // protoc (unknown) // // source: example/v1/example.proto diff --git a/gen/example/v1/examplev1xns/example_xns_temporal.pb.go b/gen/example/v1/examplev1xns/example_xns_temporal.pb.go index fba10f9a..72c5b561 100644 --- a/gen/example/v1/examplev1xns/example_xns_temporal.pb.go +++ b/gen/example/v1/examplev1xns/example_xns_temporal.pb.go @@ -1,8 +1,8 @@ // Code generated by protoc-gen-go_temporal. DO NOT EDIT. // versions: // -// protoc-gen-go_temporal 1.12.1-next (ec80fd34c1a9a69042c74c5d3da0091b91ac2e0c) -// go go1.22.1 +// protoc-gen-go_temporal 1.13.1-next (fc19a4c83a5c93edb1c0e750533a8a5a3c44094e) +// go go1.22.3 // protoc (unknown) // // source: example/v1/example.proto @@ -13,12 +13,13 @@ import ( "errors" "fmt" v1 "github.com/cludden/protoc-gen-go-temporal/gen/example/v1" - v11 "github.com/cludden/protoc-gen-go-temporal/gen/temporal/xns/v1" + v12 "github.com/cludden/protoc-gen-go-temporal/gen/temporal/v1" + v13 "github.com/cludden/protoc-gen-go-temporal/gen/temporal/xns/v1" expression "github.com/cludden/protoc-gen-go-temporal/pkg/expression" xns "github.com/cludden/protoc-gen-go-temporal/pkg/xns" uuid "github.com/google/uuid" - v13 "go.temporal.io/api/enums/v1" - v12 "go.temporal.io/api/update/v1" + v11 "go.temporal.io/api/enums/v1" + v14 "go.temporal.io/api/update/v1" activity "go.temporal.io/sdk/activity" client "go.temporal.io/sdk/client" temporal "go.temporal.io/sdk/temporal" @@ -111,6 +112,7 @@ type CreateFooWorkflowOptions struct { ActivityOptions *workflow.ActivityOptions Detached bool HeartbeatInterval time.Duration + ParentClosePolicy v11.ParentClosePolicy StartWorkflowOptions *client.StartWorkflowOptions } @@ -137,6 +139,12 @@ func (opts *CreateFooWorkflowOptions) WithHeartbeatInterval(d time.Duration) *Cr return opts } +// WithParentClosePolicy can be used to customize the cancellation propagation behavior +func (opts *CreateFooWorkflowOptions) WithParentClosePolicy(policy v11.ParentClosePolicy) *CreateFooWorkflowOptions { + opts.ParentClosePolicy = policy + return opts +} + // WithStartWorkflowOptions can be used to customize the start workflow options func (opts *CreateFooWorkflowOptions) WithStartWorkflow(swo client.StartWorkflowOptions) *CreateFooWorkflowOptions { opts.StartWorkflowOptions = &swo @@ -333,13 +341,24 @@ func CreateFooAsync(ctx workflow.Context, req *v1.CreateFooRequest, opts ...*Cre return nil, fmt.Errorf("error marshalling workflow request: %w", err) } + var parentClosePolicy v12.ParentClosePolicy + switch opt.ParentClosePolicy { + case v11.PARENT_CLOSE_POLICY_ABANDON: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON + case v11.PARENT_CLOSE_POLICY_REQUEST_CANCEL: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL + case v11.PARENT_CLOSE_POLICY_TERMINATE: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_TERMINATE + } + ctx, cancel := workflow.WithCancel(ctx) return &createFooRun{ cancel: cancel, id: wo.ID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.WorkflowRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.WorkflowRequest{ Detached: opt.Detached, HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), + ParentClosePolicy: parentClosePolicy, Request: wreq, StartWorkflowOptions: swo, }), @@ -445,7 +464,7 @@ func CreateFooWithSetFooProgressAsync(ctx workflow.Context, req *v1.CreateFooReq return &createFooRun{ cancel: cancel, id: wo.ID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.WorkflowRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.WorkflowRequest{ Detached: opt.Detached, HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), Request: wreq, @@ -567,7 +586,7 @@ func GetFooProgressAsync(ctx workflow.Context, workflowID string, runID string, ctx, cancel := workflow.WithCancel(ctx) return &getFooProgressQueryHandle{ cancel: cancel, - future: workflow.ExecuteActivity(ctx, activityName, &v11.QueryRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.QueryRequest{ HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), WorkflowId: workflowID, RunId: runID, @@ -687,7 +706,7 @@ func SetFooProgressAsync(ctx workflow.Context, workflowID string, runID string, ctx, cancel := workflow.WithCancel(ctx) return &setFooProgressSignalHandle{ cancel: cancel, - future: workflow.ExecuteActivity(ctx, activityName, &v11.SignalRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.SignalRequest{ HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), WorkflowId: workflowID, RunId: runID, @@ -869,7 +888,7 @@ func UpdateFooProgressAsync(ctx workflow.Context, workflowID string, runID strin return &updateFooProgressHandle{ cancel: cancel, id: uo.UpdateID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.UpdateRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.UpdateRequest{ HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), Request: wreq, UpdateWorkflowOptions: uopb, @@ -913,7 +932,7 @@ func (a *exampleActivities) CancelWorkflow(ctx context.Context, workflowID strin } // CreateFoo executes a(n) example.v1.Example.CreateFoo workflow via an activity -func (a *exampleActivities) CreateFoo(ctx context.Context, input *v11.WorkflowRequest) (resp *v1.CreateFooResponse, err error) { +func (a *exampleActivities) CreateFoo(ctx context.Context, input *v13.WorkflowRequest) (resp *v1.CreateFooResponse, err error) { // unmarshal workflow request var req v1.CreateFooRequest if err := input.Request.UnmarshalTo(&req); err != nil { @@ -947,21 +966,48 @@ func (a *exampleActivities) CreateFoo(ctx context.Context, input *v11.WorkflowRe heartbeatInterval := input.GetHeartbeatInterval().AsDuration() if heartbeatInterval == 0 { - heartbeatInterval = time.Minute + heartbeatInterval = time.Second * 30 } // heartbeat activity while waiting for workflow execution to complete for { select { + // send heartbeats periodically case <-time.After(heartbeatInterval): activity.RecordHeartbeat(ctx, run.ID()) + + // return retryable error on worker close + case <-activity.GetWorkerStopChannel(ctx): + return nil, temporal.NewApplicationError("worker is stopping", "WorkerStopped") + + // catch parent activity context cancellation. in most cases, this should indicate a + // server-sent cancellation, but there's a non-zero possibility that this cancellation + // is received due to the worker stopping, prior to detecting the closing of the worker + // stop channel. to give us an opportunity to detect a cancellation stemming from the + // worker closing, we again check to see if the worker stop channel is closed before + // propagating the cancellation case <-ctx.Done(): - disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) - defer cancel() - if err := run.Cancel(disconnectedCtx); err != nil { - return nil, exampleOptions.convertError(err) + select { + case <-activity.GetWorkerStopChannel(ctx): + return nil, temporal.NewApplicationError("worker is stopping", "WorkerStopped") + default: + parentClosePolicy := input.GetParentClosePolicy() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL || parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON { + disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) + defer cancel() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL { + err = run.Cancel(disconnectedCtx) + } else { + err = run.Terminate(disconnectedCtx, "xns activity cancellation received", "error", ctx.Err()) + } + if err != nil { + return nil, exampleOptions.convertError(err) + } + } + return nil, exampleOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) } - return nil, exampleOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) + + // handle workflow completion case <-doneCh: return resp, exampleOptions.convertError(err) } @@ -969,7 +1015,7 @@ func (a *exampleActivities) CreateFoo(ctx context.Context, input *v11.WorkflowRe } // CreateFooWithSetFooProgress sends a(n) example.v1.Example.SetFooProgress signal to a(n) example.v1.Example.CreateFoo workflow via an activity -func (a *exampleActivities) CreateFooWithSetFooProgress(ctx context.Context, input *v11.WorkflowRequest) (resp *v1.CreateFooResponse, err error) { +func (a *exampleActivities) CreateFooWithSetFooProgress(ctx context.Context, input *v13.WorkflowRequest) (resp *v1.CreateFooResponse, err error) { // unmarshal workflow request var req v1.CreateFooRequest if err := input.Request.UnmarshalTo(&req); err != nil { @@ -1035,7 +1081,7 @@ func (a *exampleActivities) CreateFooWithSetFooProgress(ctx context.Context, inp } // GetFooProgress executes a(n) example.v1.Example.GetFooProgress query via an activity -func (a *exampleActivities) GetFooProgress(ctx context.Context, input *v11.QueryRequest) (resp *v1.GetFooProgressResponse, err error) { +func (a *exampleActivities) GetFooProgress(ctx context.Context, input *v13.QueryRequest) (resp *v1.GetFooProgressResponse, err error) { // execute signal in child goroutine doneCh := make(chan struct{}) go func() { @@ -1062,7 +1108,7 @@ func (a *exampleActivities) GetFooProgress(ctx context.Context, input *v11.Query } // SetFooProgress executes a(n) example.v1.Example.SetFooProgress signal via an activity -func (a *exampleActivities) SetFooProgress(ctx context.Context, input *v11.SignalRequest) (err error) { +func (a *exampleActivities) SetFooProgress(ctx context.Context, input *v13.SignalRequest) (err error) { // unmarshal signal request var req v1.SetFooProgressRequest if err := input.Request.UnmarshalTo(&req); err != nil { @@ -1098,7 +1144,7 @@ func (a *exampleActivities) SetFooProgress(ctx context.Context, input *v11.Signa } // UpdateFooProgress executes a(n) example.v1.Example.UpdateFooProgress update via an activity -func (a *exampleActivities) UpdateFooProgress(ctx context.Context, input *v11.UpdateRequest) (resp *v1.GetFooProgressResponse, err error) { +func (a *exampleActivities) UpdateFooProgress(ctx context.Context, input *v13.UpdateRequest) (resp *v1.GetFooProgressResponse, err error) { var handle v1.UpdateFooProgressHandle if activity.HasHeartbeatDetails(ctx) { // extract update id from heartbeat details @@ -1128,8 +1174,8 @@ func (a *exampleActivities) UpdateFooProgress(ctx context.Context, input *v11.Up } uo := xns.UnmarshalUpdateWorkflowOptions(input.GetUpdateWorkflowOptions()) - uo.WaitPolicy = &v12.WaitPolicy{ - LifecycleStage: v13.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ACCEPTED, + uo.WaitPolicy = &v14.WaitPolicy{ + LifecycleStage: v11.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ACCEPTED, } // initialize update execution diff --git a/gen/example/xns/v1/xns.pb.go b/gen/example/xns/v1/xns.pb.go index 35926111..c48d43d8 100644 --- a/gen/example/xns/v1/xns.pb.go +++ b/gen/example/xns/v1/xns.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.34.1 // protoc (unknown) // source: example/xns/v1/xns.proto diff --git a/gen/example/xns/v1/xns_temporal.pb.go b/gen/example/xns/v1/xns_temporal.pb.go index 5fdec977..e5515732 100644 --- a/gen/example/xns/v1/xns_temporal.pb.go +++ b/gen/example/xns/v1/xns_temporal.pb.go @@ -1,8 +1,8 @@ // Code generated by protoc-gen-go_temporal. DO NOT EDIT. // versions: // -// protoc-gen-go_temporal 1.12.1-next (ec80fd34c1a9a69042c74c5d3da0091b91ac2e0c) -// go go1.22.1 +// protoc-gen-go_temporal 1.13.1-next (fc19a4c83a5c93edb1c0e750533a8a5a3c44094e) +// go go1.22.3 // protoc (unknown) // // source: example/xns/v1/xns.proto diff --git a/gen/example/xns/v1/xnsv1xns/xns_xns_temporal.pb.go b/gen/example/xns/v1/xnsv1xns/xns_xns_temporal.pb.go index 30b5180c..0b3973f2 100644 --- a/gen/example/xns/v1/xnsv1xns/xns_xns_temporal.pb.go +++ b/gen/example/xns/v1/xnsv1xns/xns_xns_temporal.pb.go @@ -1,8 +1,8 @@ // Code generated by protoc-gen-go_temporal. DO NOT EDIT. // versions: // -// protoc-gen-go_temporal 1.12.1-next (ec80fd34c1a9a69042c74c5d3da0091b91ac2e0c) -// go go1.22.1 +// protoc-gen-go_temporal 1.13.1-next (fc19a4c83a5c93edb1c0e750533a8a5a3c44094e) +// go go1.22.3 // protoc (unknown) // // source: example/xns/v1/xns.proto @@ -13,12 +13,13 @@ import ( "errors" "fmt" v1 "github.com/cludden/protoc-gen-go-temporal/gen/example/xns/v1" - v11 "github.com/cludden/protoc-gen-go-temporal/gen/temporal/xns/v1" + v12 "github.com/cludden/protoc-gen-go-temporal/gen/temporal/v1" + v13 "github.com/cludden/protoc-gen-go-temporal/gen/temporal/xns/v1" expression "github.com/cludden/protoc-gen-go-temporal/pkg/expression" xns "github.com/cludden/protoc-gen-go-temporal/pkg/xns" uuid "github.com/google/uuid" - v13 "go.temporal.io/api/enums/v1" - v12 "go.temporal.io/api/update/v1" + v11 "go.temporal.io/api/enums/v1" + v14 "go.temporal.io/api/update/v1" activity "go.temporal.io/sdk/activity" client "go.temporal.io/sdk/client" temporal "go.temporal.io/sdk/temporal" @@ -99,6 +100,7 @@ type ProvisionFooWorkflowOptions struct { ActivityOptions *workflow.ActivityOptions Detached bool HeartbeatInterval time.Duration + ParentClosePolicy v11.ParentClosePolicy StartWorkflowOptions *client.StartWorkflowOptions } @@ -125,6 +127,12 @@ func (opts *ProvisionFooWorkflowOptions) WithHeartbeatInterval(d time.Duration) return opts } +// WithParentClosePolicy can be used to customize the cancellation propagation behavior +func (opts *ProvisionFooWorkflowOptions) WithParentClosePolicy(policy v11.ParentClosePolicy) *ProvisionFooWorkflowOptions { + opts.ParentClosePolicy = policy + return opts +} + // WithStartWorkflowOptions can be used to customize the start workflow options func (opts *ProvisionFooWorkflowOptions) WithStartWorkflow(swo client.StartWorkflowOptions) *ProvisionFooWorkflowOptions { opts.StartWorkflowOptions = &swo @@ -273,13 +281,24 @@ func ProvisionFooAsync(ctx workflow.Context, req *v1.ProvisionFooRequest, opts . return nil, fmt.Errorf("error marshalling workflow request: %w", err) } + var parentClosePolicy v12.ParentClosePolicy + switch opt.ParentClosePolicy { + case v11.PARENT_CLOSE_POLICY_ABANDON: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON + case v11.PARENT_CLOSE_POLICY_REQUEST_CANCEL: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL + case v11.PARENT_CLOSE_POLICY_TERMINATE: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_TERMINATE + } + ctx, cancel := workflow.WithCancel(ctx) return &provisionFooRun{ cancel: cancel, id: wo.ID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.WorkflowRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.WorkflowRequest{ Detached: opt.Detached, HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), + ParentClosePolicy: parentClosePolicy, Request: wreq, StartWorkflowOptions: swo, }), @@ -322,7 +341,7 @@ func (a *xnsActivities) CancelWorkflow(ctx context.Context, workflowID string, r } // ProvisionFoo executes a(n) example.xns.v1.Xns.ProvisionFoo workflow via an activity -func (a *xnsActivities) ProvisionFoo(ctx context.Context, input *v11.WorkflowRequest) (resp *v1.ProvisionFooResponse, err error) { +func (a *xnsActivities) ProvisionFoo(ctx context.Context, input *v13.WorkflowRequest) (resp *v1.ProvisionFooResponse, err error) { // unmarshal workflow request var req v1.ProvisionFooRequest if err := input.Request.UnmarshalTo(&req); err != nil { @@ -356,21 +375,48 @@ func (a *xnsActivities) ProvisionFoo(ctx context.Context, input *v11.WorkflowReq heartbeatInterval := input.GetHeartbeatInterval().AsDuration() if heartbeatInterval == 0 { - heartbeatInterval = time.Minute + heartbeatInterval = time.Second * 30 } // heartbeat activity while waiting for workflow execution to complete for { select { + // send heartbeats periodically case <-time.After(heartbeatInterval): activity.RecordHeartbeat(ctx, run.ID()) + + // return retryable error on worker close + case <-activity.GetWorkerStopChannel(ctx): + return nil, temporal.NewApplicationError("worker is stopping", "WorkerStopped") + + // catch parent activity context cancellation. in most cases, this should indicate a + // server-sent cancellation, but there's a non-zero possibility that this cancellation + // is received due to the worker stopping, prior to detecting the closing of the worker + // stop channel. to give us an opportunity to detect a cancellation stemming from the + // worker closing, we again check to see if the worker stop channel is closed before + // propagating the cancellation case <-ctx.Done(): - disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) - defer cancel() - if err := run.Cancel(disconnectedCtx); err != nil { - return nil, xnsOptions.convertError(err) + select { + case <-activity.GetWorkerStopChannel(ctx): + return nil, temporal.NewApplicationError("worker is stopping", "WorkerStopped") + default: + parentClosePolicy := input.GetParentClosePolicy() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL || parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON { + disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) + defer cancel() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL { + err = run.Cancel(disconnectedCtx) + } else { + err = run.Terminate(disconnectedCtx, "xns activity cancellation received", "error", ctx.Err()) + } + if err != nil { + return nil, xnsOptions.convertError(err) + } + } + return nil, xnsOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) } - return nil, xnsOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) + + // handle workflow completion case <-doneCh: return resp, xnsOptions.convertError(err) } @@ -459,6 +505,7 @@ type CreateFooWorkflowOptions struct { ActivityOptions *workflow.ActivityOptions Detached bool HeartbeatInterval time.Duration + ParentClosePolicy v11.ParentClosePolicy StartWorkflowOptions *client.StartWorkflowOptions } @@ -485,6 +532,12 @@ func (opts *CreateFooWorkflowOptions) WithHeartbeatInterval(d time.Duration) *Cr return opts } +// WithParentClosePolicy can be used to customize the cancellation propagation behavior +func (opts *CreateFooWorkflowOptions) WithParentClosePolicy(policy v11.ParentClosePolicy) *CreateFooWorkflowOptions { + opts.ParentClosePolicy = policy + return opts +} + // WithStartWorkflowOptions can be used to customize the start workflow options func (opts *CreateFooWorkflowOptions) WithStartWorkflow(swo client.StartWorkflowOptions) *CreateFooWorkflowOptions { opts.StartWorkflowOptions = &swo @@ -681,13 +734,24 @@ func CreateFooAsync(ctx workflow.Context, req *v1.CreateFooRequest, opts ...*Cre return nil, fmt.Errorf("error marshalling workflow request: %w", err) } + var parentClosePolicy v12.ParentClosePolicy + switch opt.ParentClosePolicy { + case v11.PARENT_CLOSE_POLICY_ABANDON: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON + case v11.PARENT_CLOSE_POLICY_REQUEST_CANCEL: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL + case v11.PARENT_CLOSE_POLICY_TERMINATE: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_TERMINATE + } + ctx, cancel := workflow.WithCancel(ctx) return &createFooRun{ cancel: cancel, id: wo.ID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.WorkflowRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.WorkflowRequest{ Detached: opt.Detached, HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), + ParentClosePolicy: parentClosePolicy, Request: wreq, StartWorkflowOptions: swo, }), @@ -793,7 +857,7 @@ func CreateFooWithSetFooProgressAsync(ctx workflow.Context, req *v1.CreateFooReq return &createFooRun{ cancel: cancel, id: wo.ID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.WorkflowRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.WorkflowRequest{ Detached: opt.Detached, HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), Request: wreq, @@ -915,7 +979,7 @@ func GetFooProgressAsync(ctx workflow.Context, workflowID string, runID string, ctx, cancel := workflow.WithCancel(ctx) return &getFooProgressQueryHandle{ cancel: cancel, - future: workflow.ExecuteActivity(ctx, activityName, &v11.QueryRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.QueryRequest{ HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), WorkflowId: workflowID, RunId: runID, @@ -1035,7 +1099,7 @@ func SetFooProgressAsync(ctx workflow.Context, workflowID string, runID string, ctx, cancel := workflow.WithCancel(ctx) return &setFooProgressSignalHandle{ cancel: cancel, - future: workflow.ExecuteActivity(ctx, activityName, &v11.SignalRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.SignalRequest{ HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), WorkflowId: workflowID, RunId: runID, @@ -1217,7 +1281,7 @@ func UpdateFooProgressAsync(ctx workflow.Context, workflowID string, runID strin return &updateFooProgressHandle{ cancel: cancel, id: uo.UpdateID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.UpdateRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.UpdateRequest{ HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), Request: wreq, UpdateWorkflowOptions: uopb, @@ -1261,7 +1325,7 @@ func (a *exampleActivities) CancelWorkflow(ctx context.Context, workflowID strin } // CreateFoo executes a(n) example.xns.v1.Example.CreateFoo workflow via an activity -func (a *exampleActivities) CreateFoo(ctx context.Context, input *v11.WorkflowRequest) (resp *v1.CreateFooResponse, err error) { +func (a *exampleActivities) CreateFoo(ctx context.Context, input *v13.WorkflowRequest) (resp *v1.CreateFooResponse, err error) { // unmarshal workflow request var req v1.CreateFooRequest if err := input.Request.UnmarshalTo(&req); err != nil { @@ -1295,21 +1359,48 @@ func (a *exampleActivities) CreateFoo(ctx context.Context, input *v11.WorkflowRe heartbeatInterval := input.GetHeartbeatInterval().AsDuration() if heartbeatInterval == 0 { - heartbeatInterval = time.Minute + heartbeatInterval = time.Second * 30 } // heartbeat activity while waiting for workflow execution to complete for { select { + // send heartbeats periodically case <-time.After(heartbeatInterval): activity.RecordHeartbeat(ctx, run.ID()) + + // return retryable error on worker close + case <-activity.GetWorkerStopChannel(ctx): + return nil, temporal.NewApplicationError("worker is stopping", "WorkerStopped") + + // catch parent activity context cancellation. in most cases, this should indicate a + // server-sent cancellation, but there's a non-zero possibility that this cancellation + // is received due to the worker stopping, prior to detecting the closing of the worker + // stop channel. to give us an opportunity to detect a cancellation stemming from the + // worker closing, we again check to see if the worker stop channel is closed before + // propagating the cancellation case <-ctx.Done(): - disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) - defer cancel() - if err := run.Cancel(disconnectedCtx); err != nil { - return nil, exampleOptions.convertError(err) + select { + case <-activity.GetWorkerStopChannel(ctx): + return nil, temporal.NewApplicationError("worker is stopping", "WorkerStopped") + default: + parentClosePolicy := input.GetParentClosePolicy() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL || parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON { + disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) + defer cancel() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL { + err = run.Cancel(disconnectedCtx) + } else { + err = run.Terminate(disconnectedCtx, "xns activity cancellation received", "error", ctx.Err()) + } + if err != nil { + return nil, exampleOptions.convertError(err) + } + } + return nil, exampleOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) } - return nil, exampleOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) + + // handle workflow completion case <-doneCh: return resp, exampleOptions.convertError(err) } @@ -1317,7 +1408,7 @@ func (a *exampleActivities) CreateFoo(ctx context.Context, input *v11.WorkflowRe } // CreateFooWithSetFooProgress sends a(n) example.xns.v1.Example.SetFooProgress signal to a(n) example.xns.v1.Example.CreateFoo workflow via an activity -func (a *exampleActivities) CreateFooWithSetFooProgress(ctx context.Context, input *v11.WorkflowRequest) (resp *v1.CreateFooResponse, err error) { +func (a *exampleActivities) CreateFooWithSetFooProgress(ctx context.Context, input *v13.WorkflowRequest) (resp *v1.CreateFooResponse, err error) { // unmarshal workflow request var req v1.CreateFooRequest if err := input.Request.UnmarshalTo(&req); err != nil { @@ -1383,7 +1474,7 @@ func (a *exampleActivities) CreateFooWithSetFooProgress(ctx context.Context, inp } // GetFooProgress executes a(n) example.xns.v1.Example.GetFooProgress query via an activity -func (a *exampleActivities) GetFooProgress(ctx context.Context, input *v11.QueryRequest) (resp *v1.GetFooProgressResponse, err error) { +func (a *exampleActivities) GetFooProgress(ctx context.Context, input *v13.QueryRequest) (resp *v1.GetFooProgressResponse, err error) { // execute signal in child goroutine doneCh := make(chan struct{}) go func() { @@ -1410,7 +1501,7 @@ func (a *exampleActivities) GetFooProgress(ctx context.Context, input *v11.Query } // SetFooProgress executes a(n) example.xns.v1.Example.SetFooProgress signal via an activity -func (a *exampleActivities) SetFooProgress(ctx context.Context, input *v11.SignalRequest) (err error) { +func (a *exampleActivities) SetFooProgress(ctx context.Context, input *v13.SignalRequest) (err error) { // unmarshal signal request var req v1.SetFooProgressRequest if err := input.Request.UnmarshalTo(&req); err != nil { @@ -1446,7 +1537,7 @@ func (a *exampleActivities) SetFooProgress(ctx context.Context, input *v11.Signa } // UpdateFooProgress executes a(n) example.xns.v1.Example.UpdateFooProgress update via an activity -func (a *exampleActivities) UpdateFooProgress(ctx context.Context, input *v11.UpdateRequest) (resp *v1.GetFooProgressResponse, err error) { +func (a *exampleActivities) UpdateFooProgress(ctx context.Context, input *v13.UpdateRequest) (resp *v1.GetFooProgressResponse, err error) { var handle v1.UpdateFooProgressHandle if activity.HasHeartbeatDetails(ctx) { // extract update id from heartbeat details @@ -1476,8 +1567,8 @@ func (a *exampleActivities) UpdateFooProgress(ctx context.Context, input *v11.Up } uo := xns.UnmarshalUpdateWorkflowOptions(input.GetUpdateWorkflowOptions()) - uo.WaitPolicy = &v12.WaitPolicy{ - LifecycleStage: v13.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ACCEPTED, + uo.WaitPolicy = &v14.WaitPolicy{ + LifecycleStage: v11.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ACCEPTED, } // initialize update execution diff --git a/gen/patch/go.pb.go b/gen/patch/go.pb.go index 80279bd8..5e9d367f 100644 --- a/gen/patch/go.pb.go +++ b/gen/patch/go.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.34.1 // protoc (unknown) // source: patch/go.proto diff --git a/gen/temporal/v1/temporal.pb.go b/gen/temporal/v1/temporal.pb.go index 58bfcf8d..478b0c5e 100644 --- a/gen/temporal/v1/temporal.pb.go +++ b/gen/temporal/v1/temporal.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.34.1 // protoc (unknown) // source: temporal/v1/temporal.proto @@ -1236,6 +1236,8 @@ type XNSActivityOptions struct { HeartbeatTimeout *durationpb.Duration `protobuf:"bytes,5,opt,name=heartbeat_timeout,json=heartbeatTimeout,proto3" json:"heartbeat_timeout,omitempty"` // Specifies how to retry an Activity if an error occurs RetryPolicy *RetryPolicy `protobuf:"bytes,6,opt,name=retry_policy,json=retryPolicy,proto3" json:"retry_policy,omitempty"` + // Specifies how activity cancellation is propagated for xns activities that support it + ParentClosePolicy ParentClosePolicy `protobuf:"varint,9,opt,name=parent_close_policy,json=parentClosePolicy,proto3,enum=temporal.v1.ParentClosePolicy" json:"parent_close_policy,omitempty"` } func (x *XNSActivityOptions) Reset() { @@ -1326,6 +1328,13 @@ func (x *XNSActivityOptions) GetRetryPolicy() *RetryPolicy { return nil } +func (x *XNSActivityOptions) GetParentClosePolicy() ParentClosePolicy { + if x != nil { + return x.ParentClosePolicy + } + return ParentClosePolicy_PARENT_CLOSE_POLICY_UNSPECIFIED +} + // Query identifies a query supported by the worklow type WorkflowOptions_Query struct { state protoimpl.MessageState @@ -1792,7 +1801,7 @@ var file_temporal_v1_temporal_proto_rawDesc = []byte{ 0x72, 0x65, 0x66, 0x12, 0x31, 0x0a, 0x03, 0x78, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x58, 0x4e, 0x53, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x52, 0x03, 0x78, 0x6e, 0x73, 0x22, 0x92, 0x04, 0x0a, 0x12, 0x58, 0x4e, 0x53, 0x41, 0x63, + 0x73, 0x52, 0x03, 0x78, 0x6e, 0x73, 0x22, 0xe2, 0x04, 0x0a, 0x12, 0x58, 0x4e, 0x53, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x71, 0x75, 0x65, 0x75, 0x65, 0x18, @@ -1825,7 +1834,12 @@ var file_temporal_v1_temporal_proto_rawDesc = []byte{ 0x0a, 0x0c, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0b, - 0x72, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2a, 0x3f, 0x0a, 0x0a, 0x43, + 0x72, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x4e, 0x0a, 0x13, 0x70, + 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x5f, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x74, 0x65, 0x6d, 0x70, 0x6f, + 0x72, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x43, 0x6c, 0x6f, + 0x73, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x11, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, + 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2a, 0x3f, 0x0a, 0x0a, 0x43, 0x4c, 0x49, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x43, 0x4c, 0x49, 0x5f, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x44, 0x49, 0x53, 0x41, 0x4c, 0x42, 0x45, 0x44, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x43, 0x4c, 0x49, 0x5f, 0x46, 0x45, 0x41, 0x54, 0x55, @@ -1997,30 +2011,31 @@ var file_temporal_v1_temporal_proto_depIdxs = []int32{ 20, // 31: temporal.v1.XNSActivityOptions.heartbeat_interval:type_name -> google.protobuf.Duration 20, // 32: temporal.v1.XNSActivityOptions.heartbeat_timeout:type_name -> google.protobuf.Duration 11, // 33: temporal.v1.XNSActivityOptions.retry_policy:type_name -> temporal.v1.RetryPolicy - 16, // 34: temporal.v1.WorkflowOptions.Query.xns:type_name -> temporal.v1.XNSActivityOptions - 16, // 35: temporal.v1.WorkflowOptions.Signal.xns:type_name -> temporal.v1.XNSActivityOptions - 16, // 36: temporal.v1.WorkflowOptions.Update.xns:type_name -> temporal.v1.XNSActivityOptions - 21, // 37: temporal.v1.service:extendee -> google.protobuf.ServiceOptions - 21, // 38: temporal.v1.cli:extendee -> google.protobuf.ServiceOptions - 22, // 39: temporal.v1.activity:extendee -> google.protobuf.MethodOptions - 22, // 40: temporal.v1.command:extendee -> google.protobuf.MethodOptions - 22, // 41: temporal.v1.query:extendee -> google.protobuf.MethodOptions - 22, // 42: temporal.v1.signal:extendee -> google.protobuf.MethodOptions - 22, // 43: temporal.v1.update:extendee -> google.protobuf.MethodOptions - 22, // 44: temporal.v1.workflow:extendee -> google.protobuf.MethodOptions - 12, // 45: temporal.v1.service:type_name -> temporal.v1.ServiceOptions - 7, // 46: temporal.v1.cli:type_name -> temporal.v1.CLIOptions - 6, // 47: temporal.v1.activity:type_name -> temporal.v1.ActivityOptions - 8, // 48: temporal.v1.command:type_name -> temporal.v1.CommandOptions - 10, // 49: temporal.v1.query:type_name -> temporal.v1.QueryOptions - 13, // 50: temporal.v1.signal:type_name -> temporal.v1.SignalOptions - 14, // 51: temporal.v1.update:type_name -> temporal.v1.UpdateOptions - 15, // 52: temporal.v1.workflow:type_name -> temporal.v1.WorkflowOptions - 53, // [53:53] is the sub-list for method output_type - 53, // [53:53] is the sub-list for method input_type - 45, // [45:53] is the sub-list for extension type_name - 37, // [37:45] is the sub-list for extension extendee - 0, // [0:37] is the sub-list for field type_name + 2, // 34: temporal.v1.XNSActivityOptions.parent_close_policy:type_name -> temporal.v1.ParentClosePolicy + 16, // 35: temporal.v1.WorkflowOptions.Query.xns:type_name -> temporal.v1.XNSActivityOptions + 16, // 36: temporal.v1.WorkflowOptions.Signal.xns:type_name -> temporal.v1.XNSActivityOptions + 16, // 37: temporal.v1.WorkflowOptions.Update.xns:type_name -> temporal.v1.XNSActivityOptions + 21, // 38: temporal.v1.service:extendee -> google.protobuf.ServiceOptions + 21, // 39: temporal.v1.cli:extendee -> google.protobuf.ServiceOptions + 22, // 40: temporal.v1.activity:extendee -> google.protobuf.MethodOptions + 22, // 41: temporal.v1.command:extendee -> google.protobuf.MethodOptions + 22, // 42: temporal.v1.query:extendee -> google.protobuf.MethodOptions + 22, // 43: temporal.v1.signal:extendee -> google.protobuf.MethodOptions + 22, // 44: temporal.v1.update:extendee -> google.protobuf.MethodOptions + 22, // 45: temporal.v1.workflow:extendee -> google.protobuf.MethodOptions + 12, // 46: temporal.v1.service:type_name -> temporal.v1.ServiceOptions + 7, // 47: temporal.v1.cli:type_name -> temporal.v1.CLIOptions + 6, // 48: temporal.v1.activity:type_name -> temporal.v1.ActivityOptions + 8, // 49: temporal.v1.command:type_name -> temporal.v1.CommandOptions + 10, // 50: temporal.v1.query:type_name -> temporal.v1.QueryOptions + 13, // 51: temporal.v1.signal:type_name -> temporal.v1.SignalOptions + 14, // 52: temporal.v1.update:type_name -> temporal.v1.UpdateOptions + 15, // 53: temporal.v1.workflow:type_name -> temporal.v1.WorkflowOptions + 54, // [54:54] is the sub-list for method output_type + 54, // [54:54] is the sub-list for method input_type + 46, // [46:54] is the sub-list for extension type_name + 38, // [38:46] is the sub-list for extension extendee + 0, // [0:38] is the sub-list for field type_name } func init() { file_temporal_v1_temporal_proto_init() } diff --git a/gen/temporal/xns/v1/xns.pb.go b/gen/temporal/xns/v1/xns.pb.go index 6dd7fe91..9f6426e9 100644 --- a/gen/temporal/xns/v1/xns.pb.go +++ b/gen/temporal/xns/v1/xns.pb.go @@ -1,12 +1,13 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.34.1 // protoc (unknown) // source: temporal/xns/v1/xns.proto package xnsv1 import ( + v1 "github.com/cludden/protoc-gen-go-temporal/gen/temporal/v1" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" _ "google.golang.org/protobuf/types/descriptorpb" @@ -709,6 +710,7 @@ type WorkflowRequest struct { Request *anypb.Any `protobuf:"bytes,3,opt,name=request,proto3" json:"request,omitempty"` Detached bool `protobuf:"varint,4,opt,name=detached,proto3" json:"detached,omitempty"` Signal *anypb.Any `protobuf:"bytes,5,opt,name=signal,proto3" json:"signal,omitempty"` + ParentClosePolicy v1.ParentClosePolicy `protobuf:"varint,6,opt,name=parent_close_policy,json=parentClosePolicy,proto3,enum=temporal.v1.ParentClosePolicy" json:"parent_close_policy,omitempty"` } func (x *WorkflowRequest) Reset() { @@ -778,6 +780,13 @@ func (x *WorkflowRequest) GetSignal() *anypb.Any { return nil } +func (x *WorkflowRequest) GetParentClosePolicy() v1.ParentClosePolicy { + if x != nil { + return x.ParentClosePolicy + } + return v1.ParentClosePolicy(0) +} + var File_temporal_xns_v1_xns_proto protoreflect.FileDescriptor var file_temporal_xns_v1_xns_proto_rawDesc = []byte{ @@ -791,189 +800,196 @@ var file_temporal_xns_v1_xns_proto_rawDesc = []byte{ 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, - 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc0, 0x01, 0x0a, 0x0c, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x72, 0x75, 0x6e, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x75, 0x6e, 0x49, 0x64, 0x12, - 0x1f, 0x0a, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, - 0x12, 0x2e, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x48, 0x0a, 0x12, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x5f, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, - 0x61, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x22, 0xa0, 0x02, 0x0a, 0x0b, 0x52, - 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x44, 0x0a, 0x10, 0x69, 0x6e, - 0x69, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x0f, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, - 0x12, 0x2f, 0x0a, 0x13, 0x62, 0x61, 0x63, 0x6b, 0x6f, 0x66, 0x66, 0x5f, 0x63, 0x6f, 0x65, 0x66, - 0x66, 0x69, 0x63, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x12, 0x62, - 0x61, 0x63, 0x6b, 0x6f, 0x66, 0x66, 0x43, 0x6f, 0x65, 0x66, 0x66, 0x69, 0x63, 0x69, 0x65, 0x6e, - 0x74, 0x12, 0x3c, 0x0a, 0x0c, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, - 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, - 0x21, 0x0a, 0x0c, 0x6d, 0x61, 0x78, 0x5f, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x73, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, - 0x74, 0x73, 0x12, 0x39, 0x0a, 0x19, 0x6e, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x79, 0x61, - 0x62, 0x6c, 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, - 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x16, 0x6e, 0x6f, 0x6e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x61, - 0x62, 0x6c, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, 0xc1, 0x01, - 0x0a, 0x0d, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x15, 0x0a, 0x06, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x72, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, - 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x6f, 0x72, - 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x07, - 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x48, 0x0a, 0x12, 0x68, 0x65, 0x61, 0x72, 0x74, - 0x62, 0x65, 0x61, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, - 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, - 0x6c, 0x22, 0xaa, 0x05, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, - 0x6c, 0x6f, 0x77, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x61, - 0x73, 0x6b, 0x5f, 0x71, 0x75, 0x65, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x74, 0x61, 0x73, 0x6b, 0x51, 0x75, 0x65, 0x75, 0x65, 0x12, 0x46, 0x0a, 0x11, 0x65, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x10, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, - 0x74, 0x12, 0x3a, 0x0a, 0x0b, 0x72, 0x75, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x0a, 0x72, 0x75, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x3c, 0x0a, - 0x0c, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x05, 0x20, + 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1a, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, + 0x6c, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x6c, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x22, 0xc0, 0x01, 0x0a, 0x0c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x77, + 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x07, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x41, 0x6e, 0x79, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x48, 0x0a, 0x12, + 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, + 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x49, 0x6e, + 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x22, 0xa0, 0x02, 0x0a, 0x0b, 0x52, 0x65, 0x74, 0x72, 0x79, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x44, 0x0a, 0x10, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, + 0x6c, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x69, 0x6e, 0x69, + 0x74, 0x69, 0x61, 0x6c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x2f, 0x0a, 0x13, + 0x62, 0x61, 0x63, 0x6b, 0x6f, 0x66, 0x66, 0x5f, 0x63, 0x6f, 0x65, 0x66, 0x66, 0x69, 0x63, 0x69, + 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x12, 0x62, 0x61, 0x63, 0x6b, 0x6f, + 0x66, 0x66, 0x43, 0x6f, 0x65, 0x66, 0x66, 0x69, 0x63, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x3c, 0x0a, + 0x0c, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, - 0x74, 0x61, 0x73, 0x6b, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x46, 0x0a, 0x0f, 0x69, - 0x64, 0x5f, 0x72, 0x65, 0x75, 0x73, 0x65, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x6c, 0x2e, - 0x78, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x44, 0x52, 0x65, 0x75, 0x73, 0x65, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0d, 0x69, 0x64, 0x52, 0x65, 0x75, 0x73, 0x65, 0x50, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x12, 0x3b, 0x0a, 0x1a, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x77, 0x68, 0x65, - 0x6e, 0x5f, 0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, - 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x57, 0x68, - 0x65, 0x6e, 0x41, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, - 0x12, 0x3f, 0x0a, 0x0c, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, - 0x6c, 0x2e, 0x78, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0b, 0x72, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x12, 0x2b, 0x0a, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x12, 0x44, - 0x0a, 0x11, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5f, 0x61, 0x74, 0x74, 0x69, 0x72, 0x62, 0x75, - 0x74, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, - 0x63, 0x74, 0x52, 0x10, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x41, 0x74, 0x74, 0x69, 0x72, 0x62, - 0x75, 0x74, 0x65, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x65, - 0x61, 0x67, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x10, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x61, 0x67, 0x65, 0x72, 0x53, 0x74, 0x61, - 0x72, 0x74, 0x12, 0x3a, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x61, - 0x79, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x22, 0xf4, - 0x01, 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x48, 0x0a, 0x12, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x5f, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, - 0x61, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x69, 0x0a, 0x17, 0x75, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x6f, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x74, 0x65, - 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x6c, 0x2e, 0x78, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x57, 0x69, 0x74, 0x68, - 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x15, - 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4f, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x07, 0x72, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xea, 0x01, 0x0a, 0x20, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x57, 0x69, 0x74, 0x68, 0x4f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x66, - 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x6f, - 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x72, 0x75, 0x6e, 0x5f, - 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x75, 0x6e, 0x49, 0x64, 0x12, - 0x33, 0x0a, 0x16, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x13, 0x66, 0x69, 0x72, 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x75, 0x6e, 0x49, 0x64, 0x12, 0x3c, 0x0a, 0x0b, 0x77, 0x61, 0x69, 0x74, 0x5f, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x74, 0x65, 0x6d, 0x70, - 0x6f, 0x72, 0x61, 0x6c, 0x2e, 0x78, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x61, 0x69, 0x74, - 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0a, 0x77, 0x61, 0x69, 0x74, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x22, 0xb2, 0x02, 0x0a, 0x0f, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x48, 0x0a, 0x12, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, - 0x65, 0x61, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, + 0x6d, 0x61, 0x78, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x6d, + 0x61, 0x78, 0x5f, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x73, 0x12, 0x39, + 0x0a, 0x19, 0x6e, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x79, 0x61, 0x62, 0x6c, 0x65, 0x5f, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x16, 0x6e, 0x6f, 0x6e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x61, 0x62, 0x6c, 0x65, 0x45, + 0x72, 0x72, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, 0xc1, 0x01, 0x0a, 0x0d, 0x53, 0x69, + 0x67, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x72, + 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x75, 0x6e, + 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, + 0x77, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x48, 0x0a, 0x12, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, + 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x68, 0x65, 0x61, 0x72, + 0x74, 0x62, 0x65, 0x61, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x22, 0xaa, 0x05, + 0x0a, 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x71, + 0x75, 0x65, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x61, 0x73, 0x6b, + 0x51, 0x75, 0x65, 0x75, 0x65, 0x12, 0x46, 0x0a, 0x11, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x65, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x3a, 0x0a, + 0x0b, 0x72, 0x75, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x68, - 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, - 0x12, 0x5b, 0x0a, 0x16, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, - 0x6f, 0x77, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x25, 0x2e, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x6c, 0x2e, 0x78, 0x6e, 0x73, 0x2e, - 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, - 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x14, 0x73, 0x74, 0x61, 0x72, 0x74, 0x57, 0x6f, - 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2e, 0x0a, - 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x72, + 0x75, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x3c, 0x0a, 0x0c, 0x74, 0x61, 0x73, + 0x6b, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x74, 0x61, 0x73, 0x6b, + 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x46, 0x0a, 0x0f, 0x69, 0x64, 0x5f, 0x72, 0x65, + 0x75, 0x73, 0x65, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x1e, 0x2e, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x6c, 0x2e, 0x78, 0x6e, 0x73, 0x2e, + 0x76, 0x31, 0x2e, 0x49, 0x44, 0x52, 0x65, 0x75, 0x73, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x52, 0x0d, 0x69, 0x64, 0x52, 0x65, 0x75, 0x73, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, + 0x3b, 0x0a, 0x1a, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x77, 0x68, 0x65, 0x6e, 0x5f, 0x61, 0x6c, + 0x72, 0x65, 0x61, 0x64, 0x79, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x17, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x57, 0x68, 0x65, 0x6e, 0x41, 0x6c, + 0x72, 0x65, 0x61, 0x64, 0x79, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x12, 0x3f, 0x0a, 0x0c, + 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x6c, 0x2e, 0x78, 0x6e, + 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x52, 0x0b, 0x72, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x2b, 0x0a, + 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, + 0x72, 0x75, 0x63, 0x74, 0x52, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x12, 0x44, 0x0a, 0x11, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x5f, 0x61, 0x74, 0x74, 0x69, 0x72, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, + 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x10, + 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x41, 0x74, 0x74, 0x69, 0x72, 0x62, 0x75, 0x74, 0x65, 0x73, + 0x12, 0x2c, 0x0a, 0x12, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x65, 0x61, 0x67, 0x65, 0x72, + 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x65, 0x6e, + 0x61, 0x62, 0x6c, 0x65, 0x45, 0x61, 0x67, 0x65, 0x72, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x3a, + 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x18, 0x0c, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, + 0x73, 0x74, 0x61, 0x72, 0x74, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x22, 0xf4, 0x01, 0x0a, 0x0d, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x48, 0x0a, 0x12, + 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, + 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x49, 0x6e, + 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x69, 0x0a, 0x17, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, + 0x61, 0x6c, 0x2e, 0x78, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x57, 0x69, 0x74, 0x68, 0x4f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x15, 0x75, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x12, 0x2e, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x22, 0xea, 0x01, 0x0a, 0x20, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, + 0x66, 0x6c, 0x6f, 0x77, 0x57, 0x69, 0x74, 0x68, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, + 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, + 0x6f, 0x77, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x33, 0x0a, 0x16, 0x66, + 0x69, 0x72, 0x73, 0x74, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, + 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x66, 0x69, 0x72, + 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x75, 0x6e, 0x49, 0x64, + 0x12, 0x3c, 0x0a, 0x0b, 0x77, 0x61, 0x69, 0x74, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x6c, + 0x2e, 0x78, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x61, 0x69, 0x74, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x52, 0x0a, 0x77, 0x61, 0x69, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, 0x82, + 0x03, 0x0a, 0x0f, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x48, 0x0a, 0x12, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x5f, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, - 0x08, 0x64, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x08, 0x64, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x12, 0x2c, 0x0a, 0x06, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, - 0x06, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x2a, 0x83, 0x02, 0x0a, 0x0d, 0x49, 0x44, 0x52, 0x65, - 0x75, 0x73, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x28, 0x0a, 0x24, 0x57, 0x4f, 0x52, - 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x49, 0x44, 0x5f, 0x52, 0x45, 0x55, 0x53, 0x45, 0x5f, 0x50, - 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, - 0x44, 0x10, 0x00, 0x12, 0x2c, 0x0a, 0x28, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, - 0x49, 0x44, 0x5f, 0x52, 0x45, 0x55, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, - 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x55, 0x50, 0x4c, 0x49, 0x43, 0x41, 0x54, 0x45, 0x10, - 0x01, 0x12, 0x38, 0x0a, 0x34, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x49, 0x44, - 0x5f, 0x52, 0x45, 0x55, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x41, 0x4c, - 0x4c, 0x4f, 0x57, 0x5f, 0x44, 0x55, 0x50, 0x4c, 0x49, 0x43, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, - 0x49, 0x4c, 0x45, 0x44, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x02, 0x12, 0x2d, 0x0a, 0x29, 0x57, - 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x49, 0x44, 0x5f, 0x52, 0x45, 0x55, 0x53, 0x45, - 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x52, 0x45, 0x4a, 0x45, 0x43, 0x54, 0x5f, 0x44, - 0x55, 0x50, 0x4c, 0x49, 0x43, 0x41, 0x54, 0x45, 0x10, 0x03, 0x12, 0x31, 0x0a, 0x2d, 0x57, 0x4f, - 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x49, 0x44, 0x5f, 0x52, 0x45, 0x55, 0x53, 0x45, 0x5f, - 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x54, 0x45, 0x52, 0x4d, 0x49, 0x4e, 0x41, 0x54, 0x45, - 0x5f, 0x49, 0x46, 0x5f, 0x52, 0x55, 0x4e, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x04, 0x2a, 0xa4, 0x01, - 0x0a, 0x11, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x50, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x12, 0x23, 0x0a, 0x1f, 0x50, 0x41, 0x52, 0x45, 0x4e, 0x54, 0x5f, 0x43, 0x4c, - 0x4f, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, - 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x50, 0x41, 0x52, 0x45, - 0x4e, 0x54, 0x5f, 0x43, 0x4c, 0x4f, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, - 0x54, 0x45, 0x52, 0x4d, 0x49, 0x4e, 0x41, 0x54, 0x45, 0x10, 0x01, 0x12, 0x1f, 0x0a, 0x1b, 0x50, - 0x41, 0x52, 0x45, 0x4e, 0x54, 0x5f, 0x43, 0x4c, 0x4f, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, - 0x43, 0x59, 0x5f, 0x41, 0x42, 0x41, 0x4e, 0x44, 0x4f, 0x4e, 0x10, 0x02, 0x12, 0x26, 0x0a, 0x22, - 0x50, 0x41, 0x52, 0x45, 0x4e, 0x54, 0x5f, 0x43, 0x4c, 0x4f, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, - 0x49, 0x43, 0x59, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x43, 0x41, 0x4e, 0x43, - 0x45, 0x4c, 0x10, 0x03, 0x2a, 0x78, 0x0a, 0x0a, 0x57, 0x61, 0x69, 0x74, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x12, 0x1b, 0x0a, 0x17, 0x57, 0x41, 0x49, 0x54, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, + 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x68, 0x65, 0x61, 0x72, 0x74, + 0x62, 0x65, 0x61, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x5b, 0x0a, 0x16, + 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x6f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x74, + 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x6c, 0x2e, 0x78, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x74, 0x61, 0x72, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x52, 0x14, 0x73, 0x74, 0x61, 0x72, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, + 0x6f, 0x77, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x07, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, + 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x74, + 0x61, 0x63, 0x68, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x64, 0x65, 0x74, + 0x61, 0x63, 0x68, 0x65, 0x64, 0x12, 0x2c, 0x0a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x06, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x6c, 0x12, 0x4e, 0x0a, 0x13, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6c, + 0x6f, 0x73, 0x65, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x1e, 0x2e, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, + 0x61, 0x72, 0x65, 0x6e, 0x74, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x52, 0x11, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x2a, 0x83, 0x02, 0x0a, 0x0d, 0x49, 0x44, 0x52, 0x65, 0x75, 0x73, 0x65, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x28, 0x0a, 0x24, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, + 0x57, 0x5f, 0x49, 0x44, 0x5f, 0x52, 0x45, 0x55, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, - 0x18, 0x0a, 0x14, 0x57, 0x41, 0x49, 0x54, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x41, - 0x44, 0x4d, 0x49, 0x54, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x57, 0x41, 0x49, - 0x54, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x41, 0x43, 0x43, 0x45, 0x50, 0x54, 0x45, - 0x44, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x57, 0x41, 0x49, 0x54, 0x5f, 0x50, 0x4f, 0x4c, 0x49, - 0x43, 0x59, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x03, 0x42, 0xc2, - 0x01, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x6c, 0x2e, - 0x78, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x42, 0x08, 0x58, 0x6e, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x50, 0x01, 0x5a, 0x43, 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, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x6c, 0x2f, 0x78, 0x6e, 0x73, 0x2f, 0x76, - 0x31, 0x3b, 0x78, 0x6e, 0x73, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x54, 0x58, 0x58, 0xaa, 0x02, 0x0f, - 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x6c, 0x2e, 0x58, 0x6e, 0x73, 0x2e, 0x56, 0x31, 0xca, - 0x02, 0x0f, 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x6c, 0x5c, 0x58, 0x6e, 0x73, 0x5c, 0x56, - 0x31, 0xe2, 0x02, 0x1b, 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x6c, 0x5c, 0x58, 0x6e, 0x73, - 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, - 0x02, 0x11, 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x6c, 0x3a, 0x3a, 0x58, 0x6e, 0x73, 0x3a, - 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x2c, 0x0a, 0x28, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x49, 0x44, 0x5f, 0x52, + 0x45, 0x55, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x41, 0x4c, 0x4c, 0x4f, + 0x57, 0x5f, 0x44, 0x55, 0x50, 0x4c, 0x49, 0x43, 0x41, 0x54, 0x45, 0x10, 0x01, 0x12, 0x38, 0x0a, + 0x34, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x49, 0x44, 0x5f, 0x52, 0x45, 0x55, + 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, + 0x44, 0x55, 0x50, 0x4c, 0x49, 0x43, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, + 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x02, 0x12, 0x2d, 0x0a, 0x29, 0x57, 0x4f, 0x52, 0x4b, 0x46, + 0x4c, 0x4f, 0x57, 0x5f, 0x49, 0x44, 0x5f, 0x52, 0x45, 0x55, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, + 0x49, 0x43, 0x59, 0x5f, 0x52, 0x45, 0x4a, 0x45, 0x43, 0x54, 0x5f, 0x44, 0x55, 0x50, 0x4c, 0x49, + 0x43, 0x41, 0x54, 0x45, 0x10, 0x03, 0x12, 0x31, 0x0a, 0x2d, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, + 0x4f, 0x57, 0x5f, 0x49, 0x44, 0x5f, 0x52, 0x45, 0x55, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, + 0x43, 0x59, 0x5f, 0x54, 0x45, 0x52, 0x4d, 0x49, 0x4e, 0x41, 0x54, 0x45, 0x5f, 0x49, 0x46, 0x5f, + 0x52, 0x55, 0x4e, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x04, 0x2a, 0xa4, 0x01, 0x0a, 0x11, 0x50, 0x61, + 0x72, 0x65, 0x6e, 0x74, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, + 0x23, 0x0a, 0x1f, 0x50, 0x41, 0x52, 0x45, 0x4e, 0x54, 0x5f, 0x43, 0x4c, 0x4f, 0x53, 0x45, 0x5f, + 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, + 0x45, 0x44, 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x50, 0x41, 0x52, 0x45, 0x4e, 0x54, 0x5f, 0x43, + 0x4c, 0x4f, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x54, 0x45, 0x52, 0x4d, + 0x49, 0x4e, 0x41, 0x54, 0x45, 0x10, 0x01, 0x12, 0x1f, 0x0a, 0x1b, 0x50, 0x41, 0x52, 0x45, 0x4e, + 0x54, 0x5f, 0x43, 0x4c, 0x4f, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x41, + 0x42, 0x41, 0x4e, 0x44, 0x4f, 0x4e, 0x10, 0x02, 0x12, 0x26, 0x0a, 0x22, 0x50, 0x41, 0x52, 0x45, + 0x4e, 0x54, 0x5f, 0x43, 0x4c, 0x4f, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, + 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x10, 0x03, + 0x2a, 0x78, 0x0a, 0x0a, 0x57, 0x61, 0x69, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x1b, + 0x0a, 0x17, 0x57, 0x41, 0x49, 0x54, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x55, 0x4e, + 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x57, + 0x41, 0x49, 0x54, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x41, 0x44, 0x4d, 0x49, 0x54, + 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x57, 0x41, 0x49, 0x54, 0x5f, 0x50, 0x4f, + 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x41, 0x43, 0x43, 0x45, 0x50, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, + 0x19, 0x0a, 0x15, 0x57, 0x41, 0x49, 0x54, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x43, + 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x03, 0x42, 0xc2, 0x01, 0x0a, 0x13, 0x63, + 0x6f, 0x6d, 0x2e, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x6c, 0x2e, 0x78, 0x6e, 0x73, 0x2e, + 0x76, 0x31, 0x42, 0x08, 0x58, 0x6e, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x43, + 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, 0x74, 0x65, + 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x6c, 0x2f, 0x78, 0x6e, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x78, 0x6e, + 0x73, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x54, 0x58, 0x58, 0xaa, 0x02, 0x0f, 0x54, 0x65, 0x6d, 0x70, + 0x6f, 0x72, 0x61, 0x6c, 0x2e, 0x58, 0x6e, 0x73, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0f, 0x54, 0x65, + 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x6c, 0x5c, 0x58, 0x6e, 0x73, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1b, + 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x6c, 0x5c, 0x58, 0x6e, 0x73, 0x5c, 0x56, 0x31, 0x5c, + 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x11, 0x54, 0x65, + 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x6c, 0x3a, 0x3a, 0x58, 0x6e, 0x73, 0x3a, 0x3a, 0x56, 0x31, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1004,6 +1020,7 @@ var file_temporal_xns_v1_xns_proto_goTypes = []interface{}{ (*anypb.Any)(nil), // 10: google.protobuf.Any (*durationpb.Duration)(nil), // 11: google.protobuf.Duration (*structpb.Struct)(nil), // 12: google.protobuf.Struct + (v1.ParentClosePolicy)(0), // 13: temporal.v1.ParentClosePolicy } var file_temporal_xns_v1_xns_proto_depIdxs = []int32{ 10, // 0: temporal.xns.v1.QueryRequest.request:type_name -> google.protobuf.Any @@ -1028,11 +1045,12 @@ var file_temporal_xns_v1_xns_proto_depIdxs = []int32{ 6, // 19: temporal.xns.v1.WorkflowRequest.start_workflow_options:type_name -> temporal.xns.v1.StartWorkflowOptions 10, // 20: temporal.xns.v1.WorkflowRequest.request:type_name -> google.protobuf.Any 10, // 21: temporal.xns.v1.WorkflowRequest.signal:type_name -> google.protobuf.Any - 22, // [22:22] is the sub-list for method output_type - 22, // [22:22] is the sub-list for method input_type - 22, // [22:22] is the sub-list for extension type_name - 22, // [22:22] is the sub-list for extension extendee - 0, // [0:22] is the sub-list for field type_name + 13, // 22: temporal.xns.v1.WorkflowRequest.parent_close_policy:type_name -> temporal.v1.ParentClosePolicy + 23, // [23:23] is the sub-list for method output_type + 23, // [23:23] is the sub-list for method input_type + 23, // [23:23] is the sub-list for extension type_name + 23, // [23:23] is the sub-list for extension extendee + 0, // [0:23] is the sub-list for field type_name } func init() { file_temporal_xns_v1_xns_proto_init() } diff --git a/gen/test/expression/v1/expression.pb.go b/gen/test/expression/v1/expression.pb.go index a867196e..40d6c642 100644 --- a/gen/test/expression/v1/expression.pb.go +++ b/gen/test/expression/v1/expression.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.34.1 // protoc (unknown) // source: test/expression/v1/expression.proto diff --git a/gen/test/option/v1/option.pb.go b/gen/test/option/v1/option.pb.go index 159bb6e2..9e82a3f0 100644 --- a/gen/test/option/v1/option.pb.go +++ b/gen/test/option/v1/option.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.34.1 // protoc (unknown) // source: test/option/v1/option.proto diff --git a/gen/test/option/v1/option_temporal.pb.go b/gen/test/option/v1/option_temporal.pb.go index 23c6d7b4..a6d7464e 100644 --- a/gen/test/option/v1/option_temporal.pb.go +++ b/gen/test/option/v1/option_temporal.pb.go @@ -1,8 +1,8 @@ // Code generated by protoc-gen-go_temporal. DO NOT EDIT. // versions: // -// protoc-gen-go_temporal 1.12.1-next (ec80fd34c1a9a69042c74c5d3da0091b91ac2e0c) -// go go1.22.1 +// protoc-gen-go_temporal 1.13.1-next (fc19a4c83a5c93edb1c0e750533a8a5a3c44094e) +// go go1.22.3 // protoc (unknown) // // source: test/option/v1/option.proto diff --git a/gen/test/option/v1/optionv1xns/option_xns_temporal.pb.go b/gen/test/option/v1/optionv1xns/option_xns_temporal.pb.go index 80fac99d..001f891d 100644 --- a/gen/test/option/v1/optionv1xns/option_xns_temporal.pb.go +++ b/gen/test/option/v1/optionv1xns/option_xns_temporal.pb.go @@ -1,8 +1,8 @@ // Code generated by protoc-gen-go_temporal. DO NOT EDIT. // versions: // -// protoc-gen-go_temporal 1.12.1-next (ec80fd34c1a9a69042c74c5d3da0091b91ac2e0c) -// go go1.22.1 +// protoc-gen-go_temporal 1.13.1-next (fc19a4c83a5c93edb1c0e750533a8a5a3c44094e) +// go go1.22.3 // protoc (unknown) // // source: test/option/v1/option.proto @@ -12,13 +12,14 @@ import ( "context" "errors" "fmt" - v11 "github.com/cludden/protoc-gen-go-temporal/gen/temporal/xns/v1" + v12 "github.com/cludden/protoc-gen-go-temporal/gen/temporal/v1" + v13 "github.com/cludden/protoc-gen-go-temporal/gen/temporal/xns/v1" v1 "github.com/cludden/protoc-gen-go-temporal/gen/test/option/v1" expression "github.com/cludden/protoc-gen-go-temporal/pkg/expression" xns "github.com/cludden/protoc-gen-go-temporal/pkg/xns" uuid "github.com/google/uuid" - v13 "go.temporal.io/api/enums/v1" - v12 "go.temporal.io/api/update/v1" + v11 "go.temporal.io/api/enums/v1" + v14 "go.temporal.io/api/update/v1" activity "go.temporal.io/sdk/activity" client "go.temporal.io/sdk/client" temporal "go.temporal.io/sdk/temporal" @@ -102,6 +103,7 @@ type WorkflowWithInputWorkflowOptions struct { ActivityOptions *workflow.ActivityOptions Detached bool HeartbeatInterval time.Duration + ParentClosePolicy v11.ParentClosePolicy StartWorkflowOptions *client.StartWorkflowOptions } @@ -128,6 +130,12 @@ func (opts *WorkflowWithInputWorkflowOptions) WithHeartbeatInterval(d time.Durat return opts } +// WithParentClosePolicy can be used to customize the cancellation propagation behavior +func (opts *WorkflowWithInputWorkflowOptions) WithParentClosePolicy(policy v11.ParentClosePolicy) *WorkflowWithInputWorkflowOptions { + opts.ParentClosePolicy = policy + return opts +} + // WithStartWorkflowOptions can be used to customize the start workflow options func (opts *WorkflowWithInputWorkflowOptions) WithStartWorkflow(swo client.StartWorkflowOptions) *WorkflowWithInputWorkflowOptions { opts.StartWorkflowOptions = &swo @@ -291,13 +299,24 @@ func WorkflowWithInputAsync(ctx workflow.Context, req *v1.WorkflowWithInputReque return nil, fmt.Errorf("error marshalling workflow request: %w", err) } + parentClosePolicy := v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL + switch opt.ParentClosePolicy { + case v11.PARENT_CLOSE_POLICY_ABANDON: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON + case v11.PARENT_CLOSE_POLICY_REQUEST_CANCEL: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL + case v11.PARENT_CLOSE_POLICY_TERMINATE: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_TERMINATE + } + ctx, cancel := workflow.WithCancel(ctx) return &workflowWithInputRun{ cancel: cancel, id: wo.ID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.WorkflowRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.WorkflowRequest{ Detached: opt.Detached, HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), + ParentClosePolicy: parentClosePolicy, Request: wreq, StartWorkflowOptions: swo, }), @@ -476,7 +495,7 @@ func UpdateWithInputAsync(ctx workflow.Context, workflowID string, runID string, return &updateWithInputHandle{ cancel: cancel, id: uo.UpdateID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.UpdateRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.UpdateRequest{ HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), Request: wreq, UpdateWorkflowOptions: uopb, @@ -520,7 +539,7 @@ func (a *testActivities) CancelWorkflow(ctx context.Context, workflowID string, } // WorkflowWithInput executes a(n) test.option.v1.Test.WorkflowWithInput workflow via an activity -func (a *testActivities) WorkflowWithInput(ctx context.Context, input *v11.WorkflowRequest) (err error) { +func (a *testActivities) WorkflowWithInput(ctx context.Context, input *v13.WorkflowRequest) (err error) { // unmarshal workflow request var req v1.WorkflowWithInputRequest if err := input.Request.UnmarshalTo(&req); err != nil { @@ -554,21 +573,48 @@ func (a *testActivities) WorkflowWithInput(ctx context.Context, input *v11.Workf heartbeatInterval := input.GetHeartbeatInterval().AsDuration() if heartbeatInterval == 0 { - heartbeatInterval = time.Minute + heartbeatInterval = time.Second * 30 } // heartbeat activity while waiting for workflow execution to complete for { select { + // send heartbeats periodically case <-time.After(heartbeatInterval): activity.RecordHeartbeat(ctx, run.ID()) + + // return retryable error on worker close + case <-activity.GetWorkerStopChannel(ctx): + return temporal.NewApplicationError("worker is stopping", "WorkerStopped") + + // catch parent activity context cancellation. in most cases, this should indicate a + // server-sent cancellation, but there's a non-zero possibility that this cancellation + // is received due to the worker stopping, prior to detecting the closing of the worker + // stop channel. to give us an opportunity to detect a cancellation stemming from the + // worker closing, we again check to see if the worker stop channel is closed before + // propagating the cancellation case <-ctx.Done(): - disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) - defer cancel() - if err := run.Cancel(disconnectedCtx); err != nil { - return testOptions.convertError(err) + select { + case <-activity.GetWorkerStopChannel(ctx): + return temporal.NewApplicationError("worker is stopping", "WorkerStopped") + default: + parentClosePolicy := input.GetParentClosePolicy() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL || parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON { + disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) + defer cancel() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL { + err = run.Cancel(disconnectedCtx) + } else { + err = run.Terminate(disconnectedCtx, "xns activity cancellation received", "error", ctx.Err()) + } + if err != nil { + return testOptions.convertError(err) + } + } + return testOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) } - return testOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) + + // handle workflow completion case <-doneCh: return testOptions.convertError(err) } @@ -576,7 +622,7 @@ func (a *testActivities) WorkflowWithInput(ctx context.Context, input *v11.Workf } // UpdateWithInput executes a(n) test.option.v1.Test.UpdateWithInput update via an activity -func (a *testActivities) UpdateWithInput(ctx context.Context, input *v11.UpdateRequest) (err error) { +func (a *testActivities) UpdateWithInput(ctx context.Context, input *v13.UpdateRequest) (err error) { var handle v1.UpdateWithInputHandle if activity.HasHeartbeatDetails(ctx) { // extract update id from heartbeat details @@ -606,8 +652,8 @@ func (a *testActivities) UpdateWithInput(ctx context.Context, input *v11.UpdateR } uo := xns.UnmarshalUpdateWorkflowOptions(input.GetUpdateWorkflowOptions()) - uo.WaitPolicy = &v12.WaitPolicy{ - LifecycleStage: v13.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ACCEPTED, + uo.WaitPolicy = &v14.WaitPolicy{ + LifecycleStage: v11.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ACCEPTED, } // initialize update execution diff --git a/gen/test/simple/v1/simple.pb.go b/gen/test/simple/v1/simple.pb.go index 5d4ed672..1b984627 100644 --- a/gen/test/simple/v1/simple.pb.go +++ b/gen/test/simple/v1/simple.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.34.1 // protoc (unknown) // source: test/simple/v1/simple.proto diff --git a/gen/test/simple/v1/simple_temporal.pb.go b/gen/test/simple/v1/simple_temporal.pb.go index 11de05db..ac3f5048 100644 --- a/gen/test/simple/v1/simple_temporal.pb.go +++ b/gen/test/simple/v1/simple_temporal.pb.go @@ -1,8 +1,8 @@ // Code generated by protoc-gen-go_temporal. DO NOT EDIT. // versions: // -// protoc-gen-go_temporal 1.12.1-next (ec80fd34c1a9a69042c74c5d3da0091b91ac2e0c) -// go go1.22.1 +// protoc-gen-go_temporal 1.13.1-next (fc19a4c83a5c93edb1c0e750533a8a5a3c44094e) +// go go1.22.3 // protoc (unknown) // // source: test/simple/v1/simple.proto diff --git a/gen/test/simple/v1/v1xns/simple_xns_temporal.pb.go b/gen/test/simple/v1/v1xns/simple_xns_temporal.pb.go index 946f251f..427c56ae 100644 --- a/gen/test/simple/v1/v1xns/simple_xns_temporal.pb.go +++ b/gen/test/simple/v1/v1xns/simple_xns_temporal.pb.go @@ -1,8 +1,8 @@ // Code generated by protoc-gen-go_temporal. DO NOT EDIT. // versions: // -// protoc-gen-go_temporal 1.12.1-next (ec80fd34c1a9a69042c74c5d3da0091b91ac2e0c) -// go go1.22.1 +// protoc-gen-go_temporal 1.13.1-next (fc19a4c83a5c93edb1c0e750533a8a5a3c44094e) +// go go1.22.3 // protoc (unknown) // // source: test/simple/v1/simple.proto @@ -12,13 +12,14 @@ import ( "context" "errors" "fmt" - v11 "github.com/cludden/protoc-gen-go-temporal/gen/temporal/xns/v1" + v12 "github.com/cludden/protoc-gen-go-temporal/gen/temporal/v1" + v13 "github.com/cludden/protoc-gen-go-temporal/gen/temporal/xns/v1" v1 "github.com/cludden/protoc-gen-go-temporal/gen/test/simple/v1" expression "github.com/cludden/protoc-gen-go-temporal/pkg/expression" xns "github.com/cludden/protoc-gen-go-temporal/pkg/xns" uuid "github.com/google/uuid" - v13 "go.temporal.io/api/enums/v1" - v12 "go.temporal.io/api/update/v1" + v11 "go.temporal.io/api/enums/v1" + v14 "go.temporal.io/api/update/v1" activity "go.temporal.io/sdk/activity" client "go.temporal.io/sdk/client" temporal "go.temporal.io/sdk/temporal" @@ -129,6 +130,7 @@ type SomeWorkflow1WorkflowOptions struct { ActivityOptions *workflow.ActivityOptions Detached bool HeartbeatInterval time.Duration + ParentClosePolicy v11.ParentClosePolicy StartWorkflowOptions *client.StartWorkflowOptions } @@ -155,6 +157,12 @@ func (opts *SomeWorkflow1WorkflowOptions) WithHeartbeatInterval(d time.Duration) return opts } +// WithParentClosePolicy can be used to customize the cancellation propagation behavior +func (opts *SomeWorkflow1WorkflowOptions) WithParentClosePolicy(policy v11.ParentClosePolicy) *SomeWorkflow1WorkflowOptions { + opts.ParentClosePolicy = policy + return opts +} + // WithStartWorkflowOptions can be used to customize the start workflow options func (opts *SomeWorkflow1WorkflowOptions) WithStartWorkflow(swo client.StartWorkflowOptions) *SomeWorkflow1WorkflowOptions { opts.StartWorkflowOptions = &swo @@ -367,13 +375,24 @@ func SomeWorkflow1Async(ctx workflow.Context, req *v1.SomeWorkflow1Request, opts return nil, fmt.Errorf("error marshalling workflow request: %w", err) } + var parentClosePolicy v12.ParentClosePolicy + switch opt.ParentClosePolicy { + case v11.PARENT_CLOSE_POLICY_ABANDON: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON + case v11.PARENT_CLOSE_POLICY_REQUEST_CANCEL: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL + case v11.PARENT_CLOSE_POLICY_TERMINATE: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_TERMINATE + } + ctx, cancel := workflow.WithCancel(ctx) return &someWorkflow1Run{ cancel: cancel, id: wo.ID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.WorkflowRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.WorkflowRequest{ Detached: opt.Detached, HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), + ParentClosePolicy: parentClosePolicy, Request: wreq, StartWorkflowOptions: swo, }), @@ -385,6 +404,7 @@ type SomeWorkflow2WorkflowOptions struct { ActivityOptions *workflow.ActivityOptions Detached bool HeartbeatInterval time.Duration + ParentClosePolicy v11.ParentClosePolicy StartWorkflowOptions *client.StartWorkflowOptions } @@ -411,6 +431,12 @@ func (opts *SomeWorkflow2WorkflowOptions) WithHeartbeatInterval(d time.Duration) return opts } +// WithParentClosePolicy can be used to customize the cancellation propagation behavior +func (opts *SomeWorkflow2WorkflowOptions) WithParentClosePolicy(policy v11.ParentClosePolicy) *SomeWorkflow2WorkflowOptions { + opts.ParentClosePolicy = policy + return opts +} + // WithStartWorkflowOptions can be used to customize the start workflow options func (opts *SomeWorkflow2WorkflowOptions) WithStartWorkflow(swo client.StartWorkflowOptions) *SomeWorkflow2WorkflowOptions { opts.StartWorkflowOptions = &swo @@ -584,13 +610,24 @@ func SomeWorkflow2Async(ctx workflow.Context, opts ...*SomeWorkflow2WorkflowOpti return nil, fmt.Errorf("error marshalling start workflow options: %w", err) } + var parentClosePolicy v12.ParentClosePolicy + switch opt.ParentClosePolicy { + case v11.PARENT_CLOSE_POLICY_ABANDON: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON + case v11.PARENT_CLOSE_POLICY_REQUEST_CANCEL: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL + case v11.PARENT_CLOSE_POLICY_TERMINATE: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_TERMINATE + } + ctx, cancel := workflow.WithCancel(ctx) return &someWorkflow2Run{ cancel: cancel, id: wo.ID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.WorkflowRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.WorkflowRequest{ Detached: opt.Detached, HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), + ParentClosePolicy: parentClosePolicy, StartWorkflowOptions: swo, }), }, nil @@ -683,7 +720,7 @@ func SomeWorkflow2WithSomeSignal1Async(ctx workflow.Context, opts ...*SomeWorkfl return &someWorkflow2Run{ cancel: cancel, id: wo.ID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.WorkflowRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.WorkflowRequest{ Detached: opt.Detached, HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), StartWorkflowOptions: swo, @@ -696,6 +733,7 @@ type SomeWorkflow3WorkflowOptions struct { ActivityOptions *workflow.ActivityOptions Detached bool HeartbeatInterval time.Duration + ParentClosePolicy v11.ParentClosePolicy StartWorkflowOptions *client.StartWorkflowOptions } @@ -722,6 +760,12 @@ func (opts *SomeWorkflow3WorkflowOptions) WithHeartbeatInterval(d time.Duration) return opts } +// WithParentClosePolicy can be used to customize the cancellation propagation behavior +func (opts *SomeWorkflow3WorkflowOptions) WithParentClosePolicy(policy v11.ParentClosePolicy) *SomeWorkflow3WorkflowOptions { + opts.ParentClosePolicy = policy + return opts +} + // WithStartWorkflowOptions can be used to customize the start workflow options func (opts *SomeWorkflow3WorkflowOptions) WithStartWorkflow(swo client.StartWorkflowOptions) *SomeWorkflow3WorkflowOptions { opts.StartWorkflowOptions = &swo @@ -889,13 +933,24 @@ func SomeWorkflow3Async(ctx workflow.Context, req *v1.SomeWorkflow3Request, opts return nil, fmt.Errorf("error marshalling workflow request: %w", err) } + var parentClosePolicy v12.ParentClosePolicy + switch opt.ParentClosePolicy { + case v11.PARENT_CLOSE_POLICY_ABANDON: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON + case v11.PARENT_CLOSE_POLICY_REQUEST_CANCEL: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL + case v11.PARENT_CLOSE_POLICY_TERMINATE: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_TERMINATE + } + ctx, cancel := workflow.WithCancel(ctx) return &someWorkflow3Run{ cancel: cancel, id: wo.ID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.WorkflowRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.WorkflowRequest{ Detached: opt.Detached, HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), + ParentClosePolicy: parentClosePolicy, Request: wreq, StartWorkflowOptions: swo, }), @@ -1007,7 +1062,7 @@ func SomeWorkflow3WithSomeSignal2Async(ctx workflow.Context, req *v1.SomeWorkflo return &someWorkflow3Run{ cancel: cancel, id: wo.ID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.WorkflowRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.WorkflowRequest{ Detached: opt.Detached, HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), Request: wreq, @@ -1129,7 +1184,7 @@ func SomeQuery1Async(ctx workflow.Context, workflowID string, runID string, opts ctx, cancel := workflow.WithCancel(ctx) return &someQuery1QueryHandle{ cancel: cancel, - future: workflow.ExecuteActivity(ctx, activityName, &v11.QueryRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.QueryRequest{ HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), WorkflowId: workflowID, RunId: runID, @@ -1255,7 +1310,7 @@ func SomeQuery2Async(ctx workflow.Context, workflowID string, runID string, req ctx, cancel := workflow.WithCancel(ctx) return &someQuery2QueryHandle{ cancel: cancel, - future: workflow.ExecuteActivity(ctx, activityName, &v11.QueryRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.QueryRequest{ HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), WorkflowId: workflowID, RunId: runID, @@ -1370,7 +1425,7 @@ func SomeSignal1Async(ctx workflow.Context, workflowID string, runID string, opt ctx, cancel := workflow.WithCancel(ctx) return &someSignal1SignalHandle{ cancel: cancel, - future: workflow.ExecuteActivity(ctx, activityName, &v11.SignalRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.SignalRequest{ HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), WorkflowId: workflowID, RunId: runID, @@ -1490,7 +1545,7 @@ func SomeSignal2Async(ctx workflow.Context, workflowID string, runID string, req ctx, cancel := workflow.WithCancel(ctx) return &someSignal2SignalHandle{ cancel: cancel, - future: workflow.ExecuteActivity(ctx, activityName, &v11.SignalRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.SignalRequest{ HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), WorkflowId: workflowID, RunId: runID, @@ -1611,7 +1666,7 @@ func SomeSignal3Async(ctx workflow.Context, workflowID string, runID string, req ctx, cancel := workflow.WithCancel(ctx) return &someSignal3SignalHandle{ cancel: cancel, - future: workflow.ExecuteActivity(ctx, activityName, &v11.SignalRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.SignalRequest{ HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), WorkflowId: workflowID, RunId: runID, @@ -1793,7 +1848,7 @@ func SomeUpdate1Async(ctx workflow.Context, workflowID string, runID string, req return &someUpdate1Handle{ cancel: cancel, id: uo.UpdateID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.UpdateRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.UpdateRequest{ HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), Request: wreq, UpdateWorkflowOptions: uopb, @@ -1837,7 +1892,7 @@ func (a *simpleActivities) CancelWorkflow(ctx context.Context, workflowID string } // SomeWorkflow1 executes a(n) mycompany.simple.SomeWorkflow1 workflow via an activity -func (a *simpleActivities) SomeWorkflow1(ctx context.Context, input *v11.WorkflowRequest) (resp *v1.SomeWorkflow1Response, err error) { +func (a *simpleActivities) SomeWorkflow1(ctx context.Context, input *v13.WorkflowRequest) (resp *v1.SomeWorkflow1Response, err error) { // unmarshal workflow request var req v1.SomeWorkflow1Request if err := input.Request.UnmarshalTo(&req); err != nil { @@ -1871,21 +1926,48 @@ func (a *simpleActivities) SomeWorkflow1(ctx context.Context, input *v11.Workflo heartbeatInterval := input.GetHeartbeatInterval().AsDuration() if heartbeatInterval == 0 { - heartbeatInterval = time.Minute + heartbeatInterval = time.Second * 30 } // heartbeat activity while waiting for workflow execution to complete for { select { + // send heartbeats periodically case <-time.After(heartbeatInterval): activity.RecordHeartbeat(ctx, run.ID()) + + // return retryable error on worker close + case <-activity.GetWorkerStopChannel(ctx): + return nil, temporal.NewApplicationError("worker is stopping", "WorkerStopped") + + // catch parent activity context cancellation. in most cases, this should indicate a + // server-sent cancellation, but there's a non-zero possibility that this cancellation + // is received due to the worker stopping, prior to detecting the closing of the worker + // stop channel. to give us an opportunity to detect a cancellation stemming from the + // worker closing, we again check to see if the worker stop channel is closed before + // propagating the cancellation case <-ctx.Done(): - disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) - defer cancel() - if err := run.Cancel(disconnectedCtx); err != nil { - return nil, simpleOptions.convertError(err) + select { + case <-activity.GetWorkerStopChannel(ctx): + return nil, temporal.NewApplicationError("worker is stopping", "WorkerStopped") + default: + parentClosePolicy := input.GetParentClosePolicy() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL || parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON { + disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) + defer cancel() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL { + err = run.Cancel(disconnectedCtx) + } else { + err = run.Terminate(disconnectedCtx, "xns activity cancellation received", "error", ctx.Err()) + } + if err != nil { + return nil, simpleOptions.convertError(err) + } + } + return nil, simpleOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) } - return nil, simpleOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) + + // handle workflow completion case <-doneCh: return resp, simpleOptions.convertError(err) } @@ -1893,7 +1975,7 @@ func (a *simpleActivities) SomeWorkflow1(ctx context.Context, input *v11.Workflo } // SomeWorkflow2 executes a(n) mycompany.simple.SomeWorkflow2 workflow via an activity -func (a *simpleActivities) SomeWorkflow2(ctx context.Context, input *v11.WorkflowRequest) (err error) { +func (a *simpleActivities) SomeWorkflow2(ctx context.Context, input *v13.WorkflowRequest) (err error) { // initialize workflow execution var run v1.SomeWorkflow2Run run, err = a.client.SomeWorkflow2Async(ctx, v1.NewSomeWorkflow2Options().WithStartWorkflowOptions( @@ -1917,21 +1999,48 @@ func (a *simpleActivities) SomeWorkflow2(ctx context.Context, input *v11.Workflo heartbeatInterval := input.GetHeartbeatInterval().AsDuration() if heartbeatInterval == 0 { - heartbeatInterval = time.Minute + heartbeatInterval = time.Second * 30 } // heartbeat activity while waiting for workflow execution to complete for { select { + // send heartbeats periodically case <-time.After(heartbeatInterval): activity.RecordHeartbeat(ctx, run.ID()) + + // return retryable error on worker close + case <-activity.GetWorkerStopChannel(ctx): + return temporal.NewApplicationError("worker is stopping", "WorkerStopped") + + // catch parent activity context cancellation. in most cases, this should indicate a + // server-sent cancellation, but there's a non-zero possibility that this cancellation + // is received due to the worker stopping, prior to detecting the closing of the worker + // stop channel. to give us an opportunity to detect a cancellation stemming from the + // worker closing, we again check to see if the worker stop channel is closed before + // propagating the cancellation case <-ctx.Done(): - disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) - defer cancel() - if err := run.Cancel(disconnectedCtx); err != nil { - return simpleOptions.convertError(err) + select { + case <-activity.GetWorkerStopChannel(ctx): + return temporal.NewApplicationError("worker is stopping", "WorkerStopped") + default: + parentClosePolicy := input.GetParentClosePolicy() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL || parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON { + disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) + defer cancel() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL { + err = run.Cancel(disconnectedCtx) + } else { + err = run.Terminate(disconnectedCtx, "xns activity cancellation received", "error", ctx.Err()) + } + if err != nil { + return simpleOptions.convertError(err) + } + } + return simpleOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) } - return simpleOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) + + // handle workflow completion case <-doneCh: return simpleOptions.convertError(err) } @@ -1939,7 +2048,7 @@ func (a *simpleActivities) SomeWorkflow2(ctx context.Context, input *v11.Workflo } // SomeWorkflow2WithSomeSignal1 sends a(n) mycompany.simple.Simple.SomeSignal1 signal to a(n) mycompany.simple.SomeWorkflow2 workflow via an activity -func (a *simpleActivities) SomeWorkflow2WithSomeSignal1(ctx context.Context, input *v11.WorkflowRequest) (err error) { +func (a *simpleActivities) SomeWorkflow2WithSomeSignal1(ctx context.Context, input *v13.WorkflowRequest) (err error) { // initialize workflow execution var run v1.SomeWorkflow2Run run, err = a.client.SomeWorkflow2WithSomeSignal1Async(ctx, v1.NewSomeWorkflow2Options().WithStartWorkflowOptions( @@ -1987,7 +2096,7 @@ func (a *simpleActivities) SomeWorkflow2WithSomeSignal1(ctx context.Context, inp // SomeWorkflow3 executes a(n) mycompany.simple.Simple.SomeWorkflow3 workflow via an activity // // Deprecated: Do not use. -func (a *simpleActivities) SomeWorkflow3(ctx context.Context, input *v11.WorkflowRequest) (err error) { +func (a *simpleActivities) SomeWorkflow3(ctx context.Context, input *v13.WorkflowRequest) (err error) { activity.GetLogger(ctx).Warn("use of deprecated workflow detected", "workflow", v1.SomeWorkflow3WorkflowName) // unmarshal workflow request @@ -2023,21 +2132,48 @@ func (a *simpleActivities) SomeWorkflow3(ctx context.Context, input *v11.Workflo heartbeatInterval := input.GetHeartbeatInterval().AsDuration() if heartbeatInterval == 0 { - heartbeatInterval = time.Minute + heartbeatInterval = time.Second * 30 } // heartbeat activity while waiting for workflow execution to complete for { select { + // send heartbeats periodically case <-time.After(heartbeatInterval): activity.RecordHeartbeat(ctx, run.ID()) + + // return retryable error on worker close + case <-activity.GetWorkerStopChannel(ctx): + return temporal.NewApplicationError("worker is stopping", "WorkerStopped") + + // catch parent activity context cancellation. in most cases, this should indicate a + // server-sent cancellation, but there's a non-zero possibility that this cancellation + // is received due to the worker stopping, prior to detecting the closing of the worker + // stop channel. to give us an opportunity to detect a cancellation stemming from the + // worker closing, we again check to see if the worker stop channel is closed before + // propagating the cancellation case <-ctx.Done(): - disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) - defer cancel() - if err := run.Cancel(disconnectedCtx); err != nil { - return simpleOptions.convertError(err) + select { + case <-activity.GetWorkerStopChannel(ctx): + return temporal.NewApplicationError("worker is stopping", "WorkerStopped") + default: + parentClosePolicy := input.GetParentClosePolicy() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL || parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON { + disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) + defer cancel() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL { + err = run.Cancel(disconnectedCtx) + } else { + err = run.Terminate(disconnectedCtx, "xns activity cancellation received", "error", ctx.Err()) + } + if err != nil { + return simpleOptions.convertError(err) + } + } + return simpleOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) } - return simpleOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) + + // handle workflow completion case <-doneCh: return simpleOptions.convertError(err) } @@ -2047,7 +2183,7 @@ func (a *simpleActivities) SomeWorkflow3(ctx context.Context, input *v11.Workflo // SomeWorkflow3WithSomeSignal2 sends a(n) mycompany.simple.Simple.SomeSignal2 signal to a(n) mycompany.simple.Simple.SomeWorkflow3 workflow via an activity // // Deprecated: Do not use. -func (a *simpleActivities) SomeWorkflow3WithSomeSignal2(ctx context.Context, input *v11.WorkflowRequest) (err error) { +func (a *simpleActivities) SomeWorkflow3WithSomeSignal2(ctx context.Context, input *v13.WorkflowRequest) (err error) { activity.GetLogger(ctx).Warn("use of deprecated workflow detected", "workflow", v1.SomeWorkflow3WorkflowName) // unmarshal workflow request @@ -2115,7 +2251,7 @@ func (a *simpleActivities) SomeWorkflow3WithSomeSignal2(ctx context.Context, inp } // SomeQuery1 executes a(n) mycompany.simple.Simple.SomeQuery1 query via an activity -func (a *simpleActivities) SomeQuery1(ctx context.Context, input *v11.QueryRequest) (resp *v1.SomeQuery1Response, err error) { +func (a *simpleActivities) SomeQuery1(ctx context.Context, input *v13.QueryRequest) (resp *v1.SomeQuery1Response, err error) { // execute signal in child goroutine doneCh := make(chan struct{}) go func() { @@ -2142,7 +2278,7 @@ func (a *simpleActivities) SomeQuery1(ctx context.Context, input *v11.QueryReque } // SomeQuery2 executes a(n) mycompany.simple.Simple.SomeQuery2 query via an activity -func (a *simpleActivities) SomeQuery2(ctx context.Context, input *v11.QueryRequest) (resp *v1.SomeQuery2Response, err error) { +func (a *simpleActivities) SomeQuery2(ctx context.Context, input *v13.QueryRequest) (resp *v1.SomeQuery2Response, err error) { // unmarshal query request var req v1.SomeQuery2Request if err := input.Request.UnmarshalTo(&req); err != nil { @@ -2178,7 +2314,7 @@ func (a *simpleActivities) SomeQuery2(ctx context.Context, input *v11.QueryReque } // SomeSignal1 executes a(n) mycompany.simple.Simple.SomeSignal1 signal via an activity -func (a *simpleActivities) SomeSignal1(ctx context.Context, input *v11.SignalRequest) (err error) { +func (a *simpleActivities) SomeSignal1(ctx context.Context, input *v13.SignalRequest) (err error) { // execute signal in child goroutine doneCh := make(chan struct{}) go func() { @@ -2205,7 +2341,7 @@ func (a *simpleActivities) SomeSignal1(ctx context.Context, input *v11.SignalReq } // SomeSignal2 executes a(n) mycompany.simple.Simple.SomeSignal2 signal via an activity -func (a *simpleActivities) SomeSignal2(ctx context.Context, input *v11.SignalRequest) (err error) { +func (a *simpleActivities) SomeSignal2(ctx context.Context, input *v13.SignalRequest) (err error) { // unmarshal signal request var req v1.SomeSignal2Request if err := input.Request.UnmarshalTo(&req); err != nil { @@ -2241,7 +2377,7 @@ func (a *simpleActivities) SomeSignal2(ctx context.Context, input *v11.SignalReq } // SomeSignal3 executes a(n) mycompany.simple.Simple.SomeSignal3 signal via an activity -func (a *simpleActivities) SomeSignal3(ctx context.Context, input *v11.SignalRequest) (err error) { +func (a *simpleActivities) SomeSignal3(ctx context.Context, input *v13.SignalRequest) (err error) { // unmarshal signal request var req v1.SomeSignal3Request if err := input.Request.UnmarshalTo(&req); err != nil { @@ -2277,7 +2413,7 @@ func (a *simpleActivities) SomeSignal3(ctx context.Context, input *v11.SignalReq } // SomeUpdate1 executes a(n) mycompany.simple.Simple.SomeUpdate1 update via an activity -func (a *simpleActivities) SomeUpdate1(ctx context.Context, input *v11.UpdateRequest) (resp *v1.SomeUpdate1Response, err error) { +func (a *simpleActivities) SomeUpdate1(ctx context.Context, input *v13.UpdateRequest) (resp *v1.SomeUpdate1Response, err error) { var handle v1.SomeUpdate1Handle if activity.HasHeartbeatDetails(ctx) { // extract update id from heartbeat details @@ -2307,8 +2443,8 @@ func (a *simpleActivities) SomeUpdate1(ctx context.Context, input *v11.UpdateReq } uo := xns.UnmarshalUpdateWorkflowOptions(input.GetUpdateWorkflowOptions()) - uo.WaitPolicy = &v12.WaitPolicy{ - LifecycleStage: v13.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ACCEPTED, + uo.WaitPolicy = &v14.WaitPolicy{ + LifecycleStage: v11.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ACCEPTED, } // initialize update execution @@ -2429,6 +2565,7 @@ type OtherWorkflowWorkflowOptions struct { ActivityOptions *workflow.ActivityOptions Detached bool HeartbeatInterval time.Duration + ParentClosePolicy v11.ParentClosePolicy StartWorkflowOptions *client.StartWorkflowOptions } @@ -2455,6 +2592,12 @@ func (opts *OtherWorkflowWorkflowOptions) WithHeartbeatInterval(d time.Duration) return opts } +// WithParentClosePolicy can be used to customize the cancellation propagation behavior +func (opts *OtherWorkflowWorkflowOptions) WithParentClosePolicy(policy v11.ParentClosePolicy) *OtherWorkflowWorkflowOptions { + opts.ParentClosePolicy = policy + return opts +} + // WithStartWorkflowOptions can be used to customize the start workflow options func (opts *OtherWorkflowWorkflowOptions) WithStartWorkflow(swo client.StartWorkflowOptions) *OtherWorkflowWorkflowOptions { opts.StartWorkflowOptions = &swo @@ -2603,13 +2746,24 @@ func OtherWorkflowAsync(ctx workflow.Context, req *v1.OtherWorkflowRequest, opts return nil, fmt.Errorf("error marshalling workflow request: %w", err) } + var parentClosePolicy v12.ParentClosePolicy + switch opt.ParentClosePolicy { + case v11.PARENT_CLOSE_POLICY_ABANDON: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON + case v11.PARENT_CLOSE_POLICY_REQUEST_CANCEL: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL + case v11.PARENT_CLOSE_POLICY_TERMINATE: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_TERMINATE + } + ctx, cancel := workflow.WithCancel(ctx) return &otherWorkflowRun{ cancel: cancel, id: wo.ID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.WorkflowRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.WorkflowRequest{ Detached: opt.Detached, HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), + ParentClosePolicy: parentClosePolicy, Request: wreq, StartWorkflowOptions: swo, }), @@ -2728,7 +2882,7 @@ func OtherQueryAsync(ctx workflow.Context, workflowID string, runID string, opts ctx, cancel := workflow.WithCancel(ctx) return &otherQueryQueryHandle{ cancel: cancel, - future: workflow.ExecuteActivity(ctx, activityName, &v11.QueryRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.QueryRequest{ HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), WorkflowId: workflowID, RunId: runID, @@ -2848,7 +3002,7 @@ func OtherSignalAsync(ctx workflow.Context, workflowID string, runID string, req ctx, cancel := workflow.WithCancel(ctx) return &otherSignalSignalHandle{ cancel: cancel, - future: workflow.ExecuteActivity(ctx, activityName, &v11.SignalRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.SignalRequest{ HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), WorkflowId: workflowID, RunId: runID, @@ -3030,7 +3184,7 @@ func OtherUpdateAsync(ctx workflow.Context, workflowID string, runID string, req return &otherUpdateHandle{ cancel: cancel, id: uo.UpdateID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.UpdateRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.UpdateRequest{ HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), Request: wreq, UpdateWorkflowOptions: uopb, @@ -3074,7 +3228,7 @@ func (a *otherActivities) CancelWorkflow(ctx context.Context, workflowID string, } // OtherWorkflow executes a(n) mycompany.simple.Other.OtherWorkflow workflow via an activity -func (a *otherActivities) OtherWorkflow(ctx context.Context, input *v11.WorkflowRequest) (resp *v1.OtherWorkflowResponse, err error) { +func (a *otherActivities) OtherWorkflow(ctx context.Context, input *v13.WorkflowRequest) (resp *v1.OtherWorkflowResponse, err error) { // unmarshal workflow request var req v1.OtherWorkflowRequest if err := input.Request.UnmarshalTo(&req); err != nil { @@ -3108,21 +3262,48 @@ func (a *otherActivities) OtherWorkflow(ctx context.Context, input *v11.Workflow heartbeatInterval := input.GetHeartbeatInterval().AsDuration() if heartbeatInterval == 0 { - heartbeatInterval = time.Minute + heartbeatInterval = time.Second * 30 } // heartbeat activity while waiting for workflow execution to complete for { select { + // send heartbeats periodically case <-time.After(heartbeatInterval): activity.RecordHeartbeat(ctx, run.ID()) + + // return retryable error on worker close + case <-activity.GetWorkerStopChannel(ctx): + return nil, temporal.NewApplicationError("worker is stopping", "WorkerStopped") + + // catch parent activity context cancellation. in most cases, this should indicate a + // server-sent cancellation, but there's a non-zero possibility that this cancellation + // is received due to the worker stopping, prior to detecting the closing of the worker + // stop channel. to give us an opportunity to detect a cancellation stemming from the + // worker closing, we again check to see if the worker stop channel is closed before + // propagating the cancellation case <-ctx.Done(): - disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) - defer cancel() - if err := run.Cancel(disconnectedCtx); err != nil { - return nil, otherOptions.convertError(err) + select { + case <-activity.GetWorkerStopChannel(ctx): + return nil, temporal.NewApplicationError("worker is stopping", "WorkerStopped") + default: + parentClosePolicy := input.GetParentClosePolicy() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL || parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON { + disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) + defer cancel() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL { + err = run.Cancel(disconnectedCtx) + } else { + err = run.Terminate(disconnectedCtx, "xns activity cancellation received", "error", ctx.Err()) + } + if err != nil { + return nil, otherOptions.convertError(err) + } + } + return nil, otherOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) } - return nil, otherOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) + + // handle workflow completion case <-doneCh: return resp, otherOptions.convertError(err) } @@ -3130,7 +3311,7 @@ func (a *otherActivities) OtherWorkflow(ctx context.Context, input *v11.Workflow } // OtherQuery executes a(n) mycompany.simple.Other.OtherQuery query via an activity -func (a *otherActivities) OtherQuery(ctx context.Context, input *v11.QueryRequest) (resp *v1.OtherQueryResponse, err error) { +func (a *otherActivities) OtherQuery(ctx context.Context, input *v13.QueryRequest) (resp *v1.OtherQueryResponse, err error) { // execute signal in child goroutine doneCh := make(chan struct{}) go func() { @@ -3157,7 +3338,7 @@ func (a *otherActivities) OtherQuery(ctx context.Context, input *v11.QueryReques } // OtherSignal executes a(n) mycompany.simple.Other.OtherSignal signal via an activity -func (a *otherActivities) OtherSignal(ctx context.Context, input *v11.SignalRequest) (err error) { +func (a *otherActivities) OtherSignal(ctx context.Context, input *v13.SignalRequest) (err error) { // unmarshal signal request var req v1.OtherSignalRequest if err := input.Request.UnmarshalTo(&req); err != nil { @@ -3193,7 +3374,7 @@ func (a *otherActivities) OtherSignal(ctx context.Context, input *v11.SignalRequ } // OtherUpdate executes a(n) mycompany.simple.Other.OtherUpdate update via an activity -func (a *otherActivities) OtherUpdate(ctx context.Context, input *v11.UpdateRequest) (resp *v1.OtherUpdateResponse, err error) { +func (a *otherActivities) OtherUpdate(ctx context.Context, input *v13.UpdateRequest) (resp *v1.OtherUpdateResponse, err error) { var handle v1.OtherUpdateHandle if activity.HasHeartbeatDetails(ctx) { // extract update id from heartbeat details @@ -3223,8 +3404,8 @@ func (a *otherActivities) OtherUpdate(ctx context.Context, input *v11.UpdateRequ } uo := xns.UnmarshalUpdateWorkflowOptions(input.GetUpdateWorkflowOptions()) - uo.WaitPolicy = &v12.WaitPolicy{ - LifecycleStage: v13.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ACCEPTED, + uo.WaitPolicy = &v14.WaitPolicy{ + LifecycleStage: v11.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ACCEPTED, } // initialize update execution @@ -3336,6 +3517,7 @@ type WhatWorkflowOptions struct { ActivityOptions *workflow.ActivityOptions Detached bool HeartbeatInterval time.Duration + ParentClosePolicy v11.ParentClosePolicy StartWorkflowOptions *client.StartWorkflowOptions } @@ -3362,6 +3544,12 @@ func (opts *WhatWorkflowOptions) WithHeartbeatInterval(d time.Duration) *WhatWor return opts } +// WithParentClosePolicy can be used to customize the cancellation propagation behavior +func (opts *WhatWorkflowOptions) WithParentClosePolicy(policy v11.ParentClosePolicy) *WhatWorkflowOptions { + opts.ParentClosePolicy = policy + return opts +} + // WithStartWorkflowOptions can be used to customize the start workflow options func (opts *WhatWorkflowOptions) WithStartWorkflow(swo client.StartWorkflowOptions) *WhatWorkflowOptions { opts.StartWorkflowOptions = &swo @@ -3509,13 +3697,24 @@ func WhatAsync(ctx workflow.Context, req *v1.WhatRequest, opts ...*WhatWorkflowO return nil, fmt.Errorf("error marshalling workflow request: %w", err) } + var parentClosePolicy v12.ParentClosePolicy + switch opt.ParentClosePolicy { + case v11.PARENT_CLOSE_POLICY_ABANDON: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON + case v11.PARENT_CLOSE_POLICY_REQUEST_CANCEL: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL + case v11.PARENT_CLOSE_POLICY_TERMINATE: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_TERMINATE + } + ctx, cancel := workflow.WithCancel(ctx) return &whatRun{ cancel: cancel, id: wo.ID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.WorkflowRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.WorkflowRequest{ Detached: opt.Detached, HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), + ParentClosePolicy: parentClosePolicy, Request: wreq, StartWorkflowOptions: swo, }), @@ -3558,7 +3757,7 @@ func (a *ignoredActivities) CancelWorkflow(ctx context.Context, workflowID strin } // What executes a(n) mycompany.simple.Ignored.What workflow via an activity -func (a *ignoredActivities) What(ctx context.Context, input *v11.WorkflowRequest) (err error) { +func (a *ignoredActivities) What(ctx context.Context, input *v13.WorkflowRequest) (err error) { // unmarshal workflow request var req v1.WhatRequest if err := input.Request.UnmarshalTo(&req); err != nil { @@ -3592,21 +3791,48 @@ func (a *ignoredActivities) What(ctx context.Context, input *v11.WorkflowRequest heartbeatInterval := input.GetHeartbeatInterval().AsDuration() if heartbeatInterval == 0 { - heartbeatInterval = time.Minute + heartbeatInterval = time.Second * 30 } // heartbeat activity while waiting for workflow execution to complete for { select { + // send heartbeats periodically case <-time.After(heartbeatInterval): activity.RecordHeartbeat(ctx, run.ID()) + + // return retryable error on worker close + case <-activity.GetWorkerStopChannel(ctx): + return temporal.NewApplicationError("worker is stopping", "WorkerStopped") + + // catch parent activity context cancellation. in most cases, this should indicate a + // server-sent cancellation, but there's a non-zero possibility that this cancellation + // is received due to the worker stopping, prior to detecting the closing of the worker + // stop channel. to give us an opportunity to detect a cancellation stemming from the + // worker closing, we again check to see if the worker stop channel is closed before + // propagating the cancellation case <-ctx.Done(): - disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) - defer cancel() - if err := run.Cancel(disconnectedCtx); err != nil { - return ignoredOptions.convertError(err) + select { + case <-activity.GetWorkerStopChannel(ctx): + return temporal.NewApplicationError("worker is stopping", "WorkerStopped") + default: + parentClosePolicy := input.GetParentClosePolicy() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL || parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON { + disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) + defer cancel() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL { + err = run.Cancel(disconnectedCtx) + } else { + err = run.Terminate(disconnectedCtx, "xns activity cancellation received", "error", ctx.Err()) + } + if err != nil { + return ignoredOptions.convertError(err) + } + } + return ignoredOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) } - return ignoredOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) + + // handle workflow completion case <-doneCh: return ignoredOptions.convertError(err) } @@ -3807,6 +4033,7 @@ type SomeDeprecatedWorkflow1WorkflowOptions struct { ActivityOptions *workflow.ActivityOptions Detached bool HeartbeatInterval time.Duration + ParentClosePolicy v11.ParentClosePolicy StartWorkflowOptions *client.StartWorkflowOptions } @@ -3833,6 +4060,12 @@ func (opts *SomeDeprecatedWorkflow1WorkflowOptions) WithHeartbeatInterval(d time return opts } +// WithParentClosePolicy can be used to customize the cancellation propagation behavior +func (opts *SomeDeprecatedWorkflow1WorkflowOptions) WithParentClosePolicy(policy v11.ParentClosePolicy) *SomeDeprecatedWorkflow1WorkflowOptions { + opts.ParentClosePolicy = policy + return opts +} + // WithStartWorkflowOptions can be used to customize the start workflow options func (opts *SomeDeprecatedWorkflow1WorkflowOptions) WithStartWorkflow(swo client.StartWorkflowOptions) *SomeDeprecatedWorkflow1WorkflowOptions { opts.StartWorkflowOptions = &swo @@ -4045,13 +4278,24 @@ func SomeDeprecatedWorkflow1Async(ctx workflow.Context, req *v1.SomeDeprecatedMe return nil, fmt.Errorf("error marshalling workflow request: %w", err) } + var parentClosePolicy v12.ParentClosePolicy + switch opt.ParentClosePolicy { + case v11.PARENT_CLOSE_POLICY_ABANDON: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON + case v11.PARENT_CLOSE_POLICY_REQUEST_CANCEL: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL + case v11.PARENT_CLOSE_POLICY_TERMINATE: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_TERMINATE + } + ctx, cancel := workflow.WithCancel(ctx) return &someDeprecatedWorkflow1Run{ cancel: cancel, id: wo.ID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.WorkflowRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.WorkflowRequest{ Detached: opt.Detached, HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), + ParentClosePolicy: parentClosePolicy, Request: wreq, StartWorkflowOptions: swo, }), @@ -4152,7 +4396,7 @@ func SomeDeprecatedWorkflow1WithSomeDeprecatedSignal1Async(ctx workflow.Context, return &someDeprecatedWorkflow1Run{ cancel: cancel, id: wo.ID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.WorkflowRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.WorkflowRequest{ Detached: opt.Detached, HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), Request: wreq, @@ -4167,6 +4411,7 @@ type SomeDeprecatedWorkflow2WorkflowOptions struct { ActivityOptions *workflow.ActivityOptions Detached bool HeartbeatInterval time.Duration + ParentClosePolicy v11.ParentClosePolicy StartWorkflowOptions *client.StartWorkflowOptions } @@ -4193,6 +4438,12 @@ func (opts *SomeDeprecatedWorkflow2WorkflowOptions) WithHeartbeatInterval(d time return opts } +// WithParentClosePolicy can be used to customize the cancellation propagation behavior +func (opts *SomeDeprecatedWorkflow2WorkflowOptions) WithParentClosePolicy(policy v11.ParentClosePolicy) *SomeDeprecatedWorkflow2WorkflowOptions { + opts.ParentClosePolicy = policy + return opts +} + // WithStartWorkflowOptions can be used to customize the start workflow options func (opts *SomeDeprecatedWorkflow2WorkflowOptions) WithStartWorkflow(swo client.StartWorkflowOptions) *SomeDeprecatedWorkflow2WorkflowOptions { opts.StartWorkflowOptions = &swo @@ -4407,13 +4658,24 @@ func SomeDeprecatedWorkflow2Async(ctx workflow.Context, req *v1.SomeDeprecatedMe return nil, fmt.Errorf("error marshalling workflow request: %w", err) } + var parentClosePolicy v12.ParentClosePolicy + switch opt.ParentClosePolicy { + case v11.PARENT_CLOSE_POLICY_ABANDON: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON + case v11.PARENT_CLOSE_POLICY_REQUEST_CANCEL: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL + case v11.PARENT_CLOSE_POLICY_TERMINATE: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_TERMINATE + } + ctx, cancel := workflow.WithCancel(ctx) return &someDeprecatedWorkflow2Run{ cancel: cancel, id: wo.ID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.WorkflowRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.WorkflowRequest{ Detached: opt.Detached, HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), + ParentClosePolicy: parentClosePolicy, Request: wreq, StartWorkflowOptions: swo, }), @@ -4514,7 +4776,7 @@ func SomeDeprecatedWorkflow2WithSomeDeprecatedSignal2Async(ctx workflow.Context, return &someDeprecatedWorkflow2Run{ cancel: cancel, id: wo.ID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.WorkflowRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.WorkflowRequest{ Detached: opt.Detached, HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), Request: wreq, @@ -4648,7 +4910,7 @@ func SomeDeprecatedQuery1Async(ctx workflow.Context, workflowID string, runID st ctx, cancel := workflow.WithCancel(ctx) return &someDeprecatedQuery1QueryHandle{ cancel: cancel, - future: workflow.ExecuteActivity(ctx, activityName, &v11.QueryRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.QueryRequest{ HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), WorkflowId: workflowID, RunId: runID, @@ -4781,7 +5043,7 @@ func SomeDeprecatedQuery2Async(ctx workflow.Context, workflowID string, runID st ctx, cancel := workflow.WithCancel(ctx) return &someDeprecatedQuery2QueryHandle{ cancel: cancel, - future: workflow.ExecuteActivity(ctx, activityName, &v11.QueryRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.QueryRequest{ HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), WorkflowId: workflowID, RunId: runID, @@ -4908,7 +5170,7 @@ func SomeDeprecatedSignal1Async(ctx workflow.Context, workflowID string, runID s ctx, cancel := workflow.WithCancel(ctx) return &someDeprecatedSignal1SignalHandle{ cancel: cancel, - future: workflow.ExecuteActivity(ctx, activityName, &v11.SignalRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.SignalRequest{ HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), WorkflowId: workflowID, RunId: runID, @@ -5035,7 +5297,7 @@ func SomeDeprecatedSignal2Async(ctx workflow.Context, workflowID string, runID s ctx, cancel := workflow.WithCancel(ctx) return &someDeprecatedSignal2SignalHandle{ cancel: cancel, - future: workflow.ExecuteActivity(ctx, activityName, &v11.SignalRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.SignalRequest{ HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), WorkflowId: workflowID, RunId: runID, @@ -5211,7 +5473,7 @@ func SomeDeprecatedUpdate1Async(ctx workflow.Context, workflowID string, runID s return &someDeprecatedUpdate1Handle{ cancel: cancel, id: uo.UpdateID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.UpdateRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.UpdateRequest{ HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), Request: wreq, UpdateWorkflowOptions: uopb, @@ -5386,7 +5648,7 @@ func SomeDeprecatedUpdate2Async(ctx workflow.Context, workflowID string, runID s return &someDeprecatedUpdate2Handle{ cancel: cancel, id: uo.UpdateID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.UpdateRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.UpdateRequest{ HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), Request: wreq, UpdateWorkflowOptions: uopb, @@ -5432,7 +5694,7 @@ func (a *deprecatedActivities) CancelWorkflow(ctx context.Context, workflowID st // SomeDeprecatedWorkflow1 executes a(n) mycompany.simple.Deprecated.SomeDeprecatedWorkflow1 workflow via an activity // // Deprecated: Do not use. -func (a *deprecatedActivities) SomeDeprecatedWorkflow1(ctx context.Context, input *v11.WorkflowRequest) (resp *v1.SomeDeprecatedMessage, err error) { +func (a *deprecatedActivities) SomeDeprecatedWorkflow1(ctx context.Context, input *v13.WorkflowRequest) (resp *v1.SomeDeprecatedMessage, err error) { activity.GetLogger(ctx).Warn("use of deprecated workflow detected", "workflow", v1.SomeDeprecatedWorkflow1WorkflowName) // unmarshal workflow request @@ -5468,21 +5730,48 @@ func (a *deprecatedActivities) SomeDeprecatedWorkflow1(ctx context.Context, inpu heartbeatInterval := input.GetHeartbeatInterval().AsDuration() if heartbeatInterval == 0 { - heartbeatInterval = time.Minute + heartbeatInterval = time.Second * 30 } // heartbeat activity while waiting for workflow execution to complete for { select { + // send heartbeats periodically case <-time.After(heartbeatInterval): activity.RecordHeartbeat(ctx, run.ID()) + + // return retryable error on worker close + case <-activity.GetWorkerStopChannel(ctx): + return nil, temporal.NewApplicationError("worker is stopping", "WorkerStopped") + + // catch parent activity context cancellation. in most cases, this should indicate a + // server-sent cancellation, but there's a non-zero possibility that this cancellation + // is received due to the worker stopping, prior to detecting the closing of the worker + // stop channel. to give us an opportunity to detect a cancellation stemming from the + // worker closing, we again check to see if the worker stop channel is closed before + // propagating the cancellation case <-ctx.Done(): - disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) - defer cancel() - if err := run.Cancel(disconnectedCtx); err != nil { - return nil, deprecatedOptions.convertError(err) + select { + case <-activity.GetWorkerStopChannel(ctx): + return nil, temporal.NewApplicationError("worker is stopping", "WorkerStopped") + default: + parentClosePolicy := input.GetParentClosePolicy() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL || parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON { + disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) + defer cancel() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL { + err = run.Cancel(disconnectedCtx) + } else { + err = run.Terminate(disconnectedCtx, "xns activity cancellation received", "error", ctx.Err()) + } + if err != nil { + return nil, deprecatedOptions.convertError(err) + } + } + return nil, deprecatedOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) } - return nil, deprecatedOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) + + // handle workflow completion case <-doneCh: return resp, deprecatedOptions.convertError(err) } @@ -5492,7 +5781,7 @@ func (a *deprecatedActivities) SomeDeprecatedWorkflow1(ctx context.Context, inpu // SomeDeprecatedWorkflow1WithSomeDeprecatedSignal1 sends a(n) mycompany.simple.Deprecated.SomeDeprecatedSignal1 signal to a(n) mycompany.simple.Deprecated.SomeDeprecatedWorkflow1 workflow via an activity // // Deprecated: Do not use. -func (a *deprecatedActivities) SomeDeprecatedWorkflow1WithSomeDeprecatedSignal1(ctx context.Context, input *v11.WorkflowRequest) (resp *v1.SomeDeprecatedMessage, err error) { +func (a *deprecatedActivities) SomeDeprecatedWorkflow1WithSomeDeprecatedSignal1(ctx context.Context, input *v13.WorkflowRequest) (resp *v1.SomeDeprecatedMessage, err error) { activity.GetLogger(ctx).Warn("use of deprecated workflow detected", "workflow", v1.SomeDeprecatedWorkflow1WorkflowName) activity.GetLogger(ctx).Warn("use of deprecated signal detected", "signal", v1.SomeDeprecatedSignal1SignalName) @@ -5563,7 +5852,7 @@ func (a *deprecatedActivities) SomeDeprecatedWorkflow1WithSomeDeprecatedSignal1( // SomeDeprecatedWorkflow2 executes a(n) mycompany.simple.Deprecated.SomeDeprecatedWorkflow2 workflow via an activity // // Deprecated: Do not use. -func (a *deprecatedActivities) SomeDeprecatedWorkflow2(ctx context.Context, input *v11.WorkflowRequest) (resp *v1.SomeDeprecatedMessage, err error) { +func (a *deprecatedActivities) SomeDeprecatedWorkflow2(ctx context.Context, input *v13.WorkflowRequest) (resp *v1.SomeDeprecatedMessage, err error) { activity.GetLogger(ctx).Warn("use of deprecated workflow detected", "workflow", v1.SomeDeprecatedWorkflow2WorkflowName) // unmarshal workflow request @@ -5599,21 +5888,48 @@ func (a *deprecatedActivities) SomeDeprecatedWorkflow2(ctx context.Context, inpu heartbeatInterval := input.GetHeartbeatInterval().AsDuration() if heartbeatInterval == 0 { - heartbeatInterval = time.Minute + heartbeatInterval = time.Second * 30 } // heartbeat activity while waiting for workflow execution to complete for { select { + // send heartbeats periodically case <-time.After(heartbeatInterval): activity.RecordHeartbeat(ctx, run.ID()) + + // return retryable error on worker close + case <-activity.GetWorkerStopChannel(ctx): + return nil, temporal.NewApplicationError("worker is stopping", "WorkerStopped") + + // catch parent activity context cancellation. in most cases, this should indicate a + // server-sent cancellation, but there's a non-zero possibility that this cancellation + // is received due to the worker stopping, prior to detecting the closing of the worker + // stop channel. to give us an opportunity to detect a cancellation stemming from the + // worker closing, we again check to see if the worker stop channel is closed before + // propagating the cancellation case <-ctx.Done(): - disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) - defer cancel() - if err := run.Cancel(disconnectedCtx); err != nil { - return nil, deprecatedOptions.convertError(err) + select { + case <-activity.GetWorkerStopChannel(ctx): + return nil, temporal.NewApplicationError("worker is stopping", "WorkerStopped") + default: + parentClosePolicy := input.GetParentClosePolicy() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL || parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON { + disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) + defer cancel() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL { + err = run.Cancel(disconnectedCtx) + } else { + err = run.Terminate(disconnectedCtx, "xns activity cancellation received", "error", ctx.Err()) + } + if err != nil { + return nil, deprecatedOptions.convertError(err) + } + } + return nil, deprecatedOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) } - return nil, deprecatedOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) + + // handle workflow completion case <-doneCh: return resp, deprecatedOptions.convertError(err) } @@ -5623,7 +5939,7 @@ func (a *deprecatedActivities) SomeDeprecatedWorkflow2(ctx context.Context, inpu // SomeDeprecatedWorkflow2WithSomeDeprecatedSignal2 sends a(n) mycompany.simple.Deprecated.SomeDeprecatedSignal2 signal to a(n) mycompany.simple.Deprecated.SomeDeprecatedWorkflow2 workflow via an activity // // Deprecated: Do not use. -func (a *deprecatedActivities) SomeDeprecatedWorkflow2WithSomeDeprecatedSignal2(ctx context.Context, input *v11.WorkflowRequest) (resp *v1.SomeDeprecatedMessage, err error) { +func (a *deprecatedActivities) SomeDeprecatedWorkflow2WithSomeDeprecatedSignal2(ctx context.Context, input *v13.WorkflowRequest) (resp *v1.SomeDeprecatedMessage, err error) { activity.GetLogger(ctx).Warn("use of deprecated workflow detected", "workflow", v1.SomeDeprecatedWorkflow2WorkflowName) activity.GetLogger(ctx).Warn("use of deprecated signal detected", "signal", v1.SomeDeprecatedSignal2SignalName) @@ -5694,7 +6010,7 @@ func (a *deprecatedActivities) SomeDeprecatedWorkflow2WithSomeDeprecatedSignal2( // SomeDeprecatedQuery1 executes a(n) mycompany.simple.Deprecated.SomeDeprecatedQuery1 query via an activity // // Deprecated: Do not use. -func (a *deprecatedActivities) SomeDeprecatedQuery1(ctx context.Context, input *v11.QueryRequest) (resp *v1.SomeDeprecatedMessage, err error) { +func (a *deprecatedActivities) SomeDeprecatedQuery1(ctx context.Context, input *v13.QueryRequest) (resp *v1.SomeDeprecatedMessage, err error) { activity.GetLogger(ctx).Warn("use of deprecated query detected", "query", v1.SomeDeprecatedQuery1QueryName) // unmarshal query request @@ -5734,7 +6050,7 @@ func (a *deprecatedActivities) SomeDeprecatedQuery1(ctx context.Context, input * // SomeDeprecatedQuery2 executes a(n) mycompany.simple.Deprecated.SomeDeprecatedQuery2 query via an activity // // Deprecated: Do not use. -func (a *deprecatedActivities) SomeDeprecatedQuery2(ctx context.Context, input *v11.QueryRequest) (resp *v1.SomeDeprecatedMessage, err error) { +func (a *deprecatedActivities) SomeDeprecatedQuery2(ctx context.Context, input *v13.QueryRequest) (resp *v1.SomeDeprecatedMessage, err error) { activity.GetLogger(ctx).Warn("use of deprecated query detected", "query", v1.SomeDeprecatedQuery2QueryName) // unmarshal query request @@ -5774,7 +6090,7 @@ func (a *deprecatedActivities) SomeDeprecatedQuery2(ctx context.Context, input * // SomeDeprecatedSignal1 executes a(n) mycompany.simple.Deprecated.SomeDeprecatedSignal1 signal via an activity // // Deprecated: Do not use. -func (a *deprecatedActivities) SomeDeprecatedSignal1(ctx context.Context, input *v11.SignalRequest) (err error) { +func (a *deprecatedActivities) SomeDeprecatedSignal1(ctx context.Context, input *v13.SignalRequest) (err error) { activity.GetLogger(ctx).Warn("use of deprecated signal detected", "signal", v1.SomeDeprecatedSignal1SignalName) // unmarshal signal request @@ -5814,7 +6130,7 @@ func (a *deprecatedActivities) SomeDeprecatedSignal1(ctx context.Context, input // SomeDeprecatedSignal2 executes a(n) mycompany.simple.Deprecated.SomeDeprecatedSignal2 signal via an activity // // Deprecated: Do not use. -func (a *deprecatedActivities) SomeDeprecatedSignal2(ctx context.Context, input *v11.SignalRequest) (err error) { +func (a *deprecatedActivities) SomeDeprecatedSignal2(ctx context.Context, input *v13.SignalRequest) (err error) { activity.GetLogger(ctx).Warn("use of deprecated signal detected", "signal", v1.SomeDeprecatedSignal2SignalName) // unmarshal signal request @@ -5854,7 +6170,7 @@ func (a *deprecatedActivities) SomeDeprecatedSignal2(ctx context.Context, input // SomeDeprecatedUpdate1 executes a(n) mycompany.simple.Deprecated.SomeDeprecatedUpdate1 update via an activity // // Deprecated: Do not use. -func (a *deprecatedActivities) SomeDeprecatedUpdate1(ctx context.Context, input *v11.UpdateRequest) (resp *v1.SomeDeprecatedMessage, err error) { +func (a *deprecatedActivities) SomeDeprecatedUpdate1(ctx context.Context, input *v13.UpdateRequest) (resp *v1.SomeDeprecatedMessage, err error) { activity.GetLogger(ctx).Warn("use of deprecated update detected", "update", v1.SomeDeprecatedUpdate1UpdateName) var handle v1.SomeDeprecatedUpdate1Handle @@ -5886,8 +6202,8 @@ func (a *deprecatedActivities) SomeDeprecatedUpdate1(ctx context.Context, input } uo := xns.UnmarshalUpdateWorkflowOptions(input.GetUpdateWorkflowOptions()) - uo.WaitPolicy = &v12.WaitPolicy{ - LifecycleStage: v13.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ACCEPTED, + uo.WaitPolicy = &v14.WaitPolicy{ + LifecycleStage: v11.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ACCEPTED, } // initialize update execution @@ -5932,7 +6248,7 @@ func (a *deprecatedActivities) SomeDeprecatedUpdate1(ctx context.Context, input // SomeDeprecatedUpdate2 executes a(n) mycompany.simple.Deprecated.SomeDeprecatedUpdate2 update via an activity // // Deprecated: Do not use. -func (a *deprecatedActivities) SomeDeprecatedUpdate2(ctx context.Context, input *v11.UpdateRequest) (resp *v1.SomeDeprecatedMessage, err error) { +func (a *deprecatedActivities) SomeDeprecatedUpdate2(ctx context.Context, input *v13.UpdateRequest) (resp *v1.SomeDeprecatedMessage, err error) { activity.GetLogger(ctx).Warn("use of deprecated update detected", "update", v1.SomeDeprecatedUpdate2UpdateName) var handle v1.SomeDeprecatedUpdate2Handle @@ -5964,8 +6280,8 @@ func (a *deprecatedActivities) SomeDeprecatedUpdate2(ctx context.Context, input } uo := xns.UnmarshalUpdateWorkflowOptions(input.GetUpdateWorkflowOptions()) - uo.WaitPolicy = &v12.WaitPolicy{ - LifecycleStage: v13.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ACCEPTED, + uo.WaitPolicy = &v14.WaitPolicy{ + LifecycleStage: v11.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ACCEPTED, } // initialize update execution diff --git a/gen/test/xnserr/v1/xnserr.pb.go b/gen/test/xnserr/v1/xnserr.pb.go index 2943eaf7..039a67a8 100644 --- a/gen/test/xnserr/v1/xnserr.pb.go +++ b/gen/test/xnserr/v1/xnserr.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.34.1 // protoc (unknown) // source: test/xnserr/v1/xnserr.proto @@ -350,34 +350,34 @@ var file_test_xnserr_v1_xnserr_proto_rawDesc = []byte{ 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x06, 0x12, 0x29, 0x0a, 0x25, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x43, 0x48, 0x49, 0x4c, 0x44, 0x5f, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, - 0x57, 0x5f, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x07, 0x32, 0x72, 0x0a, - 0x06, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x50, 0x0a, 0x05, 0x53, 0x6c, 0x65, 0x65, 0x70, + 0x57, 0x5f, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x07, 0x32, 0x74, 0x0a, + 0x06, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x05, 0x53, 0x6c, 0x65, 0x65, 0x70, 0x12, 0x1c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x78, 0x6e, 0x73, 0x65, 0x72, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6c, 0x65, 0x65, 0x70, 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, 0x11, 0x8a, 0xc4, 0x03, 0x0d, 0x30, 0x03, 0x82, 0x01, - 0x08, 0x2a, 0x02, 0x08, 0x1e, 0x42, 0x02, 0x08, 0x0a, 0x1a, 0x16, 0x8a, 0xc4, 0x03, 0x12, 0x0a, - 0x10, 0x78, 0x6e, 0x73, 0x65, 0x72, 0x72, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2d, 0x76, - 0x31, 0x32, 0x6d, 0x0a, 0x06, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x4b, 0x0a, 0x09, 0x43, - 0x61, 0x6c, 0x6c, 0x53, 0x6c, 0x65, 0x65, 0x70, 0x12, 0x20, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, - 0x78, 0x6e, 0x73, 0x65, 0x72, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x53, 0x6c, - 0x65, 0x65, 0x70, 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, 0x04, 0x8a, 0xc4, 0x03, 0x00, 0x1a, 0x16, 0x8a, 0xc4, 0x03, 0x12, 0x0a, 0x10, - 0x78, 0x6e, 0x73, 0x65, 0x72, 0x72, 0x2d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2d, 0x76, 0x31, - 0x42, 0xc2, 0x01, 0x0a, 0x12, 0x63, 0x6f, 0x6d, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x78, 0x6e, - 0x73, 0x65, 0x72, 0x72, 0x2e, 0x76, 0x31, 0x42, 0x0b, 0x58, 0x6e, 0x73, 0x65, 0x72, 0x72, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x45, 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, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x78, 0x6e, 0x73, 0x65, 0x72, - 0x72, 0x2f, 0x76, 0x31, 0x3b, 0x78, 0x6e, 0x73, 0x65, 0x72, 0x72, 0x76, 0x31, 0xa2, 0x02, 0x03, - 0x54, 0x58, 0x58, 0xaa, 0x02, 0x0e, 0x54, 0x65, 0x73, 0x74, 0x2e, 0x58, 0x6e, 0x73, 0x65, 0x72, - 0x72, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0e, 0x54, 0x65, 0x73, 0x74, 0x5c, 0x58, 0x6e, 0x73, 0x65, - 0x72, 0x72, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1a, 0x54, 0x65, 0x73, 0x74, 0x5c, 0x58, 0x6e, 0x73, - 0x65, 0x72, 0x72, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0xea, 0x02, 0x10, 0x54, 0x65, 0x73, 0x74, 0x3a, 0x3a, 0x58, 0x6e, 0x73, 0x65, 0x72, - 0x72, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x13, 0x8a, 0xc4, 0x03, 0x0f, 0x30, 0x03, 0x40, 0x03, + 0x82, 0x01, 0x08, 0x2a, 0x02, 0x08, 0x1e, 0x42, 0x02, 0x08, 0x0a, 0x1a, 0x16, 0x8a, 0xc4, 0x03, + 0x12, 0x0a, 0x10, 0x78, 0x6e, 0x73, 0x65, 0x72, 0x72, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x2d, 0x76, 0x31, 0x32, 0x6d, 0x0a, 0x06, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x4b, 0x0a, + 0x09, 0x43, 0x61, 0x6c, 0x6c, 0x53, 0x6c, 0x65, 0x65, 0x70, 0x12, 0x20, 0x2e, 0x74, 0x65, 0x73, + 0x74, 0x2e, 0x78, 0x6e, 0x73, 0x65, 0x72, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6c, 0x6c, + 0x53, 0x6c, 0x65, 0x65, 0x70, 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, 0x04, 0x8a, 0xc4, 0x03, 0x00, 0x1a, 0x16, 0x8a, 0xc4, 0x03, 0x12, + 0x0a, 0x10, 0x78, 0x6e, 0x73, 0x65, 0x72, 0x72, 0x2d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2d, + 0x76, 0x31, 0x42, 0xc2, 0x01, 0x0a, 0x12, 0x63, 0x6f, 0x6d, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, + 0x78, 0x6e, 0x73, 0x65, 0x72, 0x72, 0x2e, 0x76, 0x31, 0x42, 0x0b, 0x58, 0x6e, 0x73, 0x65, 0x72, + 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x45, 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, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x78, 0x6e, 0x73, + 0x65, 0x72, 0x72, 0x2f, 0x76, 0x31, 0x3b, 0x78, 0x6e, 0x73, 0x65, 0x72, 0x72, 0x76, 0x31, 0xa2, + 0x02, 0x03, 0x54, 0x58, 0x58, 0xaa, 0x02, 0x0e, 0x54, 0x65, 0x73, 0x74, 0x2e, 0x58, 0x6e, 0x73, + 0x65, 0x72, 0x72, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0e, 0x54, 0x65, 0x73, 0x74, 0x5c, 0x58, 0x6e, + 0x73, 0x65, 0x72, 0x72, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1a, 0x54, 0x65, 0x73, 0x74, 0x5c, 0x58, + 0x6e, 0x73, 0x65, 0x72, 0x72, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x10, 0x54, 0x65, 0x73, 0x74, 0x3a, 0x3a, 0x58, 0x6e, 0x73, + 0x65, 0x72, 0x72, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/gen/test/xnserr/v1/xnserr_temporal.pb.go b/gen/test/xnserr/v1/xnserr_temporal.pb.go index 87a38ecb..692cda4d 100644 --- a/gen/test/xnserr/v1/xnserr_temporal.pb.go +++ b/gen/test/xnserr/v1/xnserr_temporal.pb.go @@ -1,8 +1,8 @@ // Code generated by protoc-gen-go_temporal. DO NOT EDIT. // versions: // -// protoc-gen-go_temporal 1.12.1-next (ec80fd34c1a9a69042c74c5d3da0091b91ac2e0c) -// go go1.22.1 +// protoc-gen-go_temporal 1.13.1-next (fc19a4c83a5c93edb1c0e750533a8a5a3c44094e) +// go go1.22.3 // protoc (unknown) // // source: test/xnserr/v1/xnserr.proto @@ -492,6 +492,8 @@ func (o *SleepChildOptions) Build(ctx workflow.Context, req protoreflect.Message } if v := o.parentClosePolicy; v != v1.PARENT_CLOSE_POLICY_UNSPECIFIED { opts.ParentClosePolicy = v + } else if opts.ParentClosePolicy == v1.PARENT_CLOSE_POLICY_UNSPECIFIED { + opts.ParentClosePolicy = v1.PARENT_CLOSE_POLICY_REQUEST_CANCEL } if v := o.waitForCancellation; v != nil { opts.WaitForCancellation = *v diff --git a/gen/test/xnserr/v1/xnserrv1xns/xnserr_xns_temporal.pb.go b/gen/test/xnserr/v1/xnserrv1xns/xnserr_xns_temporal.pb.go index 3d6ae4b7..a48728c8 100644 --- a/gen/test/xnserr/v1/xnserrv1xns/xnserr_xns_temporal.pb.go +++ b/gen/test/xnserr/v1/xnserrv1xns/xnserr_xns_temporal.pb.go @@ -1,8 +1,8 @@ // Code generated by protoc-gen-go_temporal. DO NOT EDIT. // versions: // -// protoc-gen-go_temporal 1.12.1-next (ec80fd34c1a9a69042c74c5d3da0091b91ac2e0c) -// go go1.22.1 +// protoc-gen-go_temporal 1.13.1-next (fc19a4c83a5c93edb1c0e750533a8a5a3c44094e) +// go go1.22.3 // protoc (unknown) // // source: test/xnserr/v1/xnserr.proto @@ -12,10 +12,12 @@ import ( "context" "errors" "fmt" - v11 "github.com/cludden/protoc-gen-go-temporal/gen/temporal/xns/v1" + v12 "github.com/cludden/protoc-gen-go-temporal/gen/temporal/v1" + v13 "github.com/cludden/protoc-gen-go-temporal/gen/temporal/xns/v1" v1 "github.com/cludden/protoc-gen-go-temporal/gen/test/xnserr/v1" xns "github.com/cludden/protoc-gen-go-temporal/pkg/xns" uuid "github.com/google/uuid" + v11 "go.temporal.io/api/enums/v1" activity "go.temporal.io/sdk/activity" client "go.temporal.io/sdk/client" temporal "go.temporal.io/sdk/temporal" @@ -96,6 +98,7 @@ type SleepWorkflowOptions struct { ActivityOptions *workflow.ActivityOptions Detached bool HeartbeatInterval time.Duration + ParentClosePolicy v11.ParentClosePolicy StartWorkflowOptions *client.StartWorkflowOptions } @@ -122,6 +125,12 @@ func (opts *SleepWorkflowOptions) WithHeartbeatInterval(d time.Duration) *SleepW return opts } +// WithParentClosePolicy can be used to customize the cancellation propagation behavior +func (opts *SleepWorkflowOptions) WithParentClosePolicy(policy v11.ParentClosePolicy) *SleepWorkflowOptions { + opts.ParentClosePolicy = policy + return opts +} + // WithStartWorkflowOptions can be used to customize the start workflow options func (opts *SleepWorkflowOptions) WithStartWorkflow(swo client.StartWorkflowOptions) *SleepWorkflowOptions { opts.StartWorkflowOptions = &swo @@ -257,13 +266,24 @@ func SleepAsync(ctx workflow.Context, req *v1.SleepRequest, opts ...*SleepWorkfl return nil, fmt.Errorf("error marshalling workflow request: %w", err) } + parentClosePolicy := v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL + switch opt.ParentClosePolicy { + case v11.PARENT_CLOSE_POLICY_ABANDON: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON + case v11.PARENT_CLOSE_POLICY_REQUEST_CANCEL: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL + case v11.PARENT_CLOSE_POLICY_TERMINATE: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_TERMINATE + } + ctx, cancel := workflow.WithCancel(ctx) return &sleepRun{ cancel: cancel, id: wo.ID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.WorkflowRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.WorkflowRequest{ Detached: opt.Detached, HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), + ParentClosePolicy: parentClosePolicy, Request: wreq, StartWorkflowOptions: swo, }), @@ -306,7 +326,7 @@ func (a *serverActivities) CancelWorkflow(ctx context.Context, workflowID string } // Sleep executes a(n) test.xnserr.v1.Server.Sleep workflow via an activity -func (a *serverActivities) Sleep(ctx context.Context, input *v11.WorkflowRequest) (err error) { +func (a *serverActivities) Sleep(ctx context.Context, input *v13.WorkflowRequest) (err error) { // unmarshal workflow request var req v1.SleepRequest if err := input.Request.UnmarshalTo(&req); err != nil { @@ -340,21 +360,48 @@ func (a *serverActivities) Sleep(ctx context.Context, input *v11.WorkflowRequest heartbeatInterval := input.GetHeartbeatInterval().AsDuration() if heartbeatInterval == 0 { - heartbeatInterval = time.Minute + heartbeatInterval = time.Second * 30 } // heartbeat activity while waiting for workflow execution to complete for { select { + // send heartbeats periodically case <-time.After(heartbeatInterval): activity.RecordHeartbeat(ctx, run.ID()) + + // return retryable error on worker close + case <-activity.GetWorkerStopChannel(ctx): + return temporal.NewApplicationError("worker is stopping", "WorkerStopped") + + // catch parent activity context cancellation. in most cases, this should indicate a + // server-sent cancellation, but there's a non-zero possibility that this cancellation + // is received due to the worker stopping, prior to detecting the closing of the worker + // stop channel. to give us an opportunity to detect a cancellation stemming from the + // worker closing, we again check to see if the worker stop channel is closed before + // propagating the cancellation case <-ctx.Done(): - disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) - defer cancel() - if err := run.Cancel(disconnectedCtx); err != nil { - return serverOptions.convertError(err) + select { + case <-activity.GetWorkerStopChannel(ctx): + return temporal.NewApplicationError("worker is stopping", "WorkerStopped") + default: + parentClosePolicy := input.GetParentClosePolicy() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL || parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON { + disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) + defer cancel() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL { + err = run.Cancel(disconnectedCtx) + } else { + err = run.Terminate(disconnectedCtx, "xns activity cancellation received", "error", ctx.Err()) + } + if err != nil { + return serverOptions.convertError(err) + } + } + return serverOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) } - return serverOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) + + // handle workflow completion case <-doneCh: return serverOptions.convertError(err) } @@ -431,6 +478,7 @@ type CallSleepWorkflowOptions struct { ActivityOptions *workflow.ActivityOptions Detached bool HeartbeatInterval time.Duration + ParentClosePolicy v11.ParentClosePolicy StartWorkflowOptions *client.StartWorkflowOptions } @@ -457,6 +505,12 @@ func (opts *CallSleepWorkflowOptions) WithHeartbeatInterval(d time.Duration) *Ca return opts } +// WithParentClosePolicy can be used to customize the cancellation propagation behavior +func (opts *CallSleepWorkflowOptions) WithParentClosePolicy(policy v11.ParentClosePolicy) *CallSleepWorkflowOptions { + opts.ParentClosePolicy = policy + return opts +} + // WithStartWorkflowOptions can be used to customize the start workflow options func (opts *CallSleepWorkflowOptions) WithStartWorkflow(swo client.StartWorkflowOptions) *CallSleepWorkflowOptions { opts.StartWorkflowOptions = &swo @@ -592,13 +646,24 @@ func CallSleepAsync(ctx workflow.Context, req *v1.CallSleepRequest, opts ...*Cal return nil, fmt.Errorf("error marshalling workflow request: %w", err) } + var parentClosePolicy v12.ParentClosePolicy + switch opt.ParentClosePolicy { + case v11.PARENT_CLOSE_POLICY_ABANDON: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON + case v11.PARENT_CLOSE_POLICY_REQUEST_CANCEL: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL + case v11.PARENT_CLOSE_POLICY_TERMINATE: + parentClosePolicy = v12.ParentClosePolicy_PARENT_CLOSE_POLICY_TERMINATE + } + ctx, cancel := workflow.WithCancel(ctx) return &callSleepRun{ cancel: cancel, id: wo.ID, - future: workflow.ExecuteActivity(ctx, activityName, &v11.WorkflowRequest{ + future: workflow.ExecuteActivity(ctx, activityName, &v13.WorkflowRequest{ Detached: opt.Detached, HeartbeatInterval: durationpb.New(opt.HeartbeatInterval), + ParentClosePolicy: parentClosePolicy, Request: wreq, StartWorkflowOptions: swo, }), @@ -641,7 +706,7 @@ func (a *clientActivities) CancelWorkflow(ctx context.Context, workflowID string } // CallSleep executes a(n) test.xnserr.v1.Client.CallSleep workflow via an activity -func (a *clientActivities) CallSleep(ctx context.Context, input *v11.WorkflowRequest) (err error) { +func (a *clientActivities) CallSleep(ctx context.Context, input *v13.WorkflowRequest) (err error) { // unmarshal workflow request var req v1.CallSleepRequest if err := input.Request.UnmarshalTo(&req); err != nil { @@ -675,21 +740,48 @@ func (a *clientActivities) CallSleep(ctx context.Context, input *v11.WorkflowReq heartbeatInterval := input.GetHeartbeatInterval().AsDuration() if heartbeatInterval == 0 { - heartbeatInterval = time.Minute + heartbeatInterval = time.Second * 30 } // heartbeat activity while waiting for workflow execution to complete for { select { + // send heartbeats periodically case <-time.After(heartbeatInterval): activity.RecordHeartbeat(ctx, run.ID()) + + // return retryable error on worker close + case <-activity.GetWorkerStopChannel(ctx): + return temporal.NewApplicationError("worker is stopping", "WorkerStopped") + + // catch parent activity context cancellation. in most cases, this should indicate a + // server-sent cancellation, but there's a non-zero possibility that this cancellation + // is received due to the worker stopping, prior to detecting the closing of the worker + // stop channel. to give us an opportunity to detect a cancellation stemming from the + // worker closing, we again check to see if the worker stop channel is closed before + // propagating the cancellation case <-ctx.Done(): - disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) - defer cancel() - if err := run.Cancel(disconnectedCtx); err != nil { - return clientOptions.convertError(err) + select { + case <-activity.GetWorkerStopChannel(ctx): + return temporal.NewApplicationError("worker is stopping", "WorkerStopped") + default: + parentClosePolicy := input.GetParentClosePolicy() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL || parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON { + disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Second*5) + defer cancel() + if parentClosePolicy == v12.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL { + err = run.Cancel(disconnectedCtx) + } else { + err = run.Terminate(disconnectedCtx, "xns activity cancellation received", "error", ctx.Err()) + } + if err != nil { + return clientOptions.convertError(err) + } + } + return clientOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) } - return clientOptions.convertError(temporal.NewCanceledError(ctx.Err().Error())) + + // handle workflow completion case <-doneCh: return clientOptions.convertError(err) } diff --git a/internal/plugin/parse.go b/internal/plugin/parse.go index ebac934a..10e81b33 100644 --- a/internal/plugin/parse.go +++ b/internal/plugin/parse.go @@ -29,6 +29,7 @@ const ( protoreflectPkg = "google.golang.org/protobuf/reflect/protoreflect" serviceerrorPkg = "go.temporal.io/api/serviceerror" temporalPkg = "go.temporal.io/sdk/temporal" + temporalv1Pkg = "github.com/cludden/protoc-gen-go-temporal/gen/temporal/v1" timestamppbPkg = "google.golang.org/protobuf/types/known/timestamppb" updatePkg = "go.temporal.io/api/update/v1" uuidPkg = "github.com/google/uuid" diff --git a/internal/plugin/xns.go b/internal/plugin/xns.go index 949f81d4..5eb82867 100644 --- a/internal/plugin/xns.go +++ b/internal/plugin/xns.go @@ -500,6 +500,7 @@ func (svc *Manifest) genXNSActivitiesWorkflowMethod(f *g.File, workflow protoref if isDeprecated(method) { fn.Qual(activityPkg, "GetLogger").Call(g.Id("ctx")).Dot("Warn").Call(g.Lit("use of deprecated workflow detected"), g.Lit("workflow"), g.Qual(string(svc.File.GoImportPath), svc.toCamel("%sWorkflowName", workflow))).Line() } + if hasInput { fn.Comment("unmarshal workflow request") fn.Var().Id("req").Qual(string(svc.File.GoImportPath), svc.getMessageName(method.Input)) @@ -520,8 +521,7 @@ func (svc *Manifest) genXNSActivitiesWorkflowMethod(f *g.File, workflow protoref ), ) }), - ) - fn.Line() + ).Line() } fn.Comment("initialize workflow execution") @@ -543,8 +543,7 @@ func (svc *Manifest) genXNSActivitiesWorkflowMethod(f *g.File, workflow protoref } returnVals.Id(svc.toLowerCamel("%sOptions", svc.GoName)).Dot("convertError").Call(g.Err()) }), - ) - fn.Line() + ).Line() fn.Comment("exit early if detached enabled") fn.If(g.Id("input").Dot("GetDetached").Call()).Block( @@ -554,8 +553,7 @@ func (svc *Manifest) genXNSActivitiesWorkflowMethod(f *g.File, workflow protoref } returnVals.Nil() }), - ) - fn.Line() + ).Line() fn.Comment("otherwise, wait for execution to complete in child goroutine") fn.Id("doneCh").Op(":=").Make(g.Chan().Struct()) @@ -567,44 +565,85 @@ func (svc *Manifest) genXNSActivitiesWorkflowMethod(f *g.File, workflow protoref ls.Err() }).Op("=").Id("run").Dot("Get").Call(g.Id("ctx")), g.Close(g.Id("doneCh")), - ).Call() - fn.Line() + ).Call().Line() fn.Id("heartbeatInterval").Op(":=").Id("input").Dot("GetHeartbeatInterval").Call().Dot("AsDuration").Call() fn.If(g.Id("heartbeatInterval").Op("==").Lit(0)).Block( - g.Id("heartbeatInterval").Op("=").Qual("time", "Minute"), - ) - fn.Line() + g.Id("heartbeatInterval").Op("=").Qual("time", "Second").Op("*").Lit(30), + ).Line() fn.Comment("heartbeat activity while waiting for workflow execution to complete") fn.For().Block( g.Select().Block( + g.Comment("send heartbeats periodically"), g.Case(g.Op("<-").Qual("time", "After").Call(g.Id("heartbeatInterval"))).Block( g.Qual(activityPkg, "RecordHeartbeat").Call(g.Id("ctx"), g.Id("run").Dot("ID").Call()), - ), - g.Case(g.Op("<-").Id("ctx").Dot("Done").Call()).Block( - g.List(g.Id("disconnectedCtx"), g.Id("cancel")).Op(":=").Qual("context", "WithTimeout").Call(g.Qual("context", "Background").Call(), g.Qual("time", "Second").Op("*").Lit(5)), - g.Defer().Id("cancel").Call(), - g.If( - g.Err().Op(":=").Id("run").Dot("Cancel").Call(g.Id("disconnectedCtx")), - g.Err().Op("!=").Nil(), - ).Block( - g.ReturnFunc(func(returnVals *g.Group) { - if hasOutput { - returnVals.Nil() - } - returnVals.Id(svc.toLowerCamel("%sOptions", svc.GoName)).Dot("convertError").Call(g.Err()) - }), - ), + ).Line(), + + g.Comment("return retryable error on worker close"), + g.Case(g.Op("<-").Qual(activityPkg, "GetWorkerStopChannel").Call(g.Id("ctx"))).Block( g.ReturnFunc(func(returnVals *g.Group) { if hasOutput { returnVals.Nil() } - returnVals.Id(svc.toLowerCamel("%sOptions", svc.GoName)).Dot("convertError").Call( - g.Qual(temporalPkg, "NewCanceledError").Call(g.Id("ctx").Dot("Err").Call().Dot("Error").Call()), - ) + returnVals.Qual(temporalPkg, "NewApplicationError").Call(g.Lit("worker is stopping"), g.Lit("WorkerStopped")) }), - ), + ).Line(), + + g.Comment("catch parent activity context cancellation. in most cases, this should indicate a"), + g.Comment("server-sent cancellation, but there's a non-zero possibility that this cancellation"), + g.Comment("is received due to the worker stopping, prior to detecting the closing of the worker"), + g.Comment("stop channel. to give us an opportunity to detect a cancellation stemming from the"), + g.Comment("worker closing, we again check to see if the worker stop channel is closed before"), + g.Comment("propagating the cancellation"), + g.Case(g.Op("<-").Id("ctx").Dot("Done").Call()).Block( + g.Select().Block( + g.Case(g.Op("<-").Qual(activityPkg, "GetWorkerStopChannel").Call(g.Id("ctx"))).Block( + g.ReturnFunc(func(returnVals *g.Group) { + if hasOutput { + returnVals.Nil() + } + returnVals.Qual(temporalPkg, "NewApplicationError").Call(g.Lit("worker is stopping"), g.Lit("WorkerStopped")) + }), + ), + g.Default().BlockFunc(func(b *g.Group) { + b.Id("parentClosePolicy").Op(":=").Id("input").Dot("GetParentClosePolicy").Call() + b.If( + g.Id("parentClosePolicy").Op("==").Qual(temporalv1Pkg, "ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL").Op("||"). + Id("parentClosePolicy").Op("==").Qual(temporalv1Pkg, "ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON"), + ).BlockFunc(func(b *g.Group) { + // initialize cancellation context + b.List(g.Id("disconnectedCtx"), g.Id("cancel")).Op(":=").Qual("context", "WithTimeout").Call(g.Qual("context", "Background").Call(), g.Qual("time", "Second").Op("*").Lit(5)) + b.Defer().Id("cancel").Call() + + // cancel or terminate workflow depending on desired parent close policy + b.If(g.Id("parentClosePolicy").Op("==").Qual(temporalv1Pkg, "ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL")).Block( + g.Err().Op("=").Id("run").Dot("Cancel").Call(g.Id("disconnectedCtx")), + ).Else().Block( + g.Err().Op("=").Id("run").Dot("Terminate").Call(g.Id("disconnectedCtx"), g.Lit("xns activity cancellation received"), g.Lit("error"), g.Id("ctx").Dot("Err").Call()), + ) + b.If(g.Err().Op("!=").Nil()).Block( + g.ReturnFunc(func(returnVals *g.Group) { + if hasOutput { + returnVals.Nil() + } + returnVals.Id(svc.toLowerCamel("%sOptions", svc.GoName)).Dot("convertError").Call(g.Err()) + }), + ) + }) + b.ReturnFunc(func(returnVals *g.Group) { + if hasOutput { + returnVals.Nil() + } + returnVals.Id(svc.toLowerCamel("%sOptions", svc.GoName)).Dot("convertError").Call( + g.Qual(temporalPkg, "NewCanceledError").Call(g.Id("ctx").Dot("Err").Call().Dot("Error").Call()), + ) + }) + }), + ), + ).Line(), + + g.Comment("handle workflow completion"), g.Case(g.Op("<-").Id("doneCh")).Block( g.ReturnFunc(func(returnVals *g.Group) { if hasOutput { @@ -2077,8 +2116,7 @@ func (svc *Manifest) genXNSWorkflowFunctionAsync(f *g.File, workflow protoreflec g.Nil(), ), ), - ) - fn.Line() + ).Line() fn.Id("opt").Op(":=").Op("&").Id(svc.toCamel("%sWorkflowOptions", workflow)).Values() fn.If(g.Len(g.Id("opts")).Op(">").Lit(0).Op("&&").Id("opts").Index(g.Lit(0)).Op("!=").Nil()).Block( @@ -2093,9 +2131,41 @@ func (svc *Manifest) genXNSWorkflowFunctionAsync(f *g.File, workflow protoreflec fn.List(g.Id("wreq"), g.Err()).Op(":=").Qual(anypbPkg, "New").Call(g.Id("req")) fn.If(g.Err().Op("!=").Nil()).Block( g.Return(g.Nil(), g.Qual("fmt", "Errorf").Call(g.Lit("error marshalling workflow request: %w"), g.Err())), - ) - fn.Line() + ).Line() + } + + defaultParentClosePolicy := opts.GetParentClosePolicy() + if opts.GetXns().GetParentClosePolicy() != temporalv1.ParentClosePolicy_PARENT_CLOSE_POLICY_UNSPECIFIED { + defaultParentClosePolicy = opts.GetXns().GetParentClosePolicy() + } + if defaultParentClosePolicy != temporalv1.ParentClosePolicy_PARENT_CLOSE_POLICY_UNSPECIFIED { + var v string + switch defaultParentClosePolicy { + case temporalv1.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON: + v = "ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON" + case temporalv1.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL: + v = "ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL" + case temporalv1.ParentClosePolicy_PARENT_CLOSE_POLICY_TERMINATE: + v = "ParentClosePolicy_PARENT_CLOSE_POLICY_TERMINATE" + } + fn.Id("parentClosePolicy").Op(":=").Qual(temporalv1Pkg, v) + } else { + fn.Var().Id("parentClosePolicy").Qual(temporalv1Pkg, "ParentClosePolicy") } + fn.Switch(g.Id("opt").Dot("ParentClosePolicy")).Block( + g.Case(g.Qual(enumsPkg, "PARENT_CLOSE_POLICY_ABANDON")). + Block( + g.Id("parentClosePolicy").Op("=").Qual(temporalv1Pkg, "ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON"), + ), + g.Case(g.Qual(enumsPkg, "PARENT_CLOSE_POLICY_REQUEST_CANCEL")). + Block( + g.Id("parentClosePolicy").Op("=").Qual(temporalv1Pkg, "ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL"), + ), + g.Case(g.Qual(enumsPkg, "PARENT_CLOSE_POLICY_TERMINATE")). + Block( + g.Id("parentClosePolicy").Op("=").Qual(temporalv1Pkg, "ParentClosePolicy_PARENT_CLOSE_POLICY_TERMINATE"), + ), + ).Line() // return run with execute activity future fn.List(g.Id("ctx"), g.Id("cancel")).Op(":=").Qual(workflowPkg, "WithCancel").Call(g.Id("ctx")) @@ -2109,6 +2179,7 @@ func (svc *Manifest) genXNSWorkflowFunctionAsync(f *g.File, workflow protoreflec g.Op("&").Qual(xnsv1Pkg, "WorkflowRequest").CustomFunc(multiLineValues, func(fields *g.Group) { fields.Id("Detached").Op(":").Id("opt").Dot("Detached") fields.Id("HeartbeatInterval").Op(":").Qual(durationpbPkg, "New").Call(g.Id("opt").Dot("HeartbeatInterval")) + fields.Id("ParentClosePolicy").Op(":").Id("parentClosePolicy") if hasInput { fields.Id("Request").Op(":").Id("wreq") } @@ -2129,6 +2200,7 @@ func (svc *Manifest) genXNSWorkflowOptions(f *g.File, workflow protoreflect.Full g.Id("ActivityOptions").Op("*").Qual(workflowPkg, "ActivityOptions"), g.Id("Detached").Bool(), g.Id("HeartbeatInterval").Qual("time", "Duration"), + g.Id("ParentClosePolicy").Qual(enumsPkg, "ParentClosePolicy"), g.Id("StartWorkflowOptions").Op("*").Qual(clientPkg, "StartWorkflowOptions"), ) @@ -2188,6 +2260,21 @@ func (svc *Manifest) genXNSWorkflowOptions(f *g.File, workflow protoreflect.Full g.Return(g.Id("opts")), ) + f.Comment("WithParentClosePolicy can be used to customize the cancellation propagation behavior") + f.Func(). + Params( + g.Id("opts").Op("*").Id(typeName), + ). + Id("WithParentClosePolicy"). + Params( + g.Id("policy").Qual(enumsPkg, "ParentClosePolicy"), + ). + Op("*").Id(typeName). + Block( + g.Id("opts").Dot("ParentClosePolicy").Op("=").Id("policy"), + g.Return(g.Id("opts")), + ) + f.Comment("WithStartWorkflowOptions can be used to customize the start workflow options") f.Func(). Params( diff --git a/justfile b/justfile index d1c8404d..e6207c1e 100644 --- a/justfile +++ b/justfile @@ -67,6 +67,6 @@ temporal: test: #!/usr/bin/env bash set -euo pipefail - go test -count=1 ./internal/... - go test -count=1 ./pkg/... - go test -count=1 ./test/... + go test -count=1 -timeout 60s ./internal/... + go test -count=1 -timeout 60s ./pkg/... + go test -count=1 -timeout 60s ./test/... diff --git a/mocks/github.com/cludden/protoc-gen-go-temporal/gen/example/v1/mock_CreateFooRun.go b/mocks/github.com/cludden/protoc-gen-go-temporal/gen/example/v1/mock_CreateFooRun.go index fb6eee12..57f4cd76 100644 --- a/mocks/github.com/cludden/protoc-gen-go-temporal/gen/example/v1/mock_CreateFooRun.go +++ b/mocks/github.com/cludden/protoc-gen-go-temporal/gen/example/v1/mock_CreateFooRun.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.1. DO NOT EDIT. +// Code generated by mockery v2.43.0. DO NOT EDIT. package examplev1 diff --git a/mocks/github.com/cludden/protoc-gen-go-temporal/gen/example/v1/mock_ExampleClient.go b/mocks/github.com/cludden/protoc-gen-go-temporal/gen/example/v1/mock_ExampleClient.go index ca0d0f5a..97468527 100644 --- a/mocks/github.com/cludden/protoc-gen-go-temporal/gen/example/v1/mock_ExampleClient.go +++ b/mocks/github.com/cludden/protoc-gen-go-temporal/gen/example/v1/mock_ExampleClient.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.1. DO NOT EDIT. +// Code generated by mockery v2.43.0. DO NOT EDIT. package examplev1 diff --git a/mocks/github.com/cludden/protoc-gen-go-temporal/gen/example/v1/mock_UpdateFooProgressHandle.go b/mocks/github.com/cludden/protoc-gen-go-temporal/gen/example/v1/mock_UpdateFooProgressHandle.go index edbf1e2e..0be8c44f 100644 --- a/mocks/github.com/cludden/protoc-gen-go-temporal/gen/example/v1/mock_UpdateFooProgressHandle.go +++ b/mocks/github.com/cludden/protoc-gen-go-temporal/gen/example/v1/mock_UpdateFooProgressHandle.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.1. DO NOT EDIT. +// Code generated by mockery v2.43.0. DO NOT EDIT. package examplev1 diff --git a/mocks/github.com/cludden/protoc-gen-go-temporal/gen/test/simple/v1/mock_SimpleWorkflowFunctions.go b/mocks/github.com/cludden/protoc-gen-go-temporal/gen/test/simple/v1/mock_SimpleWorkflowFunctions.go index e11f5410..1af34411 100644 --- a/mocks/github.com/cludden/protoc-gen-go-temporal/gen/test/simple/v1/mock_SimpleWorkflowFunctions.go +++ b/mocks/github.com/cludden/protoc-gen-go-temporal/gen/test/simple/v1/mock_SimpleWorkflowFunctions.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.1. DO NOT EDIT. +// Code generated by mockery v2.43.0. DO NOT EDIT. package v1 diff --git a/mocks/github.com/cludden/protoc-gen-go-temporal/gen/test/xnserr/v1/mock_ServerClient.go b/mocks/github.com/cludden/protoc-gen-go-temporal/gen/test/xnserr/v1/mock_ServerClient.go index bbbdfc77..ea2e12e8 100644 --- a/mocks/github.com/cludden/protoc-gen-go-temporal/gen/test/xnserr/v1/mock_ServerClient.go +++ b/mocks/github.com/cludden/protoc-gen-go-temporal/gen/test/xnserr/v1/mock_ServerClient.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.1. DO NOT EDIT. +// Code generated by mockery v2.43.0. DO NOT EDIT. package xnserrv1mocks diff --git a/mocks/github.com/cludden/protoc-gen-go-temporal/gen/test/xnserr/v1/mock_SleepRun.go b/mocks/github.com/cludden/protoc-gen-go-temporal/gen/test/xnserr/v1/mock_SleepRun.go index 95f57ba0..6e167b4b 100644 --- a/mocks/github.com/cludden/protoc-gen-go-temporal/gen/test/xnserr/v1/mock_SleepRun.go +++ b/mocks/github.com/cludden/protoc-gen-go-temporal/gen/test/xnserr/v1/mock_SleepRun.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.1. DO NOT EDIT. +// Code generated by mockery v2.43.0. DO NOT EDIT. package xnserrv1mocks diff --git a/mocks/go.temporal.io/sdk/client/mock_Client.go b/mocks/go.temporal.io/sdk/client/mock_Client.go index 758d3a40..dcd05996 100644 --- a/mocks/go.temporal.io/sdk/client/mock_Client.go +++ b/mocks/go.temporal.io/sdk/client/mock_Client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.1. DO NOT EDIT. +// Code generated by mockery v2.43.0. DO NOT EDIT. package client diff --git a/mocks/go.temporal.io/sdk/clientutils/mock_WorkflowRun.go b/mocks/go.temporal.io/sdk/clientutils/mock_WorkflowRun.go index 264df18c..23a7ece9 100644 --- a/mocks/go.temporal.io/sdk/clientutils/mock_WorkflowRun.go +++ b/mocks/go.temporal.io/sdk/clientutils/mock_WorkflowRun.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.1. DO NOT EDIT. +// Code generated by mockery v2.43.0. DO NOT EDIT. package clientutils diff --git a/proto/README.md b/proto/README.md index 1a0b599e..97dab7ad 100644 --- a/proto/README.md +++ b/proto/README.md @@ -4280,6 +4280,7 @@ go_name: Sleep
Name | Value |
---|---|
id_reuse_policy |
|
parent_close_policy |
|
xns.heartbeat_interval | 10 seconds |
xns.heartbeat_timeout | 30 seconds |