// Code generated by protoc-gen-go_temporal. DO NOT EDIT.
// versions:
//
//	protoc-gen-go_temporal dev (latest)
//	protoc (unknown)
//
// source: example/xns/v1/xns.proto
package xnsv1xns

import (
	"context"
	"errors"
	"fmt"
	v1 "github.com/cludden/protoc-gen-go-temporal/gen/example/xns/v1"
	temporalv1 "github.com/cludden/protoc-gen-go-temporal/gen/temporal/v1"
	xnsv1 "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"
	enumsv1 "go.temporal.io/api/enums/v1"
	activity "go.temporal.io/sdk/activity"
	client "go.temporal.io/sdk/client"
	temporal "go.temporal.io/sdk/temporal"
	worker "go.temporal.io/sdk/worker"
	workflow "go.temporal.io/sdk/workflow"
	anypb "google.golang.org/protobuf/types/known/anypb"
	durationpb "google.golang.org/protobuf/types/known/durationpb"
	"time"
)

// XnsOptions is used to configure example.xns.v1.Xns xns activity registration
type XnsOptions struct {
	// errorConverter is used to customize error
	errorConverter func(error) error
	// filter is used to filter xns activity registrations. It receives as
	// input the original activity name, and should return one of the following:
	// 1. the original activity name, for no changes
	// 2. a modified activity name, to override the original activity name
	// 3. an empty string, to skip registration
	filter func(string) string
}

// NewXnsOptions initializes a new XnsOptions value
func NewXnsOptions() *XnsOptions {
	return &XnsOptions{}
}

// WithErrorConverter overrides the default error converter applied to xns activity errors
func (opts *XnsOptions) WithErrorConverter(errorConverter func(error) error) *XnsOptions {
	opts.errorConverter = errorConverter
	return opts
}

// Filter is used to filter registered xns activities or customize their name
func (opts *XnsOptions) WithFilter(filter func(string) string) *XnsOptions {
	opts.filter = filter
	return opts
}

// convertError is applied to all xns activity errors
func (opts *XnsOptions) convertError(err error) error {
	if err == nil {
		return nil
	}
	if opts != nil && opts.errorConverter != nil {
		return opts.errorConverter(err)
	}
	return xns.ErrorToApplicationError(err)
}

// filterActivity is used to filter xns activity registrations
func (opts *XnsOptions) filterActivity(name string) string {
	if opts == nil || opts.filter == nil {
		return name
	}
	return opts.filter(name)
}

// xnsOptions is a reference to the XnsOptions initialized at registration
var xnsOptions *XnsOptions

// RegisterXnsActivities registers example.xns.v1.Xns cross-namespace activities
func RegisterXnsActivities(r worker.ActivityRegistry, c v1.XnsClient, options ...*XnsOptions) {
	if xnsOptions == nil && len(options) > 0 && options[0] != nil {
		xnsOptions = options[0]
	}
	a := &xnsActivities{c}
	if name := xnsOptions.filterActivity("example.xns.v1.Xns.CancelWorkflow"); name != "" {
		r.RegisterActivityWithOptions(a.CancelWorkflow, activity.RegisterOptions{Name: name})
	}
	if name := xnsOptions.filterActivity(v1.ProvisionFooWorkflowName); name != "" {
		r.RegisterActivityWithOptions(a.ProvisionFoo, activity.RegisterOptions{Name: name})
	}
	if name := xnsOptions.filterActivity("example.xns.v1.Xns.GetProvisionFoo"); name != "" {
		r.RegisterActivityWithOptions(a.GetProvisionFoo, activity.RegisterOptions{Name: name})
	}
}

// ProvisionFooWorkflowOptions are used to configure a(n) example.xns.v1.Xns.ProvisionFoo workflow execution
type ProvisionFooWorkflowOptions struct {
	ActivityOptions      *workflow.ActivityOptions
	Detached             bool
	HeartbeatInterval    time.Duration
	HeartbeatTimeout     time.Duration
	ParentClosePolicy    enumsv1.ParentClosePolicy
	StartWorkflowOptions *client.StartWorkflowOptions
}

// NewProvisionFooWorkflowOptions initializes a new ProvisionFooWorkflowOptions value
func NewProvisionFooWorkflowOptions() *ProvisionFooWorkflowOptions {
	return &ProvisionFooWorkflowOptions{}
}

// Build initializes the activity context and input
func (opts *ProvisionFooWorkflowOptions) Build(ctx workflow.Context, input *v1.ProvisionFooRequest) (workflow.Context, *xnsv1.WorkflowRequest, error) {
	// initialize start workflow options
	swo := client.StartWorkflowOptions{}
	if opts.StartWorkflowOptions != nil {
		swo = *opts.StartWorkflowOptions
	}

	// initialize workflow id if not set
	if swo.ID == "" {
		if err := workflow.SideEffect(ctx, func(ctx workflow.Context) any {
			id, err := expression.EvalExpression(v1.ProvisionFooIdexpression, input.ProtoReflect())
			if err != nil {
				workflow.GetLogger(ctx).Error("error evaluating id expression for \"example.xns.v1.Xns.ProvisionFoo\" workflow", "error", err)
				return nil
			}
			return id
		}).Get(&swo.ID); err != nil {
			return nil, nil, err
		}
	}
	if swo.ID == "" {
		if err := workflow.SideEffect(ctx, func(ctx workflow.Context) any {
			id, err := uuid.NewRandom()
			if err != nil {
				workflow.GetLogger(ctx).Error("error generating workflow id", "error", err)
				return nil
			}
			return id
		}).Get(&swo.ID); err != nil {
			return nil, nil, err
		}
	}
	if swo.ID == "" {
		return nil, nil, temporal.NewNonRetryableApplicationError("workflow id is required", "InvalidArgument", nil)
	}

	// marshal workflow request protobuf message
	inputpb, err := anypb.New(input)
	if err != nil {
		return ctx, nil, fmt.Errorf("error marshalling workflow request: %w", err)
	}

	// marshal start workflow options protobuf message
	swopb, err := xns.MarshalStartWorkflowOptions(swo)
	if err != nil {
		return ctx, nil, fmt.Errorf("error marshalling start workflow options: %w", err)
	}

	// marshal parent close policy protobuf message
	var parentClosePolicy temporalv1.ParentClosePolicy
	switch opts.ParentClosePolicy {
	case enumsv1.PARENT_CLOSE_POLICY_ABANDON:
		parentClosePolicy = temporalv1.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON
	case enumsv1.PARENT_CLOSE_POLICY_REQUEST_CANCEL:
		parentClosePolicy = temporalv1.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL
	case enumsv1.PARENT_CLOSE_POLICY_TERMINATE:
		parentClosePolicy = temporalv1.ParentClosePolicy_PARENT_CLOSE_POLICY_TERMINATE
	}

	// initialize xns activity options
	ao := workflow.ActivityOptions{}
	if opts.ActivityOptions != nil {
		ao = *opts.ActivityOptions
	}

	if ao.HeartbeatTimeout == 0 {
		ao.HeartbeatTimeout = time.Second * 60
	}

	if ao.StartToCloseTimeout == 0 && ao.ScheduleToCloseTimeout == 0 {
		ao.ScheduleToCloseTimeout = time.Hour * 24
	}

	// WaitForCancellation must be set otherwise the underlying workflow is not guaranteed to be canceled
	ao.WaitForCancellation = true

	// configure heartbeat interval
	if opts.HeartbeatInterval == 0 {
		opts.HeartbeatInterval = ao.HeartbeatTimeout / 2
	}

	ctx = workflow.WithActivityOptions(ctx, ao)

	return ctx, &xnsv1.WorkflowRequest{
		Detached:             opts.Detached,
		HeartbeatInterval:    durationpb.New(opts.HeartbeatInterval),
		ParentClosePolicy:    parentClosePolicy,
		Request:              inputpb,
		StartWorkflowOptions: swopb,
	}, nil
}

// WithActivityOptions can be used to customize the activity options
func (opts *ProvisionFooWorkflowOptions) WithActivityOptions(ao workflow.ActivityOptions) *ProvisionFooWorkflowOptions {
	opts.ActivityOptions = &ao
	return opts
}

// WithDetached can be used to start a workflow execution and exit immediately
func (opts *ProvisionFooWorkflowOptions) WithDetached(d bool) *ProvisionFooWorkflowOptions {
	opts.Detached = d
	return opts
}

// WithHeartbeatInterval can be used to customize the activity heartbeat interval
func (opts *ProvisionFooWorkflowOptions) WithHeartbeatInterval(d time.Duration) *ProvisionFooWorkflowOptions {
	opts.HeartbeatInterval = d
	return opts
}

// WithHeartbeatTimeout can be used to customize the activity heartbeat timeout
func (opts *ProvisionFooWorkflowOptions) WithHeartbeatTimeout(d time.Duration) *ProvisionFooWorkflowOptions {
	opts.HeartbeatTimeout = d
	return opts
}

// WithParentClosePolicy can be used to customize the cancellation propagation behavior
func (opts *ProvisionFooWorkflowOptions) WithParentClosePolicy(policy enumsv1.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
	return opts
}

// ProvisionFooRun provides a handle to a example.xns.v1.Xns.ProvisionFoo workflow execution
type ProvisionFooRun interface {
	// Cancel cancels the workflow
	Cancel(workflow.Context) error

	// Future returns the inner workflow.Future
	Future() workflow.Future

	// Get returns the inner workflow.Future
	Get(workflow.Context) (*v1.ProvisionFooResponse, error)

	// ID returns the workflow id
	ID() string
}

// provisionFooRun provides a(n) ProvisionFooRun implementation
type provisionFooRun struct {
	cancel            func()
	ctx               workflow.Context
	future            workflow.Future
	id                string
	heartbeatInterval time.Duration
	parentClosePolicy enumsv1.ParentClosePolicy
}

// Cancel the underlying workflow execution
func (r *provisionFooRun) Cancel(ctx workflow.Context) error {
	if r.cancel != nil {
		r.cancel()
		if _, err := r.Get(ctx); err != nil && !errors.Is(err, workflow.ErrCanceled) {
			return err
		}
		return nil
	}
	return CancelXnsWorkflow(ctx, r.id, "")
}

// Future returns the underlying activity future
func (r *provisionFooRun) Future() workflow.Future {
	if r.future == nil {
		rr := GetProvisionFooAsync(r.ctx, r.id, "").(*provisionFooRun)
		r.future = rr.future
		r.cancel = rr.cancel
	}
	return r.future
}

// Get blocks on activity completion and returns the underlying workflow result
func (r *provisionFooRun) Get(ctx workflow.Context) (*v1.ProvisionFooResponse, error) {
	ctx, cancel := workflow.WithCancel(ctx)
	if r.future == nil {
		rr := GetProvisionFooAsync(ctx, r.id, "", NewGetProvisionFooOptions().WithParentClosePolicy(r.parentClosePolicy).WithHeartbeatInterval(r.heartbeatInterval)).(*provisionFooRun)
		r.future = rr.future
		r.cancel = cancel
	}
	var resp v1.ProvisionFooResponse
	if err := r.future.Get(ctx, &resp); err != nil {
		return nil, err
	}
	return &resp, nil
}

// ID returns the underlying workflow id
func (r *provisionFooRun) ID() string {
	return r.id
}

// ProvisionFoo executes a(n) example.xns.v1.Xns.ProvisionFoo workflow and blocks until error or response is received
func ProvisionFoo(ctx workflow.Context, req *v1.ProvisionFooRequest, opts ...*ProvisionFooWorkflowOptions) (*v1.ProvisionFooResponse, error) {
	run, err := ProvisionFooAsync(ctx, req, opts...)
	if err != nil {
		return nil, err
	}
	return run.Get(ctx)
}

// ProvisionFooAsync executes a(n) example.xns.v1.Xns.ProvisionFoo workflow and returns a handle to the underlying activity
func ProvisionFooAsync(ctx workflow.Context, input *v1.ProvisionFooRequest, opts ...*ProvisionFooWorkflowOptions) (ProvisionFooRun, error) {
	activityName := xnsOptions.filterActivity(v1.ProvisionFooWorkflowName)
	if activityName == "" {
		return nil, temporal.NewNonRetryableApplicationError(
			fmt.Sprintf("no activity registered for %s", v1.ProvisionFooWorkflowName),
			"Unimplemented",
			nil,
		)
	}

	var opt *ProvisionFooWorkflowOptions
	if len(opts) > 0 && opts[0] != nil {
		opt = opts[0]
	} else {
		opt = NewProvisionFooWorkflowOptions()
	}
	ctx, req, err := opt.Build(ctx, input)
	if err != nil {
		return nil, xnsOptions.convertError(err)
	}
	ctx, cancel := workflow.WithCancel(ctx)
	return &provisionFooRun{
		cancel: cancel,
		future: workflow.ExecuteActivity(ctx, activityName, req),
		id:     req.GetStartWorkflowOptions().GetId(),
	}, nil
}

// GetProvisionFoo returns a(n) example.xns.v1.Xns.ProvisionFoo workflow execution
func GetProvisionFoo(ctx workflow.Context, workflowID string, runID string, options ...*GetProvisionFooOptions) (out *v1.ProvisionFooResponse, err error) {
	out, err = GetProvisionFooAsync(ctx, workflowID, runID, options...).Get(ctx)
	if err != nil {
		return nil, err
	}
	return out, nil
}

// GetProvisionFooAsync returns a handle to a(n) example.xns.v1.Xns.ProvisionFoo workflow execution
func GetProvisionFooAsync(ctx workflow.Context, workflowID string, runID string, options ...*GetProvisionFooOptions) ProvisionFooRun {
	activityName := xnsOptions.filterActivity("example.xns.v1.Xns.GetProvisionFoo")
	if activityName == "" {
		f, set := workflow.NewFuture(ctx)
		set.SetError(temporal.NewNonRetryableApplicationError(fmt.Sprintf("no activity registered for %s", activityName), "Unimplemented", nil))
		return &provisionFooRun{
			future: f,
			id:     workflowID,
		}
	}
	var opt *GetProvisionFooOptions
	if len(options) > 0 && options[0] != nil {
		opt = options[0]
	} else {
		opt = NewGetProvisionFooOptions()
	}
	ctx, req, err := opt.Build(ctx, workflowID, runID)
	if err != nil {
		f, set := workflow.NewFuture(ctx)
		set.SetError(xnsOptions.convertError(temporal.NewNonRetryableApplicationError(fmt.Sprintf("no activity registered for %s", activityName), "Unimplemented", nil)))
		return &provisionFooRun{
			future: f,
			id:     workflowID,
		}
	}
	ctx, cancel := workflow.WithCancel(ctx)
	return &provisionFooRun{
		cancel: cancel,
		future: workflow.ExecuteActivity(ctx, activityName, req),
		id:     workflowID,
	}
}

// GetProvisionFooOptions are used to configure a(n) example.xns.v1.Xns.ProvisionFoo workflow execution getter activity
type GetProvisionFooOptions struct {
	activityOptions   *workflow.ActivityOptions
	heartbeatInterval time.Duration
	parentClosePolicy enumsv1.ParentClosePolicy
}

// NewGetProvisionFooOptions initializes a new GetProvisionFooOptions value
func NewGetProvisionFooOptions() *GetProvisionFooOptions {
	return &GetProvisionFooOptions{}
}

// Build initializes the activity context and input
func (opt *GetProvisionFooOptions) Build(ctx workflow.Context, workflowID string, runID string) (workflow.Context, *xnsv1.GetWorkflowRequest, error) {
	if opt.heartbeatInterval == 0 {
		opt.heartbeatInterval = 30000000000 // 30 seconds
	}

	// configure activity options
	var ao workflow.ActivityOptions
	if opt.activityOptions != nil {
		ao = *opt.activityOptions
	} else {
		ao = workflow.ActivityOptions{}
	}
	if ao.HeartbeatTimeout == 0 {
		ao.HeartbeatTimeout = 60000000000 // 1 minute
	}
	// WaitForCancellation must be set otherwise the underlying workflow is not guaranteed to be canceled
	ao.WaitForCancellation = true

	if ao.StartToCloseTimeout == 0 && ao.ScheduleToCloseTimeout == 0 {
		ao.ScheduleToCloseTimeout = 86400000000000 // 1 day
	}
	ctx = workflow.WithActivityOptions(ctx, ao)

	return ctx, &xnsv1.GetWorkflowRequest{
		HeartbeatInterval: durationpb.New(opt.heartbeatInterval),
		ParentClosePolicy: opt.parentClosePolicy,
		RunId:             runID,
		WorkflowId:        workflowID,
	}, nil
}

// WithActivityOptions can be used to customize the activity options
func (o *GetProvisionFooOptions) WithActivityOptions(ao workflow.ActivityOptions) *GetProvisionFooOptions {
	o.activityOptions = &ao
	return o
}

// WithHeartbeatInterval can be used to customize the activity heartbeat interval
func (o *GetProvisionFooOptions) WithHeartbeatInterval(d time.Duration) *GetProvisionFooOptions {
	o.heartbeatInterval = d
	return o
}

// WithParentClosePolicy can be used to customize the cancellation propagation behavior
func (o *GetProvisionFooOptions) WithParentClosePolicy(policy enumsv1.ParentClosePolicy) *GetProvisionFooOptions {
	o.parentClosePolicy = policy
	return o
}

// CancelXnsWorkflow cancels an existing workflow
func CancelXnsWorkflow(ctx workflow.Context, workflowID string, runID string) error {
	return CancelXnsWorkflowAsync(ctx, workflowID, runID).Get(ctx, nil)
}

// CancelXnsWorkflowAsync cancels an existing workflow
func CancelXnsWorkflowAsync(ctx workflow.Context, workflowID string, runID string) workflow.Future {
	activityName := xnsOptions.filterActivity("example.xns.v1.Xns.CancelWorkflow")
	if activityName == "" {
		f, s := workflow.NewFuture(ctx)
		s.SetError(temporal.NewNonRetryableApplicationError(
			"no activity registered for example.xns.v1.Xns.CancelWorkflow",
			"Unimplemented",
			nil,
		))
		return f
	}
	ao := workflow.GetActivityOptions(ctx)
	if ao.StartToCloseTimeout == 0 && ao.ScheduleToCloseTimeout == 0 {
		ao.StartToCloseTimeout = time.Minute
	}
	ctx = workflow.WithActivityOptions(ctx, ao)
	return workflow.ExecuteActivity(ctx, activityName, workflowID, runID)
}

// xnsActivities provides activities that can be used to interact with a(n) Xns service's workflow, queries, signals, and updates across namespaces
type xnsActivities struct {
	client v1.XnsClient
}

// CancelWorkflow cancels an existing workflow execution
func (a *xnsActivities) CancelWorkflow(ctx context.Context, workflowID string, runID string) error {
	return a.client.CancelWorkflow(ctx, workflowID, runID)
}

// GetProvisionFoo retrieves a(n) example.xns.v1.Xns.ProvisionFoo workflow via an activity
func (a *xnsActivities) GetProvisionFoo(ctx context.Context, input *xnsv1.GetWorkflowRequest) (out *v1.ProvisionFooResponse, err error) {
	heartbeatInterval := input.GetHeartbeatInterval().AsDuration()
	if heartbeatInterval == 0 {
		heartbeatInterval = time.Second * 30
	}

	actx, cancel := context.WithCancel(context.Background())
	defer cancel()
	run := a.client.GetProvisionFoo(actx, input.GetWorkflowId(), input.GetRunId())
	done := make(chan struct{})
	go func() {
		defer close(done)
		out, err = run.Get(actx)
	}()

	for {
		select {
		// send heartbeats periodically
		case <-time.After(heartbeatInterval):
			activity.RecordHeartbeat(ctx)

		// return retryable error if the worker is stopping
		case <-activity.GetWorkerStopChannel(ctx):
			return nil, xnsOptions.convertError(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():
			select {
			case <-activity.GetWorkerStopChannel(ctx):
				activity.GetLogger(ctx).Info("worker is stopping")
				return nil, xnsOptions.convertError(temporal.NewApplicationError("worker is stopping", "WorkerStopped"))
			default:
				parentClosePolicy := input.GetParentClosePolicy()
				if parentClosePolicy == enumsv1.PARENT_CLOSE_POLICY_REQUEST_CANCEL || parentClosePolicy == enumsv1.PARENT_CLOSE_POLICY_TERMINATE {
					disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Minute)
					defer cancel()
					if parentClosePolicy == enumsv1.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()))
			}

		// handle workflow completion
		case <-done:
			return out, xnsOptions.convertError(err)
		}
	}
}

// ProvisionFoo executes a(n) example.xns.v1.Xns.ProvisionFoo workflow via an activity
func (a *xnsActivities) ProvisionFoo(ctx context.Context, input *xnsv1.WorkflowRequest) (resp *v1.ProvisionFooResponse, err error) {
	// unmarshal workflow request
	var req v1.ProvisionFooRequest
	if err := input.Request.UnmarshalTo(&req); err != nil {
		return nil, xnsOptions.convertError(temporal.NewNonRetryableApplicationError(
			fmt.Sprintf("error unmarshalling workflow request of type %s as github.com/cludden/protoc-gen-go-temporal/gen/example/xns/v1.ProvisionFooRequest", input.Request.GetTypeUrl()),
			"InvalidArgument",
			err,
		))
	}

	// initialize workflow execution
	actx := ctx
	if !input.GetDetached() {
		var cancel context.CancelFunc
		actx, cancel = context.WithCancel(context.Background())
		defer cancel()
	}
	var run v1.ProvisionFooRun
	run, err = a.client.ProvisionFooAsync(actx, &req, v1.NewProvisionFooOptions().WithStartWorkflowOptions(
		xns.UnmarshalStartWorkflowOptions(input.GetStartWorkflowOptions()),
	))
	if err != nil {
		return nil, xnsOptions.convertError(err)
	}

	// exit early if detached enabled
	if input.GetDetached() {
		return nil, nil
	}

	// otherwise, wait for execution to complete in child goroutine
	doneCh := make(chan struct{})
	go func() {
		resp, err = run.Get(actx)
		close(doneCh)
	}()

	heartbeatInterval := input.GetHeartbeatInterval().AsDuration()
	if heartbeatInterval == 0 {
		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():
			select {
			case <-activity.GetWorkerStopChannel(ctx):
				return nil, temporal.NewApplicationError("worker is stopping", "WorkerStopped")
			default:
				parentClosePolicy := input.GetParentClosePolicy()
				if parentClosePolicy == temporalv1.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL || parentClosePolicy == temporalv1.ParentClosePolicy_PARENT_CLOSE_POLICY_TERMINATE {
					disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Minute)
					defer cancel()
					if parentClosePolicy == temporalv1.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()))
			}

		// handle workflow completion
		case <-doneCh:
			return resp, xnsOptions.convertError(err)
		}
	}
}

// ExampleOptions is used to configure example.xns.v1.Example xns activity registration
type ExampleOptions struct {
	// errorConverter is used to customize error
	errorConverter func(error) error
	// filter is used to filter xns activity registrations. It receives as
	// input the original activity name, and should return one of the following:
	// 1. the original activity name, for no changes
	// 2. a modified activity name, to override the original activity name
	// 3. an empty string, to skip registration
	filter func(string) string
}

// NewExampleOptions initializes a new ExampleOptions value
func NewExampleOptions() *ExampleOptions {
	return &ExampleOptions{}
}

// WithErrorConverter overrides the default error converter applied to xns activity errors
func (opts *ExampleOptions) WithErrorConverter(errorConverter func(error) error) *ExampleOptions {
	opts.errorConverter = errorConverter
	return opts
}

// Filter is used to filter registered xns activities or customize their name
func (opts *ExampleOptions) WithFilter(filter func(string) string) *ExampleOptions {
	opts.filter = filter
	return opts
}

// convertError is applied to all xns activity errors
func (opts *ExampleOptions) convertError(err error) error {
	if err == nil {
		return nil
	}
	if opts != nil && opts.errorConverter != nil {
		return opts.errorConverter(err)
	}
	return xns.ErrorToApplicationError(err)
}

// filterActivity is used to filter xns activity registrations
func (opts *ExampleOptions) filterActivity(name string) string {
	if opts == nil || opts.filter == nil {
		return name
	}
	return opts.filter(name)
}

// exampleOptions is a reference to the ExampleOptions initialized at registration
var exampleOptions *ExampleOptions

// RegisterExampleActivities registers example.xns.v1.Example cross-namespace activities
func RegisterExampleActivities(r worker.ActivityRegistry, c v1.ExampleClient, options ...*ExampleOptions) {
	if exampleOptions == nil && len(options) > 0 && options[0] != nil {
		exampleOptions = options[0]
	}
	a := &exampleActivities{c}
	if name := exampleOptions.filterActivity("example.xns.v1.Example.CancelWorkflow"); name != "" {
		r.RegisterActivityWithOptions(a.CancelWorkflow, activity.RegisterOptions{Name: name})
	}
	if name := exampleOptions.filterActivity(v1.CreateFooWorkflowName); name != "" {
		r.RegisterActivityWithOptions(a.CreateFoo, activity.RegisterOptions{Name: name})
	}
	if name := exampleOptions.filterActivity("example.xns.v1.Example.GetCreateFoo"); name != "" {
		r.RegisterActivityWithOptions(a.GetCreateFoo, activity.RegisterOptions{Name: name})
	}
	if name := exampleOptions.filterActivity("example.xns.v1.Example.CreateFooWithSetFooProgress"); name != "" {
		r.RegisterActivityWithOptions(a.CreateFooWithSetFooProgress, activity.RegisterOptions{Name: name})
	}
	if name := exampleOptions.filterActivity(v1.GetFooProgressQueryName); name != "" {
		r.RegisterActivityWithOptions(a.GetFooProgress, activity.RegisterOptions{Name: name})
	}
	if name := exampleOptions.filterActivity(v1.SetFooProgressSignalName); name != "" {
		r.RegisterActivityWithOptions(a.SetFooProgress, activity.RegisterOptions{Name: name})
	}
	if name := exampleOptions.filterActivity(v1.UpdateFooProgressUpdateName); name != "" {
		r.RegisterActivityWithOptions(a.UpdateFooProgress, activity.RegisterOptions{Name: name})
	}
}

// CreateFooWorkflowOptions are used to configure a(n) example.xns.v1.Example.CreateFoo workflow execution
type CreateFooWorkflowOptions struct {
	ActivityOptions      *workflow.ActivityOptions
	Detached             bool
	HeartbeatInterval    time.Duration
	HeartbeatTimeout     time.Duration
	ParentClosePolicy    enumsv1.ParentClosePolicy
	StartWorkflowOptions *client.StartWorkflowOptions
}

// NewCreateFooWorkflowOptions initializes a new CreateFooWorkflowOptions value
func NewCreateFooWorkflowOptions() *CreateFooWorkflowOptions {
	return &CreateFooWorkflowOptions{}
}

// Build initializes the activity context and input
func (opts *CreateFooWorkflowOptions) Build(ctx workflow.Context, input *v1.CreateFooRequest) (workflow.Context, *xnsv1.WorkflowRequest, error) {
	// initialize start workflow options
	swo := client.StartWorkflowOptions{}
	if opts.StartWorkflowOptions != nil {
		swo = *opts.StartWorkflowOptions
	}

	// initialize workflow id if not set
	if swo.ID == "" {
		if err := workflow.SideEffect(ctx, func(ctx workflow.Context) any {
			id, err := expression.EvalExpression(v1.CreateFooIdexpression, input.ProtoReflect())
			if err != nil {
				workflow.GetLogger(ctx).Error("error evaluating id expression for \"example.xns.v1.Example.CreateFoo\" workflow", "error", err)
				return nil
			}
			return id
		}).Get(&swo.ID); err != nil {
			return nil, nil, err
		}
	}
	if swo.ID == "" {
		if err := workflow.SideEffect(ctx, func(ctx workflow.Context) any {
			id, err := uuid.NewRandom()
			if err != nil {
				workflow.GetLogger(ctx).Error("error generating workflow id", "error", err)
				return nil
			}
			return id
		}).Get(&swo.ID); err != nil {
			return nil, nil, err
		}
	}
	if swo.ID == "" {
		return nil, nil, temporal.NewNonRetryableApplicationError("workflow id is required", "InvalidArgument", nil)
	}

	// marshal workflow request protobuf message
	inputpb, err := anypb.New(input)
	if err != nil {
		return ctx, nil, fmt.Errorf("error marshalling workflow request: %w", err)
	}

	// marshal start workflow options protobuf message
	swopb, err := xns.MarshalStartWorkflowOptions(swo)
	if err != nil {
		return ctx, nil, fmt.Errorf("error marshalling start workflow options: %w", err)
	}

	// marshal parent close policy protobuf message
	var parentClosePolicy temporalv1.ParentClosePolicy
	switch opts.ParentClosePolicy {
	case enumsv1.PARENT_CLOSE_POLICY_ABANDON:
		parentClosePolicy = temporalv1.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON
	case enumsv1.PARENT_CLOSE_POLICY_REQUEST_CANCEL:
		parentClosePolicy = temporalv1.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL
	case enumsv1.PARENT_CLOSE_POLICY_TERMINATE:
		parentClosePolicy = temporalv1.ParentClosePolicy_PARENT_CLOSE_POLICY_TERMINATE
	}

	// initialize xns activity options
	ao := workflow.ActivityOptions{}
	if opts.ActivityOptions != nil {
		ao = *opts.ActivityOptions
	}

	if ao.HeartbeatTimeout == 0 {
		ao.HeartbeatTimeout = 20000000000 // 20 seconds
	}

	if ao.StartToCloseTimeout == 0 {
		ao.StartToCloseTimeout = 3630000000000 // 1 hour 30 seconds
	}

	// WaitForCancellation must be set otherwise the underlying workflow is not guaranteed to be canceled
	ao.WaitForCancellation = true

	// configure heartbeat interval
	if opts.HeartbeatInterval == 0 {
		opts.HeartbeatInterval = 10000000000 // 10 seconds
	}

	ctx = workflow.WithActivityOptions(ctx, ao)

	return ctx, &xnsv1.WorkflowRequest{
		Detached:             opts.Detached,
		HeartbeatInterval:    durationpb.New(opts.HeartbeatInterval),
		ParentClosePolicy:    parentClosePolicy,
		Request:              inputpb,
		StartWorkflowOptions: swopb,
	}, nil
}

// WithActivityOptions can be used to customize the activity options
func (opts *CreateFooWorkflowOptions) WithActivityOptions(ao workflow.ActivityOptions) *CreateFooWorkflowOptions {
	opts.ActivityOptions = &ao
	return opts
}

// WithDetached can be used to start a workflow execution and exit immediately
func (opts *CreateFooWorkflowOptions) WithDetached(d bool) *CreateFooWorkflowOptions {
	opts.Detached = d
	return opts
}

// WithHeartbeatInterval can be used to customize the activity heartbeat interval
func (opts *CreateFooWorkflowOptions) WithHeartbeatInterval(d time.Duration) *CreateFooWorkflowOptions {
	opts.HeartbeatInterval = d
	return opts
}

// WithHeartbeatTimeout can be used to customize the activity heartbeat timeout
func (opts *CreateFooWorkflowOptions) WithHeartbeatTimeout(d time.Duration) *CreateFooWorkflowOptions {
	opts.HeartbeatTimeout = d
	return opts
}

// WithParentClosePolicy can be used to customize the cancellation propagation behavior
func (opts *CreateFooWorkflowOptions) WithParentClosePolicy(policy enumsv1.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
	return opts
}

// CreateFooRun provides a handle to a example.xns.v1.Example.CreateFoo workflow execution
type CreateFooRun interface {
	// Cancel cancels the workflow
	Cancel(workflow.Context) error

	// Future returns the inner workflow.Future
	Future() workflow.Future

	// Get returns the inner workflow.Future
	Get(workflow.Context) (*v1.CreateFooResponse, error)

	// ID returns the workflow id
	ID() string

	// GetFooProgress returns the status of a CreateFoo operation
	GetFooProgress(workflow.Context, ...*GetFooProgressQueryOptions) (*v1.GetFooProgressResponse, error)

	// GetFooProgress returns the status of a CreateFoo operation
	GetFooProgressAsync(workflow.Context, ...*GetFooProgressQueryOptions) (GetFooProgressQueryHandle, error)

	// SetFooProgress sets the current status of a CreateFoo operation
	SetFooProgress(workflow.Context, *v1.SetFooProgressRequest, ...*SetFooProgressSignalOptions) error

	// SetFooProgress sets the current status of a CreateFoo operation
	SetFooProgressAsync(workflow.Context, *v1.SetFooProgressRequest, ...*SetFooProgressSignalOptions) (SetFooProgressSignalHandle, error)

	// UpdateFooProgress sets the current status of a CreateFoo operation
	UpdateFooProgress(workflow.Context, *v1.SetFooProgressRequest, ...*UpdateFooProgressUpdateOptions) (*v1.GetFooProgressResponse, error)

	// UpdateFooProgress sets the current status of a CreateFoo operation
	UpdateFooProgressAsync(workflow.Context, *v1.SetFooProgressRequest, ...*UpdateFooProgressUpdateOptions) (UpdateFooProgressHandle, error)
}

// createFooRun provides a(n) CreateFooRun implementation
type createFooRun struct {
	cancel            func()
	ctx               workflow.Context
	future            workflow.Future
	id                string
	heartbeatInterval time.Duration
	parentClosePolicy enumsv1.ParentClosePolicy
}

// Cancel the underlying workflow execution
func (r *createFooRun) Cancel(ctx workflow.Context) error {
	if r.cancel != nil {
		r.cancel()
		if _, err := r.Get(ctx); err != nil && !errors.Is(err, workflow.ErrCanceled) {
			return err
		}
		return nil
	}
	return CancelExampleWorkflow(ctx, r.id, "")
}

// Future returns the underlying activity future
func (r *createFooRun) Future() workflow.Future {
	if r.future == nil {
		rr := GetCreateFooAsync(r.ctx, r.id, "").(*createFooRun)
		r.future = rr.future
		r.cancel = rr.cancel
	}
	return r.future
}

// Get blocks on activity completion and returns the underlying workflow result
func (r *createFooRun) Get(ctx workflow.Context) (*v1.CreateFooResponse, error) {
	ctx, cancel := workflow.WithCancel(ctx)
	if r.future == nil {
		rr := GetCreateFooAsync(ctx, r.id, "", NewGetCreateFooOptions().WithParentClosePolicy(r.parentClosePolicy).WithHeartbeatInterval(r.heartbeatInterval)).(*createFooRun)
		r.future = rr.future
		r.cancel = cancel
	}
	var resp v1.CreateFooResponse
	if err := r.future.Get(ctx, &resp); err != nil {
		return nil, err
	}
	return &resp, nil
}

// ID returns the underlying workflow id
func (r *createFooRun) ID() string {
	return r.id
}

// GetFooProgress returns the status of a CreateFoo operation
func (r *createFooRun) GetFooProgress(ctx workflow.Context, opts ...*GetFooProgressQueryOptions) (*v1.GetFooProgressResponse, error) {
	return GetFooProgress(ctx, r.ID(), "", opts...)
}

// GetFooProgress returns the status of a CreateFoo operation
func (r *createFooRun) GetFooProgressAsync(ctx workflow.Context, opts ...*GetFooProgressQueryOptions) (GetFooProgressQueryHandle, error) {
	return GetFooProgressAsync(ctx, r.ID(), "", opts...)
}

// SetFooProgress sets the current status of a CreateFoo operation
func (r *createFooRun) SetFooProgress(ctx workflow.Context, req *v1.SetFooProgressRequest, opts ...*SetFooProgressSignalOptions) error {
	return SetFooProgress(ctx, r.ID(), "", req, opts...)
}

// SetFooProgress sets the current status of a CreateFoo operation
func (r *createFooRun) SetFooProgressAsync(ctx workflow.Context, req *v1.SetFooProgressRequest, opts ...*SetFooProgressSignalOptions) (SetFooProgressSignalHandle, error) {
	return SetFooProgressAsync(ctx, r.ID(), "", req, opts...)
}

// UpdateFooProgress sets the current status of a CreateFoo operation
func (r *createFooRun) UpdateFooProgress(ctx workflow.Context, req *v1.SetFooProgressRequest, opts ...*UpdateFooProgressUpdateOptions) (*v1.GetFooProgressResponse, error) {
	return UpdateFooProgress(ctx, r.ID(), "", req, opts...)
}

// UpdateFooProgress sets the current status of a CreateFoo operation
func (r *createFooRun) UpdateFooProgressAsync(ctx workflow.Context, req *v1.SetFooProgressRequest, opts ...*UpdateFooProgressUpdateOptions) (UpdateFooProgressHandle, error) {
	return UpdateFooProgressAsync(ctx, r.ID(), "", req, opts...)
}

// CreateFoo creates a new foo operation
func CreateFoo(ctx workflow.Context, req *v1.CreateFooRequest, opts ...*CreateFooWorkflowOptions) (*v1.CreateFooResponse, error) {
	run, err := CreateFooAsync(ctx, req, opts...)
	if err != nil {
		return nil, err
	}
	return run.Get(ctx)
}

// CreateFoo creates a new foo operation
func CreateFooAsync(ctx workflow.Context, input *v1.CreateFooRequest, opts ...*CreateFooWorkflowOptions) (CreateFooRun, error) {
	activityName := exampleOptions.filterActivity(v1.CreateFooWorkflowName)
	if activityName == "" {
		return nil, temporal.NewNonRetryableApplicationError(
			fmt.Sprintf("no activity registered for %s", v1.CreateFooWorkflowName),
			"Unimplemented",
			nil,
		)
	}

	var opt *CreateFooWorkflowOptions
	if len(opts) > 0 && opts[0] != nil {
		opt = opts[0]
	} else {
		opt = NewCreateFooWorkflowOptions()
	}
	ctx, req, err := opt.Build(ctx, input)
	if err != nil {
		return nil, exampleOptions.convertError(err)
	}
	ctx, cancel := workflow.WithCancel(ctx)
	return &createFooRun{
		cancel: cancel,
		future: workflow.ExecuteActivity(ctx, activityName, req),
		id:     req.GetStartWorkflowOptions().GetId(),
	}, nil
}

// GetCreateFoo returns a(n) example.xns.v1.Example.CreateFoo workflow execution
func GetCreateFoo(ctx workflow.Context, workflowID string, runID string, options ...*GetCreateFooOptions) (out *v1.CreateFooResponse, err error) {
	out, err = GetCreateFooAsync(ctx, workflowID, runID, options...).Get(ctx)
	if err != nil {
		return nil, err
	}
	return out, nil
}

// GetCreateFooAsync returns a handle to a(n) example.xns.v1.Example.CreateFoo workflow execution
func GetCreateFooAsync(ctx workflow.Context, workflowID string, runID string, options ...*GetCreateFooOptions) CreateFooRun {
	activityName := exampleOptions.filterActivity("example.xns.v1.Example.GetCreateFoo")
	if activityName == "" {
		f, set := workflow.NewFuture(ctx)
		set.SetError(temporal.NewNonRetryableApplicationError(fmt.Sprintf("no activity registered for %s", activityName), "Unimplemented", nil))
		return &createFooRun{
			future: f,
			id:     workflowID,
		}
	}
	var opt *GetCreateFooOptions
	if len(options) > 0 && options[0] != nil {
		opt = options[0]
	} else {
		opt = NewGetCreateFooOptions()
	}
	ctx, req, err := opt.Build(ctx, workflowID, runID)
	if err != nil {
		f, set := workflow.NewFuture(ctx)
		set.SetError(exampleOptions.convertError(temporal.NewNonRetryableApplicationError(fmt.Sprintf("no activity registered for %s", activityName), "Unimplemented", nil)))
		return &createFooRun{
			future: f,
			id:     workflowID,
		}
	}
	ctx, cancel := workflow.WithCancel(ctx)
	return &createFooRun{
		cancel: cancel,
		future: workflow.ExecuteActivity(ctx, activityName, req),
		id:     workflowID,
	}
}

// GetCreateFooOptions are used to configure a(n) example.xns.v1.Example.CreateFoo workflow execution getter activity
type GetCreateFooOptions struct {
	activityOptions   *workflow.ActivityOptions
	heartbeatInterval time.Duration
	parentClosePolicy enumsv1.ParentClosePolicy
}

// NewGetCreateFooOptions initializes a new GetCreateFooOptions value
func NewGetCreateFooOptions() *GetCreateFooOptions {
	return &GetCreateFooOptions{}
}

// Build initializes the activity context and input
func (opt *GetCreateFooOptions) Build(ctx workflow.Context, workflowID string, runID string) (workflow.Context, *xnsv1.GetWorkflowRequest, error) {
	if opt.heartbeatInterval == 0 {
		opt.heartbeatInterval = 10000000000 // 10 seconds
	}

	// configure activity options
	var ao workflow.ActivityOptions
	if opt.activityOptions != nil {
		ao = *opt.activityOptions
	} else {
		ao = workflow.ActivityOptions{}
	}
	if ao.HeartbeatTimeout == 0 {
		ao.HeartbeatTimeout = 20000000000 // 20 seconds
	}
	// WaitForCancellation must be set otherwise the underlying workflow is not guaranteed to be canceled
	ao.WaitForCancellation = true

	if ao.StartToCloseTimeout == 0 {
		ao.StartToCloseTimeout = 3630000000000 // 1 hour 30 seconds
	}
	ctx = workflow.WithActivityOptions(ctx, ao)

	return ctx, &xnsv1.GetWorkflowRequest{
		HeartbeatInterval: durationpb.New(opt.heartbeatInterval),
		ParentClosePolicy: opt.parentClosePolicy,
		RunId:             runID,
		WorkflowId:        workflowID,
	}, nil
}

// WithActivityOptions can be used to customize the activity options
func (o *GetCreateFooOptions) WithActivityOptions(ao workflow.ActivityOptions) *GetCreateFooOptions {
	o.activityOptions = &ao
	return o
}

// WithHeartbeatInterval can be used to customize the activity heartbeat interval
func (o *GetCreateFooOptions) WithHeartbeatInterval(d time.Duration) *GetCreateFooOptions {
	o.heartbeatInterval = d
	return o
}

// WithParentClosePolicy can be used to customize the cancellation propagation behavior
func (o *GetCreateFooOptions) WithParentClosePolicy(policy enumsv1.ParentClosePolicy) *GetCreateFooOptions {
	o.parentClosePolicy = policy
	return o
}

// CreateFooWithSetFooProgressOptions are used to configure a(n) example.xns.v1.Example.CreateFooWithSetFooProgress activity
type CreateFooWithSetFooProgressOptions struct {
	ActivityOptions      *workflow.ActivityOptions
	Detached             bool
	HeartbeatInterval    time.Duration
	HeartbeatTimeout     time.Duration
	ParentClosePolicy    enumsv1.ParentClosePolicy
	StartWorkflowOptions *client.StartWorkflowOptions
}

// NewCreateFooWithSetFooProgressOptions initializes a new CreateFooWithSetFooProgressOptions value
func NewCreateFooWithSetFooProgressOptions() *CreateFooWithSetFooProgressOptions {
	return &CreateFooWithSetFooProgressOptions{}
}

// Build initializes the activity context and input
func (opts *CreateFooWithSetFooProgressOptions) Build(ctx workflow.Context, input *v1.CreateFooRequest, signal *v1.SetFooProgressRequest) (workflow.Context, *xnsv1.WorkflowRequest, error) {
	// initialize start workflow options
	swo := client.StartWorkflowOptions{}
	if opts.StartWorkflowOptions != nil {
		swo = *opts.StartWorkflowOptions
	}

	// initialize workflow id if not set
	if swo.ID == "" {
		if err := workflow.SideEffect(ctx, func(ctx workflow.Context) any {
			id, err := expression.EvalExpression(v1.CreateFooIdexpression, input.ProtoReflect())
			if err != nil {
				workflow.GetLogger(ctx).Error("error evaluating id expression for \"example.xns.v1.Example.CreateFoo\" workflow", "error", err)
				return nil
			}
			return id
		}).Get(&swo.ID); err != nil {
			return nil, nil, err
		}
	}
	if swo.ID == "" {
		if err := workflow.SideEffect(ctx, func(ctx workflow.Context) any {
			id, err := uuid.NewRandom()
			if err != nil {
				workflow.GetLogger(ctx).Error("error generating workflow id", "error", err)
				return nil
			}
			return id
		}).Get(&swo.ID); err != nil {
			return nil, nil, err
		}
	}
	if swo.ID == "" {
		return nil, nil, temporal.NewNonRetryableApplicationError("workflow id is required", "InvalidArgument", nil)
	}

	// marshal workflow request protobuf message
	inputpb, err := anypb.New(input)
	if err != nil {
		return ctx, nil, fmt.Errorf("error marshalling workflow request: %w", err)
	}

	// marshal signal request protobuf message
	signalpb, err := anypb.New(signal)
	if err != nil {
		return ctx, nil, fmt.Errorf("error marshalling signal request: %w", err)
	}

	// marshal start workflow options protobuf message
	swopb, err := xns.MarshalStartWorkflowOptions(swo)
	if err != nil {
		return ctx, nil, fmt.Errorf("error marshalling start workflow options: %w", err)
	}

	// marshal parent close policy protobuf message
	var parentClosePolicy temporalv1.ParentClosePolicy
	switch opts.ParentClosePolicy {
	case enumsv1.PARENT_CLOSE_POLICY_ABANDON:
		parentClosePolicy = temporalv1.ParentClosePolicy_PARENT_CLOSE_POLICY_ABANDON
	case enumsv1.PARENT_CLOSE_POLICY_REQUEST_CANCEL:
		parentClosePolicy = temporalv1.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL
	case enumsv1.PARENT_CLOSE_POLICY_TERMINATE:
		parentClosePolicy = temporalv1.ParentClosePolicy_PARENT_CLOSE_POLICY_TERMINATE
	}

	// initialize xns activity options
	ao := workflow.ActivityOptions{}
	if opts.ActivityOptions != nil {
		ao = *opts.ActivityOptions
	}

	if ao.HeartbeatTimeout == 0 {
		ao.HeartbeatTimeout = 20000000000 // 20 seconds
	}

	if ao.StartToCloseTimeout == 0 {
		ao.StartToCloseTimeout = 3630000000000 // 1 hour 30 seconds
	}

	// WaitForCancellation must be set otherwise the underlying workflow is not guaranteed to be canceled
	ao.WaitForCancellation = true

	// configure heartbeat interval
	if opts.HeartbeatInterval == 0 {
		opts.HeartbeatInterval = 10000000000 // 10 seconds
	}

	ctx = workflow.WithActivityOptions(ctx, ao)

	return ctx, &xnsv1.WorkflowRequest{
		Detached:             opts.Detached,
		HeartbeatInterval:    durationpb.New(opts.HeartbeatInterval),
		ParentClosePolicy:    parentClosePolicy,
		Request:              inputpb,
		Signal:               signalpb,
		StartWorkflowOptions: swopb,
	}, nil
}

// WithActivityOptions can be used to customize the activity options
func (opts *CreateFooWithSetFooProgressOptions) WithActivityOptions(ao workflow.ActivityOptions) *CreateFooWithSetFooProgressOptions {
	opts.ActivityOptions = &ao
	return opts
}

// WithDetached can be used to start a workflow execution and exit immediately
func (opts *CreateFooWithSetFooProgressOptions) WithDetached(d bool) *CreateFooWithSetFooProgressOptions {
	opts.Detached = d
	return opts
}

// WithHeartbeatInterval can be used to customize the activity heartbeat interval
func (opts *CreateFooWithSetFooProgressOptions) WithHeartbeatInterval(d time.Duration) *CreateFooWithSetFooProgressOptions {
	opts.HeartbeatInterval = d
	return opts
}

// WithHeartbeatTimeout can be used to customize the activity heartbeat timeout
func (opts *CreateFooWithSetFooProgressOptions) WithHeartbeatTimeout(d time.Duration) *CreateFooWithSetFooProgressOptions {
	opts.HeartbeatTimeout = d
	return opts
}

// WithParentClosePolicy can be used to customize the cancellation propagation behavior
func (opts *CreateFooWithSetFooProgressOptions) WithParentClosePolicy(policy enumsv1.ParentClosePolicy) *CreateFooWithSetFooProgressOptions {
	opts.ParentClosePolicy = policy
	return opts
}

// WithStartWorkflowOptions can be used to customize the start workflow options
func (opts *CreateFooWithSetFooProgressOptions) WithStartWorkflow(swo client.StartWorkflowOptions) *CreateFooWithSetFooProgressOptions {
	opts.StartWorkflowOptions = &swo
	return opts
}

// CreateFoo creates a new foo operation
func CreateFooWithSetFooProgress(ctx workflow.Context, input *v1.CreateFooRequest, signal *v1.SetFooProgressRequest, opts ...*CreateFooWithSetFooProgressOptions) (*v1.CreateFooResponse, error) {
	run, err := CreateFooWithSetFooProgressAsync(ctx, input, signal, opts...)
	if err != nil {
		return nil, err
	}
	return run.Get(ctx)
}

// CreateFooWithSetFooProgressAsync executes a(n) example.xns.v1.Example.CreateFooWithSetFooProgress activity and returns a handle to the activity
func CreateFooWithSetFooProgressAsync(ctx workflow.Context, input *v1.CreateFooRequest, signal *v1.SetFooProgressRequest, opts ...*CreateFooWithSetFooProgressOptions) (CreateFooRun, error) {
	activityName := exampleOptions.filterActivity("example.xns.v1.Example.CreateFooWithSetFooProgress")
	if activityName == "" {
		return nil, temporal.NewNonRetryableApplicationError(
			fmt.Sprintf("no activity registered for %s", "example.xns.v1.Example.CreateFooWithSetFooProgress"),
			"Unimplemented",
			nil,
		)
	}

	var opt *CreateFooWithSetFooProgressOptions
	if len(opts) > 0 && opts[0] != nil {
		opt = opts[0]
	} else {
		opt = NewCreateFooWithSetFooProgressOptions()
	}
	ctx, req, err := opt.Build(ctx, input, signal)
	if err != nil {
		return nil, err
	}
	ctx, cancel := workflow.WithCancel(ctx)
	return &createFooRun{
		cancel: cancel,
		future: workflow.ExecuteActivity(ctx, activityName, req),
		id:     req.GetStartWorkflowOptions().GetId(),
	}, nil
}

// GetFooProgressQueryOptions are used to configure a(n) example.xns.v1.Example.GetFooProgress query execution
type GetFooProgressQueryOptions struct {
	ActivityOptions   *workflow.ActivityOptions
	HeartbeatInterval time.Duration
}

// NewGetFooProgressQueryOptions initializes a new GetFooProgressQueryOptions value
func NewGetFooProgressQueryOptions() *GetFooProgressQueryOptions {
	return &GetFooProgressQueryOptions{}
}

// WithActivityOptions can be used to customize the activity options
func (opts *GetFooProgressQueryOptions) WithActivityOptions(ao workflow.ActivityOptions) *GetFooProgressQueryOptions {
	opts.ActivityOptions = &ao
	return opts
}

// WithHeartbeatInterval can be used to customize the activity heartbeat interval
func (opts *GetFooProgressQueryOptions) WithHeartbeatInterval(d time.Duration) *GetFooProgressQueryOptions {
	opts.HeartbeatInterval = d
	return opts
}

// GetFooProgressQueryHandle provides a handle for a example.xns.v1.Example.GetFooProgress query activity
type GetFooProgressQueryHandle interface {
	// Cancel cancels the workflow
	Cancel(workflow.Context) error

	// Future returns the inner workflow.Future
	Future() workflow.Future

	// Get returns the inner workflow.Future
	Get(workflow.Context) (*v1.GetFooProgressResponse, error)
}

// getFooProgressQueryHandle provides a(n) GetFooProgressQueryHandle implementation
type getFooProgressQueryHandle struct {
	cancel func()
	future workflow.Future
}

// Cancel the underlying query activity
func (r *getFooProgressQueryHandle) Cancel(ctx workflow.Context) error {
	r.cancel()
	if _, err := r.Get(ctx); err != nil && !errors.Is(err, workflow.ErrCanceled) {
		return err
	}
	return nil
}

// Future returns the underlying activity future
func (r *getFooProgressQueryHandle) Future() workflow.Future {
	return r.future
}

// Get blocks on activity completion and returns the underlying query result
func (r *getFooProgressQueryHandle) Get(ctx workflow.Context) (*v1.GetFooProgressResponse, error) {
	var resp v1.GetFooProgressResponse
	if err := r.future.Get(ctx, &resp); err != nil {
		return nil, err
	}
	return &resp, nil
}

// GetFooProgress returns the status of a CreateFoo operation
func GetFooProgress(ctx workflow.Context, workflowID string, runID string, opts ...*GetFooProgressQueryOptions) (*v1.GetFooProgressResponse, error) {
	handle, err := GetFooProgressAsync(ctx, workflowID, runID, opts...)
	if err != nil {
		return nil, err
	}
	return handle.Get(ctx)
}

// GetFooProgressAsync executes a(n) example.xns.v1.Example.GetFooProgress query and returns a handle to the activity
func GetFooProgressAsync(ctx workflow.Context, workflowID string, runID string, opts ...*GetFooProgressQueryOptions) (GetFooProgressQueryHandle, error) {
	activityName := exampleOptions.filterActivity(v1.GetFooProgressQueryName)
	if activityName == "" {
		return nil, temporal.NewNonRetryableApplicationError(
			fmt.Sprintf("no activity registered for %s", v1.GetFooProgressQueryName),
			"Unimplemented",
			nil,
		)
	}

	opt := &GetFooProgressQueryOptions{}
	if len(opts) > 0 && opts[0] != nil {
		opt = opts[0]
	}

	if opt.HeartbeatInterval == 0 {
		opt.HeartbeatInterval = 10000000000 // 10 seconds
	}

	// configure activity options
	var ao workflow.ActivityOptions
	if opt.ActivityOptions != nil {
		ao = *opt.ActivityOptions
	} else {
		ao = workflow.ActivityOptions{}
	}
	if ao.HeartbeatTimeout == 0 {
		ao.HeartbeatTimeout = 20000000000 // 20 seconds
	}
	// WaitForCancellation must be set otherwise the underlying workflow is not guaranteed to be canceled
	ao.WaitForCancellation = true

	if ao.StartToCloseTimeout == 0 {
		ao.StartToCloseTimeout = 60000000000 // 1 minute
	}
	ctx = workflow.WithActivityOptions(ctx, ao)

	ctx, cancel := workflow.WithCancel(ctx)
	return &getFooProgressQueryHandle{
		cancel: cancel,
		future: workflow.ExecuteActivity(ctx, activityName, &xnsv1.QueryRequest{
			HeartbeatInterval: durationpb.New(opt.HeartbeatInterval),
			WorkflowId:        workflowID,
			RunId:             runID,
		}),
	}, nil
}

// SetFooProgressSignalOptions are used to configure a(n) example.xns.v1.Example.SetFooProgress signal execution
type SetFooProgressSignalOptions struct {
	ActivityOptions   *workflow.ActivityOptions
	HeartbeatInterval time.Duration
}

// NewSetFooProgressSignalOptions initializes a new SetFooProgressSignalOptions value
func NewSetFooProgressSignalOptions() *SetFooProgressSignalOptions {
	return &SetFooProgressSignalOptions{}
}

// WithActivityOptions can be used to customize the activity options
func (opts *SetFooProgressSignalOptions) WithActivityOptions(ao workflow.ActivityOptions) *SetFooProgressSignalOptions {
	opts.ActivityOptions = &ao
	return opts
}

// WithHeartbeatInterval can be used to customize the activity heartbeat interval
func (opts *SetFooProgressSignalOptions) WithHeartbeatInterval(d time.Duration) *SetFooProgressSignalOptions {
	opts.HeartbeatInterval = d
	return opts
}

// SetFooProgressSignalHandle provides a handle for a example.xns.v1.Example.SetFooProgress signal activity
type SetFooProgressSignalHandle interface {
	// Cancel cancels the workflow
	Cancel(workflow.Context) error
	// Future returns the inner workflow.Future
	Future() workflow.Future
	// Get returns the inner workflow.Future
	Get(workflow.Context) error
}

// setFooProgressSignalHandle provides a(n) SetFooProgressQueryHandle implementation
type setFooProgressSignalHandle struct {
	cancel func()
	future workflow.Future
}

// Cancel the underlying signal activity
func (r *setFooProgressSignalHandle) Cancel(ctx workflow.Context) error {
	r.cancel()
	if err := r.Get(ctx); err != nil && !errors.Is(err, workflow.ErrCanceled) {
		return err
	}
	return nil
}

// Future returns the underlying activity future
func (r *setFooProgressSignalHandle) Future() workflow.Future {
	return r.future
}

// Get blocks on activity completion
func (r *setFooProgressSignalHandle) Get(ctx workflow.Context) error {
	return r.future.Get(ctx, nil)
}

// SetFooProgress sets the current status of a CreateFoo operation
func SetFooProgress(ctx workflow.Context, workflowID string, runID string, req *v1.SetFooProgressRequest, opts ...*SetFooProgressSignalOptions) error {
	handle, err := SetFooProgressAsync(ctx, workflowID, runID, req, opts...)
	if err != nil {
		return err
	}
	return handle.Get(ctx)
}

// SetFooProgressAsync executes a(n) example.xns.v1.Example.SetFooProgress signal
func SetFooProgressAsync(ctx workflow.Context, workflowID string, runID string, req *v1.SetFooProgressRequest, opts ...*SetFooProgressSignalOptions) (SetFooProgressSignalHandle, error) {
	activityName := exampleOptions.filterActivity(v1.SetFooProgressSignalName)
	if activityName == "" {
		return nil, temporal.NewNonRetryableApplicationError(
			fmt.Sprintf("no activity registered for %s", v1.SetFooProgressSignalName),
			"Unimplemented",
			nil,
		)
	}

	opt := &SetFooProgressSignalOptions{}
	if len(opts) > 0 && opts[0] != nil {
		opt = opts[0]
	}

	if opt.HeartbeatInterval == 0 {
		opt.HeartbeatInterval = 10000000000 // 10 seconds
	}

	// configure activity options
	var ao workflow.ActivityOptions
	if opt.ActivityOptions != nil {
		ao = *opt.ActivityOptions
	} else {
		ao = workflow.ActivityOptions{}
	}
	if ao.HeartbeatTimeout == 0 {
		ao.HeartbeatTimeout = 20000000000 // 20 seconds
	}
	// WaitForCancellation must be set otherwise the underlying workflow is not guaranteed to be canceled
	ao.WaitForCancellation = true

	if ao.StartToCloseTimeout == 0 {
		ao.StartToCloseTimeout = 60000000000 // 1 minute
	}
	ctx = workflow.WithActivityOptions(ctx, ao)

	// marshal workflow request
	wreq, err := anypb.New(req)
	if err != nil {
		return nil, fmt.Errorf("error marshalling workflow request: %w", err)
	}

	ctx, cancel := workflow.WithCancel(ctx)
	return &setFooProgressSignalHandle{
		cancel: cancel,
		future: workflow.ExecuteActivity(ctx, activityName, &xnsv1.SignalRequest{
			HeartbeatInterval: durationpb.New(opt.HeartbeatInterval),
			WorkflowId:        workflowID,
			RunId:             runID,
			Request:           wreq,
		}),
	}, nil
}

// UpdateFooProgressUpdateOptions are used to configure a(n) example.xns.v1.Example.UpdateFooProgress update execution
type UpdateFooProgressUpdateOptions struct {
	ActivityOptions       *workflow.ActivityOptions
	HeartbeatInterval     time.Duration
	UpdateWorkflowOptions *client.UpdateWorkflowOptions
}

// NewUpdateFooProgressUpdateOptions initializes a new UpdateFooProgressUpdateOptions value
func NewUpdateFooProgressUpdateOptions() *UpdateFooProgressUpdateOptions {
	return &UpdateFooProgressUpdateOptions{}
}

// Build initializes the update options
func (opt *UpdateFooProgressUpdateOptions) Build(ctx workflow.Context, workflowID string, runID string, input *v1.SetFooProgressRequest) (workflow.Context, *xnsv1.UpdateRequest, error) {
	// configure activity options
	var ao workflow.ActivityOptions
	if opt.ActivityOptions != nil {
		ao = *opt.ActivityOptions
	} else {
		ao = workflow.ActivityOptions{}
	}
	if ao.HeartbeatTimeout == 0 {
		ao.HeartbeatTimeout = 20000000000 // 20 seconds
	}
	if ao.StartToCloseTimeout == 0 {
		ao.StartToCloseTimeout = 60000000000 // 1 minute
	}

	// WaitForCancellation must be set otherwise the underlying workflow is not guaranteed to be canceled
	ao.WaitForCancellation = true

	// configure heartbeat interval
	if opt.HeartbeatInterval == 0 {
		opt.HeartbeatInterval = 10000000000 // 10 seconds
	}

	ctx = workflow.WithActivityOptions(ctx, ao)

	uo := client.UpdateWorkflowOptions{}
	if opt.UpdateWorkflowOptions != nil {
		uo = *opt.UpdateWorkflowOptions
	}
	uo.WorkflowID = workflowID
	uo.RunID = runID
	if uo.UpdateID == "" {
		if err := workflow.SideEffect(ctx, func(ctx workflow.Context) any {
			id, err := expression.EvalExpression(v1.UpdateFooProgressIdexpression, input.ProtoReflect())
			if err != nil {
				workflow.GetLogger(ctx).Error("error evaluating id expression for \"example.xns.v1.Example.UpdateFooProgress\" update", "error", err)
				return nil
			}
			return id
		}).Get(&uo.UpdateID); err != nil {
			return nil, nil, err
		}
	}
	if uo.UpdateID == "" {
		if err := workflow.SideEffect(ctx, func(ctx workflow.Context) any {
			id, err := uuid.NewRandom()
			if err != nil {
				workflow.GetLogger(ctx).Error("error generating update id", "error", err)
				return nil
			}
			return id
		}).Get(&uo.UpdateID); err != nil {
			return nil, nil, err
		}
	}
	if uo.UpdateID == "" {
		return nil, nil, temporal.NewNonRetryableApplicationError("update id is required", "InvalidArgument", nil)
	}

	uopb, err := xns.MarshalUpdateWorkflowOptions(uo)
	if err != nil {
		return nil, nil, fmt.Errorf("error marshalling update workflow options: %w", err)
	}

	inpb, err := anypb.New(input)
	if err != nil {
		return nil, nil, fmt.Errorf("error marshalling update request: %w", err)
	}

	return ctx, &xnsv1.UpdateRequest{
		HeartbeatInterval:     durationpb.New(opt.HeartbeatInterval),
		Request:               inpb,
		UpdateWorkflowOptions: uopb,
	}, nil
}

// WithActivityOptions can be used to customize the activity options
func (opts *UpdateFooProgressUpdateOptions) WithActivityOptions(ao workflow.ActivityOptions) *UpdateFooProgressUpdateOptions {
	opts.ActivityOptions = &ao
	return opts
}

// WithHeartbeatInterval can be used to customize the activity heartbeat interval
func (opts *UpdateFooProgressUpdateOptions) WithHeartbeatInterval(d time.Duration) *UpdateFooProgressUpdateOptions {
	opts.HeartbeatInterval = d
	return opts
}

// WithUpdateWorkflowOptions can be used to customize the update workflow options
func (opts *UpdateFooProgressUpdateOptions) WithUpdateWorkflowOptions(uwo client.UpdateWorkflowOptions) *UpdateFooProgressUpdateOptions {
	opts.UpdateWorkflowOptions = &uwo
	return opts
}

// UpdateFooProgressHandle provides a handle to a example.xns.v1.Example.UpdateFooProgress workflow update
type UpdateFooProgressHandle interface {
	// Cancel cancels the update activity
	Cancel(workflow.Context) error

	// Future returns the inner workflow.Future
	Future() workflow.Future

	// Get blocks on update completion and returns the result
	Get(workflow.Context) (*v1.GetFooProgressResponse, error)

	// ID returns the update id
	ID() string
}

// updateFooProgressHandle provides a(n) UpdateFooProgressHandle implementation
type updateFooProgressHandle struct {
	cancel func()
	future workflow.Future
	id     string
}

// Cancel the underlying workflow update
func (r *updateFooProgressHandle) Cancel(ctx workflow.Context) error {
	r.cancel()
	if _, err := r.Get(ctx); err != nil && !errors.Is(err, workflow.ErrCanceled) {
		return err
	}
	return nil
}

// Future returns the underlying activity future
func (r *updateFooProgressHandle) Future() workflow.Future {
	return r.future
}

// Get blocks on activity completion and returns the underlying update result
func (r *updateFooProgressHandle) Get(ctx workflow.Context) (*v1.GetFooProgressResponse, error) {
	var resp v1.GetFooProgressResponse
	if err := r.future.Get(ctx, &resp); err != nil {
		return nil, err
	}
	return &resp, nil
}

// ID returns the underlying workflow id
func (r *updateFooProgressHandle) ID() string {
	return r.id
}

// UpdateFooProgress sets the current status of a CreateFoo operation
func UpdateFooProgress(ctx workflow.Context, workflowID string, runID string, req *v1.SetFooProgressRequest, opts ...*UpdateFooProgressUpdateOptions) (*v1.GetFooProgressResponse, error) {
	run, err := UpdateFooProgressAsync(ctx, workflowID, runID, req, opts...)
	if err != nil {
		return nil, err
	}
	return run.Get(ctx)
}

// UpdateFooProgressAsync executes a(n) example.xns.v1.Example.UpdateFooProgress update and blocks until error or response received
func UpdateFooProgressAsync(ctx workflow.Context, workflowID string, runID string, input *v1.SetFooProgressRequest, opts ...*UpdateFooProgressUpdateOptions) (UpdateFooProgressHandle, error) {
	activityName := exampleOptions.filterActivity(v1.UpdateFooProgressUpdateName)
	if activityName == "" {
		return nil, temporal.NewNonRetryableApplicationError(
			fmt.Sprintf("no activity registered for %s", v1.UpdateFooProgressUpdateName),
			"Unimplemented",
			nil,
		)
	}

	var opt *UpdateFooProgressUpdateOptions
	if len(opts) > 0 && opts[0] != nil {
		opt = opts[0]
	} else {
		opt = NewUpdateFooProgressUpdateOptions()
	}

	ctx, req, err := opt.Build(ctx, workflowID, runID, input)
	if err != nil {
		return nil, err
	}
	ctx, cancel := workflow.WithCancel(ctx)
	return &updateFooProgressHandle{
		cancel: cancel,
		id:     req.GetUpdateWorkflowOptions().GetUpdateId(),
		future: workflow.ExecuteActivity(ctx, activityName, req),
	}, nil
}

// CancelExampleWorkflow cancels an existing workflow
func CancelExampleWorkflow(ctx workflow.Context, workflowID string, runID string) error {
	return CancelExampleWorkflowAsync(ctx, workflowID, runID).Get(ctx, nil)
}

// CancelExampleWorkflowAsync cancels an existing workflow
func CancelExampleWorkflowAsync(ctx workflow.Context, workflowID string, runID string) workflow.Future {
	activityName := exampleOptions.filterActivity("example.xns.v1.Example.CancelWorkflow")
	if activityName == "" {
		f, s := workflow.NewFuture(ctx)
		s.SetError(temporal.NewNonRetryableApplicationError(
			"no activity registered for example.xns.v1.Example.CancelWorkflow",
			"Unimplemented",
			nil,
		))
		return f
	}
	ao := workflow.GetActivityOptions(ctx)
	if ao.StartToCloseTimeout == 0 && ao.ScheduleToCloseTimeout == 0 {
		ao.StartToCloseTimeout = time.Minute
	}
	ctx = workflow.WithActivityOptions(ctx, ao)
	return workflow.ExecuteActivity(ctx, activityName, workflowID, runID)
}

// exampleActivities provides activities that can be used to interact with a(n) Example service's workflow, queries, signals, and updates across namespaces
type exampleActivities struct {
	client v1.ExampleClient
}

// CancelWorkflow cancels an existing workflow execution
func (a *exampleActivities) CancelWorkflow(ctx context.Context, workflowID string, runID string) error {
	return a.client.CancelWorkflow(ctx, workflowID, runID)
}

// GetCreateFoo retrieves a(n) example.xns.v1.Example.CreateFoo workflow via an activity
func (a *exampleActivities) GetCreateFoo(ctx context.Context, input *xnsv1.GetWorkflowRequest) (out *v1.CreateFooResponse, err error) {
	heartbeatInterval := input.GetHeartbeatInterval().AsDuration()
	if heartbeatInterval == 0 {
		heartbeatInterval = time.Second * 30
	}

	actx, cancel := context.WithCancel(context.Background())
	defer cancel()
	run := a.client.GetCreateFoo(actx, input.GetWorkflowId(), input.GetRunId())
	done := make(chan struct{})
	go func() {
		defer close(done)
		out, err = run.Get(actx)
	}()

	for {
		select {
		// send heartbeats periodically
		case <-time.After(heartbeatInterval):
			activity.RecordHeartbeat(ctx)

		// return retryable error if the worker is stopping
		case <-activity.GetWorkerStopChannel(ctx):
			return nil, exampleOptions.convertError(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():
			select {
			case <-activity.GetWorkerStopChannel(ctx):
				activity.GetLogger(ctx).Info("worker is stopping")
				return nil, exampleOptions.convertError(temporal.NewApplicationError("worker is stopping", "WorkerStopped"))
			default:
				parentClosePolicy := input.GetParentClosePolicy()
				if parentClosePolicy == enumsv1.PARENT_CLOSE_POLICY_REQUEST_CANCEL || parentClosePolicy == enumsv1.PARENT_CLOSE_POLICY_TERMINATE {
					disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Minute)
					defer cancel()
					if parentClosePolicy == enumsv1.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()))
			}

		// handle workflow completion
		case <-done:
			return out, exampleOptions.convertError(err)
		}
	}
}

// CreateFoo executes a(n) example.xns.v1.Example.CreateFoo workflow via an activity
func (a *exampleActivities) CreateFoo(ctx context.Context, input *xnsv1.WorkflowRequest) (resp *v1.CreateFooResponse, err error) {
	// unmarshal workflow request
	var req v1.CreateFooRequest
	if err := input.Request.UnmarshalTo(&req); err != nil {
		return nil, exampleOptions.convertError(temporal.NewNonRetryableApplicationError(
			fmt.Sprintf("error unmarshalling workflow request of type %s as github.com/cludden/protoc-gen-go-temporal/gen/example/xns/v1.CreateFooRequest", input.Request.GetTypeUrl()),
			"InvalidArgument",
			err,
		))
	}

	// initialize workflow execution
	actx := ctx
	if !input.GetDetached() {
		var cancel context.CancelFunc
		actx, cancel = context.WithCancel(context.Background())
		defer cancel()
	}
	var run v1.CreateFooRun
	run, err = a.client.CreateFooAsync(actx, &req, v1.NewCreateFooOptions().WithStartWorkflowOptions(
		xns.UnmarshalStartWorkflowOptions(input.GetStartWorkflowOptions()),
	))
	if err != nil {
		return nil, exampleOptions.convertError(err)
	}

	// exit early if detached enabled
	if input.GetDetached() {
		return nil, nil
	}

	// otherwise, wait for execution to complete in child goroutine
	doneCh := make(chan struct{})
	go func() {
		resp, err = run.Get(actx)
		close(doneCh)
	}()

	heartbeatInterval := input.GetHeartbeatInterval().AsDuration()
	if heartbeatInterval == 0 {
		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():
			select {
			case <-activity.GetWorkerStopChannel(ctx):
				return nil, temporal.NewApplicationError("worker is stopping", "WorkerStopped")
			default:
				parentClosePolicy := input.GetParentClosePolicy()
				if parentClosePolicy == temporalv1.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL || parentClosePolicy == temporalv1.ParentClosePolicy_PARENT_CLOSE_POLICY_TERMINATE {
					disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Minute)
					defer cancel()
					if parentClosePolicy == temporalv1.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()))
			}

		// handle workflow completion
		case <-doneCh:
			return resp, exampleOptions.convertError(err)
		}
	}
}

// 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 *xnsv1.WorkflowRequest) (resp *v1.CreateFooResponse, err error) {
	// unmarshal workflow request
	var req v1.CreateFooRequest
	if err := input.Request.UnmarshalTo(&req); err != nil {
		return nil, exampleOptions.convertError(temporal.NewNonRetryableApplicationError(
			fmt.Sprintf("error unmarshalling workflow request of type %s as github.com/cludden/protoc-gen-go-temporal/gen/example/xns/v1.CreateFooRequest", input.Request.GetTypeUrl()),
			"InvalidArgument",
			err,
		))
	}

	// unmarshal signal request
	var signal v1.SetFooProgressRequest
	if err := input.Signal.UnmarshalTo(&signal); err != nil {
		return nil, exampleOptions.convertError(temporal.NewNonRetryableApplicationError(
			fmt.Sprintf("error unmarshalling signal request of type %s as github.com/cludden/protoc-gen-go-temporal/gen/example/xns/v1.SetFooProgressRequest", input.Signal.GetTypeUrl()),
			"InvalidArgument",
			err,
		))
	}

	// initialize workflow execution
	actx := ctx
	if !input.GetDetached() {
		var cancel context.CancelFunc
		actx, cancel = context.WithCancel(context.Background())
		defer cancel()
	}
	var run v1.CreateFooRun
	run, err = a.client.CreateFooWithSetFooProgressAsync(actx, &req, &signal, v1.NewCreateFooOptions().WithStartWorkflowOptions(
		xns.UnmarshalStartWorkflowOptions(input.GetStartWorkflowOptions()),
	))
	if err != nil {
		return nil, exampleOptions.convertError(err)
	}

	// exit early if detached enabled
	if input.GetDetached() {
		return nil, nil
	}

	// otherwise, wait for execution to complete in child goroutine
	doneCh := make(chan struct{})
	go func() {
		resp, err = run.Get(actx)
		close(doneCh)
	}()

	heartbeatInterval := input.GetHeartbeatInterval().AsDuration()
	if heartbeatInterval == 0 {
		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():
			select {
			case <-activity.GetWorkerStopChannel(ctx):
				return nil, temporal.NewApplicationError("worker is stopping", "WorkerStopped")
			default:
				parentClosePolicy := input.GetParentClosePolicy()
				if parentClosePolicy == temporalv1.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL || parentClosePolicy == temporalv1.ParentClosePolicy_PARENT_CLOSE_POLICY_TERMINATE {
					disconnectedCtx, cancel := context.WithTimeout(context.Background(), time.Minute)
					defer cancel()
					if parentClosePolicy == temporalv1.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()))
			}

		// handle workflow completion
		case <-doneCh:
			return resp, exampleOptions.convertError(err)
		}
	}
}

// GetFooProgress executes a(n) example.xns.v1.Example.GetFooProgress query via an activity
func (a *exampleActivities) GetFooProgress(ctx context.Context, input *xnsv1.QueryRequest) (resp *v1.GetFooProgressResponse, err error) {
	// execute signal in child goroutine
	doneCh := make(chan struct{})
	go func() {
		resp, err = a.client.GetFooProgress(ctx, input.GetWorkflowId(), input.GetRunId())
		close(doneCh)
	}()

	heartbeatInterval := input.GetHeartbeatInterval().AsDuration()
	if heartbeatInterval == 0 {
		heartbeatInterval = time.Second * 10
	}

	// heartbeat activity while waiting for signal to complete
	for {
		select {
		case <-time.After(heartbeatInterval):
			activity.RecordHeartbeat(ctx)
		case <-ctx.Done():
			return nil, exampleOptions.convertError(ctx.Err())
		case <-doneCh:
			return resp, exampleOptions.convertError(err)
		}
	}
}

// SetFooProgress executes a(n) example.xns.v1.Example.SetFooProgress signal via an activity
func (a *exampleActivities) SetFooProgress(ctx context.Context, input *xnsv1.SignalRequest) (err error) {
	// unmarshal signal request
	var req v1.SetFooProgressRequest
	if err := input.Request.UnmarshalTo(&req); err != nil {
		return exampleOptions.convertError(temporal.NewNonRetryableApplicationError(
			fmt.Sprintf("error unmarshalling signal request of type %s as github.com/cludden/protoc-gen-go-temporal/gen/example/xns/v1.SetFooProgressRequest", input.Request.GetTypeUrl()),
			"InvalidArgument",
			err,
		))
	}
	// execute signal in child goroutine
	doneCh := make(chan struct{})
	go func() {
		err = a.client.SetFooProgress(ctx, input.GetWorkflowId(), input.GetRunId(), &req)
		close(doneCh)
	}()

	heartbeatInterval := input.GetHeartbeatInterval().AsDuration()
	if heartbeatInterval == 0 {
		heartbeatInterval = time.Second * 10
	}

	// heartbeat activity while waiting for signal to complete
	for {
		select {
		case <-time.After(heartbeatInterval):
			activity.RecordHeartbeat(ctx)
		case <-ctx.Done():
			exampleOptions.convertError(ctx.Err())
		case <-doneCh:
			return exampleOptions.convertError(err)
		}
	}
}

// UpdateFooProgress executes a(n) example.xns.v1.Example.UpdateFooProgress update via an activity
func (a *exampleActivities) UpdateFooProgress(ctx context.Context, input *xnsv1.UpdateRequest) (resp *v1.GetFooProgressResponse, err error) {
	var handle v1.UpdateFooProgressHandle
	if activity.HasHeartbeatDetails(ctx) {
		// extract update id from heartbeat details
		var updateID string
		if err := activity.GetHeartbeatDetails(ctx, &updateID); err != nil {
			return nil, exampleOptions.convertError(err)
		}

		// retrieve handle for existing update
		handle, err = a.client.GetUpdateFooProgress(ctx, client.GetWorkflowUpdateHandleOptions{
			WorkflowID: input.GetUpdateWorkflowOptions().GetWorkflowId(),
			RunID:      input.GetUpdateWorkflowOptions().GetRunId(),
			UpdateID:   updateID,
		})
		if err != nil {
			return nil, exampleOptions.convertError(err)
		}
	} else {
		// unmarshal update request
		var req v1.SetFooProgressRequest
		if err := input.Request.UnmarshalTo(&req); err != nil {
			return nil, exampleOptions.convertError(temporal.NewNonRetryableApplicationError(
				fmt.Sprintf("error unmarshalling update request of type %s as github.com/cludden/protoc-gen-go-temporal/gen/example/xns/v1.SetFooProgressRequest", input.Request.GetTypeUrl()),
				"InvalidArgument",
				err,
			))
		}

		uo := xns.UnmarshalUpdateWorkflowOptions(input.GetUpdateWorkflowOptions())
		uo.WaitForStage = client.WorkflowUpdateStageAccepted

		// initialize update execution
		handle, err = a.client.UpdateFooProgressAsync(
			ctx,
			input.GetUpdateWorkflowOptions().GetWorkflowId(),
			input.GetUpdateWorkflowOptions().GetRunId(),
			&req,
			v1.NewUpdateFooProgressOptions().WithUpdateWorkflowOptions(uo),
		)
		if err != nil {
			return nil, exampleOptions.convertError(err)
		}
		activity.RecordHeartbeat(ctx, handle.UpdateID())
	}

	// wait for update to complete in child goroutine
	doneCh := make(chan struct{})
	go func() {
		resp, err = handle.Get(ctx)
		close(doneCh)
	}()

	heartbeatInterval := input.GetHeartbeatInterval().AsDuration()
	if heartbeatInterval == 0 {
		heartbeatInterval = time.Minute
	}

	// heartbeat activity while waiting for workflow update to complete
	for {
		select {
		case <-time.After(heartbeatInterval):
			activity.RecordHeartbeat(ctx, handle.UpdateID())
		case <-ctx.Done():
			return nil, exampleOptions.convertError(ctx.Err())
		case <-doneCh:
			return resp, exampleOptions.convertError(err)
		}
	}
}
