// Code generated by protoc-gen-go_temporal. DO NOT EDIT.
// versions:
//
//	protoc-gen-go_temporal dev (latest)
//	protoc (unknown)
//
// source: test/xnsheartbeat/v1/xnsheartbeat.proto
package xnsheartbeatv1xns

import (
	"context"
	"errors"
	"fmt"
	temporalv1 "github.com/cludden/protoc-gen-go-temporal/gen/temporal/v1"
	xnsv1 "github.com/cludden/protoc-gen-go-temporal/gen/temporal/xns/v1"
	v1 "github.com/cludden/protoc-gen-go-temporal/gen/test/xnsheartbeat/v1"
	convert "github.com/cludden/protoc-gen-go-temporal/pkg/convert"
	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"
)

// XnsHeartbeatServiceOptions is used to configure test.xnsheartbeat.v1.XnsHeartbeatService xns activity registration
type XnsHeartbeatServiceOptions 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
}

// NewXnsHeartbeatServiceOptions initializes a new XnsHeartbeatServiceOptions value
func NewXnsHeartbeatServiceOptions() *XnsHeartbeatServiceOptions {
	return &XnsHeartbeatServiceOptions{}
}

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

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

// convertError is applied to all xns activity errors
func (opts *XnsHeartbeatServiceOptions) 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 *XnsHeartbeatServiceOptions) filterActivity(name string) string {
	if opts == nil || opts.filter == nil {
		return name
	}
	return opts.filter(name)
}

// xnsHeartbeatServiceOptions is a reference to the XnsHeartbeatServiceOptions initialized at registration
var xnsHeartbeatServiceOptions *XnsHeartbeatServiceOptions

// RegisterXnsHeartbeatServiceActivities registers test.xnsheartbeat.v1.XnsHeartbeatService cross-namespace activities
func RegisterXnsHeartbeatServiceActivities(r worker.ActivityRegistry, c v1.XnsHeartbeatServiceClient, options ...*XnsHeartbeatServiceOptions) {
	if xnsHeartbeatServiceOptions == nil && len(options) > 0 && options[0] != nil {
		xnsHeartbeatServiceOptions = options[0]
	}
	a := &xnsHeartbeatServiceActivities{c}
	if name := xnsHeartbeatServiceOptions.filterActivity("test.xnsheartbeat.v1.XnsHeartbeatService.CancelWorkflow"); name != "" {
		r.RegisterActivityWithOptions(a.CancelWorkflow, activity.RegisterOptions{Name: name})
	}
	if name := xnsHeartbeatServiceOptions.filterActivity(v1.TestWorkflowWorkflowName); name != "" {
		r.RegisterActivityWithOptions(a.TestWorkflow, activity.RegisterOptions{Name: name})
	}
	if name := xnsHeartbeatServiceOptions.filterActivity("test.xnsheartbeat.v1.XnsHeartbeatService.GetTestWorkflow"); name != "" {
		r.RegisterActivityWithOptions(a.GetTestWorkflow, activity.RegisterOptions{Name: name})
	}
	if name := xnsHeartbeatServiceOptions.filterActivity("test.xnsheartbeat.v1.XnsHeartbeatService.TestWorkflowWithTestUpdate"); name != "" {
		r.RegisterActivityWithOptions(a.TestWorkflowWithTestUpdate, activity.RegisterOptions{Name: name})
	}
	if name := xnsHeartbeatServiceOptions.filterActivity(v1.TestSignalSignalName); name != "" {
		r.RegisterActivityWithOptions(a.TestSignal, activity.RegisterOptions{Name: name})
	}
	if name := xnsHeartbeatServiceOptions.filterActivity(v1.TestUpdateUpdateName); name != "" {
		r.RegisterActivityWithOptions(a.TestUpdate, activity.RegisterOptions{Name: name})
	}
}

// TestWorkflowWorkflowOptions are used to configure a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestWorkflow workflow execution
type TestWorkflowWorkflowOptions struct {
	ActivityOptions      *workflow.ActivityOptions
	Detached             bool
	HeartbeatInterval    time.Duration
	HeartbeatTimeout     time.Duration
	ParentClosePolicy    enumsv1.ParentClosePolicy
	StartWorkflowOptions *client.StartWorkflowOptions
}

// NewTestWorkflowWorkflowOptions initializes a new TestWorkflowWorkflowOptions value
func NewTestWorkflowWorkflowOptions() *TestWorkflowWorkflowOptions {
	return &TestWorkflowWorkflowOptions{}
}

// Build initializes the activity context and input
func (opts *TestWorkflowWorkflowOptions) Build(ctx workflow.Context, input *v1.TestWorkflowInput) (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 := 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 = 30000000000 // 30 seconds
	}

	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 = 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 *TestWorkflowWorkflowOptions) WithActivityOptions(ao workflow.ActivityOptions) *TestWorkflowWorkflowOptions {
	opts.ActivityOptions = &ao
	return opts
}

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

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

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

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

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

// TestWorkflowRun provides a handle to a test.xnsheartbeat.v1.XnsHeartbeatService.TestWorkflow workflow execution
type TestWorkflowRun 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.TestWorkflowOutput, error)

	// ID returns the workflow id
	ID() string

	// TestSignal executes a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestSignal signal and blocks until completion
	TestSignal(workflow.Context, *v1.TestSignalInput, ...*TestSignalSignalOptions) error

	// TestSignalAsync executes a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestSignal signal and returns a handle to the underlying activity
	TestSignalAsync(workflow.Context, *v1.TestSignalInput, ...*TestSignalSignalOptions) (TestSignalSignalHandle, error)

	// TestUpdate executes a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestUpdate update and blocks until completion
	TestUpdate(workflow.Context, *v1.TestUpdateInput, ...*TestUpdateUpdateOptions) (*v1.TestUpdateOutput, error)

	// TestUpdateAsync executes a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestUpdate update and returns a handle to the underlying activity
	TestUpdateAsync(workflow.Context, *v1.TestUpdateInput, ...*TestUpdateUpdateOptions) (TestUpdateHandle, error)
}

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

// Cancel the underlying workflow execution
func (r *testWorkflowRun) 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 CancelXnsHeartbeatServiceWorkflow(ctx, r.id, "")
}

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

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

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

// TestSignal executes a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestSignal signal and blocks until the underlying activity completes
func (r *testWorkflowRun) TestSignal(ctx workflow.Context, req *v1.TestSignalInput, opts ...*TestSignalSignalOptions) error {
	return TestSignal(ctx, r.ID(), "", req, opts...)
}

// TestSignalAsync executes a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestSignal signal and returns a handle to the underlying activity
func (r *testWorkflowRun) TestSignalAsync(ctx workflow.Context, req *v1.TestSignalInput, opts ...*TestSignalSignalOptions) (TestSignalSignalHandle, error) {
	return TestSignalAsync(ctx, r.ID(), "", req, opts...)
}

// TestUpdate executes a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestUpdate update and blocks until completion
func (r *testWorkflowRun) TestUpdate(ctx workflow.Context, req *v1.TestUpdateInput, opts ...*TestUpdateUpdateOptions) (*v1.TestUpdateOutput, error) {
	// configure activity options if unset
	opt := &TestUpdateUpdateOptions{}
	if len(opts) > 0 && opts[0] != nil {
		opt = opts[0]
	}
	if opt.ActivityOptions == nil {
		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 = 30000000000 // 30 seconds
		}
		// 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)

		opt.ActivityOptions = &ao
		opts[0] = opt
	}
	return TestUpdate(ctx, r.ID(), "", req, opts...)
}

// TestUpdateAsync executes a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestUpdate update and returns a handle to the underlying activity
func (r *testWorkflowRun) TestUpdateAsync(ctx workflow.Context, req *v1.TestUpdateInput, opts ...*TestUpdateUpdateOptions) (TestUpdateHandle, error) {
	// configure activity options if unset
	opt := &TestUpdateUpdateOptions{}
	if len(opts) > 0 && opts[0] != nil {
		opt = opts[0]
	}
	if opt.ActivityOptions == nil {
		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 = 30000000000 // 30 seconds
		}
		// 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)

		opt.ActivityOptions = &ao
		opts[0] = opt
	}
	return TestUpdateAsync(ctx, r.ID(), "", req, opts...)
}

// TestWorkflow executes a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestWorkflow workflow and blocks until error or response is received
func TestWorkflow(ctx workflow.Context, req *v1.TestWorkflowInput, opts ...*TestWorkflowWorkflowOptions) (*v1.TestWorkflowOutput, error) {
	run, err := TestWorkflowAsync(ctx, req, opts...)
	if err != nil {
		return nil, err
	}
	return run.Get(ctx)
}

// TestWorkflowAsync executes a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestWorkflow workflow and returns a handle to the underlying activity
func TestWorkflowAsync(ctx workflow.Context, input *v1.TestWorkflowInput, opts ...*TestWorkflowWorkflowOptions) (TestWorkflowRun, error) {
	activityName := xnsHeartbeatServiceOptions.filterActivity(v1.TestWorkflowWorkflowName)
	if activityName == "" {
		return nil, temporal.NewNonRetryableApplicationError(
			fmt.Sprintf("no activity registered for %s", v1.TestWorkflowWorkflowName),
			"Unimplemented",
			nil,
		)
	}

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

// GetTestWorkflow returns a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestWorkflow workflow execution
func GetTestWorkflow(ctx workflow.Context, workflowID string, runID string, options ...*GetTestWorkflowOptions) (out *v1.TestWorkflowOutput, err error) {
	out, err = GetTestWorkflowAsync(ctx, workflowID, runID, options...).Get(ctx)
	if err != nil {
		return nil, err
	}
	return out, nil
}

// GetTestWorkflowAsync returns a handle to a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestWorkflow workflow execution
func GetTestWorkflowAsync(ctx workflow.Context, workflowID string, runID string, options ...*GetTestWorkflowOptions) TestWorkflowRun {
	activityName := xnsHeartbeatServiceOptions.filterActivity("test.xnsheartbeat.v1.XnsHeartbeatService.GetTestWorkflow")
	if activityName == "" {
		f, set := workflow.NewFuture(ctx)
		set.SetError(temporal.NewNonRetryableApplicationError(fmt.Sprintf("no activity registered for %s", activityName), "Unimplemented", nil))
		return &testWorkflowRun{
			future: f,
			id:     workflowID,
		}
	}
	var opt *GetTestWorkflowOptions
	if len(options) > 0 && options[0] != nil {
		opt = options[0]
	} else {
		opt = NewGetTestWorkflowOptions()
	}
	ctx, req, err := opt.Build(ctx, workflowID, runID)
	if err != nil {
		f, set := workflow.NewFuture(ctx)
		set.SetError(xnsHeartbeatServiceOptions.convertError(temporal.NewNonRetryableApplicationError(fmt.Sprintf("no activity registered for %s", activityName), "Unimplemented", nil)))
		return &testWorkflowRun{
			future: f,
			id:     workflowID,
		}
	}
	ctx, cancel := workflow.WithCancel(ctx)
	return &testWorkflowRun{
		cancel: cancel,
		future: workflow.ExecuteActivity(ctx, activityName, req),
		id:     workflowID,
	}
}

// GetTestWorkflowOptions are used to configure a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestWorkflow workflow execution getter activity
type GetTestWorkflowOptions struct {
	activityOptions   *workflow.ActivityOptions
	heartbeatInterval time.Duration
	parentClosePolicy enumsv1.ParentClosePolicy
}

// NewGetTestWorkflowOptions initializes a new GetTestWorkflowOptions value
func NewGetTestWorkflowOptions() *GetTestWorkflowOptions {
	return &GetTestWorkflowOptions{}
}

// Build initializes the activity context and input
func (opt *GetTestWorkflowOptions) 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 = 30000000000 // 30 seconds
	}
	// 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 *GetTestWorkflowOptions) WithActivityOptions(ao workflow.ActivityOptions) *GetTestWorkflowOptions {
	o.activityOptions = &ao
	return o
}

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

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

// TestWorkflowWithTestUpdateOptions are used to configure a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestUpdate update for a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestWorkflow workflow
type TestWorkflowWithTestUpdateOptions struct {
	activityOptions   *workflow.ActivityOptions
	heartbeatInterval time.Duration
	updateOptions     *TestUpdateUpdateOptions
	parentClosePolicy enumsv1.ParentClosePolicy
	workflowOptions   *TestWorkflowWorkflowOptions
}

// NewTestWorkflowWithTestUpdateOptions initializes a new TestWorkflowWithTestUpdateOptions value
func NewTestWorkflowWithTestUpdateOptions() *TestWorkflowWithTestUpdateOptions {
	return &TestWorkflowWithTestUpdateOptions{}
}

// Build builds the activity context and input for an update with start workflow activity
func (o *TestWorkflowWithTestUpdateOptions) Build(ctx workflow.Context, input *v1.TestWorkflowInput, update *v1.TestUpdateInput) (workflow.Context, *xnsv1.UpdateWithStartRequest, error) {
	wo := o.workflowOptions
	if wo == nil {
		wo = NewTestWorkflowWorkflowOptions()
	}

	_, swreq, err := wo.Build(ctx, input)
	if err != nil {
		return nil, nil, fmt.Errorf("error building start workflow options: %w", err)
	}

	uo := o.updateOptions
	if uo == nil {
		uo = NewTestUpdateUpdateOptions()
	}

	ctx, ureq, err := uo.Build(ctx, swreq.GetStartWorkflowOptions().GetId(), "", update)
	if err != nil {
		return nil, nil, fmt.Errorf("error building update options: %w", err)
	}

	var ao workflow.ActivityOptions
	if o.activityOptions != nil {
		ao = *o.activityOptions
	}

	if ao.HeartbeatTimeout == 0 {
		ao.HeartbeatTimeout = 30000000000 // 30 seconds
	}

	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 o.heartbeatInterval == 0 {
		o.heartbeatInterval = 10000000000 // 10 seconds
	}

	ctx = workflow.WithActivityOptions(ctx, ao)

	return ctx, &xnsv1.UpdateWithStartRequest{
		HeartbeatInterval:     durationpb.New(o.heartbeatInterval),
		Input:                 swreq.GetRequest(),
		ParentClosePolicy:     convert.ToParentClosePolicy(o.parentClosePolicy),
		StartWorkflowOptions:  swreq.GetStartWorkflowOptions(),
		Update:                ureq.GetRequest(),
		UpdateWorkflowOptions: ureq.GetUpdateWorkflowOptions(),
	}, nil
}

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

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

// WithParentClosePolicy can be used to customize the parent close policy for the workflow
func (o *TestWorkflowWithTestUpdateOptions) WithParentClosePolicy(p enumsv1.ParentClosePolicy) *TestWorkflowWithTestUpdateOptions {
	o.parentClosePolicy = p
	return o
}

// WithUpdateOptions can be used to customize the update options
func (o *TestWorkflowWithTestUpdateOptions) WithUpdateOptions(uo *TestUpdateUpdateOptions) *TestWorkflowWithTestUpdateOptions {
	o.updateOptions = uo
	return o
}

// WithWorkflowOptions can be used to customize the workflow options
func (o *TestWorkflowWithTestUpdateOptions) WithWorkflowOptions(wo *TestWorkflowWorkflowOptions) *TestWorkflowWithTestUpdateOptions {
	o.workflowOptions = wo
	return o
}

// TestWorkflowWithTestUpdate executes a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestUpdate update for a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestWorkflow workflow, starting it if necessary, and blocks until error or update is complete
func TestWorkflowWithTestUpdate(ctx workflow.Context, input *v1.TestWorkflowInput, update *v1.TestUpdateInput, options ...*TestWorkflowWithTestUpdateOptions) (*v1.TestUpdateOutput, TestWorkflowRun, error) {
	handle, run, err := TestWorkflowWithTestUpdateAsync(ctx, input, update, options...)
	if err != nil {
		return nil, run, err
	}
	if out, err := handle.Get(ctx); err != nil {
		return nil, run, err
	} else {
		return out, run, nil
	}
}

// TestWorkflowWithTestUpdateAsync executes a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestUpdate update for a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestWorkflow workflow, starting it if necessary, and returns a handle to the update and workflow execution
func TestWorkflowWithTestUpdateAsync(ctx workflow.Context, input *v1.TestWorkflowInput, update *v1.TestUpdateInput, options ...*TestWorkflowWithTestUpdateOptions) (TestUpdateHandle, TestWorkflowRun, error) {
	activityName := xnsHeartbeatServiceOptions.filterActivity("test.xnsheartbeat.v1.XnsHeartbeatService.TestWorkflowWithTestUpdate")
	if activityName == "" {
		return nil, nil, xnsHeartbeatServiceOptions.convertError(temporal.NewNonRetryableApplicationError(fmt.Sprintf("no activity registered for %s", activityName), "Unimplemented", nil))
	}
	var o *TestWorkflowWithTestUpdateOptions
	if len(options) > 0 && options[0] != nil {
		o = options[0]
	} else {
		o = NewTestWorkflowWithTestUpdateOptions()
	}
	ctx, req, err := o.Build(ctx, input, update)
	if err != nil {
		return nil, nil, xnsHeartbeatServiceOptions.convertError(err)
	}
	var parentClosePolicy enumsv1.ParentClosePolicy
	if p := req.GetParentClosePolicy(); p != temporalv1.ParentClosePolicy_PARENT_CLOSE_POLICY_UNSPECIFIED {
		parentClosePolicy = enumsv1.ParentClosePolicy(p)
	}
	ctx, cancel := workflow.WithCancel(ctx)
	handle := &testUpdateHandle{
		cancel: cancel,
		future: workflow.ExecuteActivity(ctx, activityName, req),
		id:     req.GetUpdateWorkflowOptions().GetUpdateId(),
	}
	run := &testWorkflowRun{
		cancel:            cancel,
		ctx:               ctx,
		heartbeatInterval: req.GetHeartbeatInterval().AsDuration(),
		id:                req.GetStartWorkflowOptions().GetId(),
		parentClosePolicy: parentClosePolicy,
	}
	return handle, run, nil
}

// TestSignalSignalOptions are used to configure a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestSignal signal execution
type TestSignalSignalOptions struct {
	ActivityOptions   *workflow.ActivityOptions
	HeartbeatInterval time.Duration
}

// NewTestSignalSignalOptions initializes a new TestSignalSignalOptions value
func NewTestSignalSignalOptions() *TestSignalSignalOptions {
	return &TestSignalSignalOptions{}
}

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

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

// TestSignalSignalHandle provides a handle for a test.xnsheartbeat.v1.XnsHeartbeatService.TestSignal signal activity
type TestSignalSignalHandle 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
}

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

// Cancel the underlying signal activity
func (r *testSignalSignalHandle) 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 *testSignalSignalHandle) Future() workflow.Future {
	return r.future
}

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

// TestSignal executes a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestSignal signal
func TestSignal(ctx workflow.Context, workflowID string, runID string, req *v1.TestSignalInput, opts ...*TestSignalSignalOptions) error {
	handle, err := TestSignalAsync(ctx, workflowID, runID, req, opts...)
	if err != nil {
		return err
	}
	return handle.Get(ctx)
}

// TestSignalAsync executes a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestSignal signal
func TestSignalAsync(ctx workflow.Context, workflowID string, runID string, req *v1.TestSignalInput, opts ...*TestSignalSignalOptions) (TestSignalSignalHandle, error) {
	activityName := xnsHeartbeatServiceOptions.filterActivity(v1.TestSignalSignalName)
	if activityName == "" {
		return nil, temporal.NewNonRetryableApplicationError(
			fmt.Sprintf("no activity registered for %s", v1.TestSignalSignalName),
			"Unimplemented",
			nil,
		)
	}

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

	if opt.HeartbeatInterval == 0 {
		opt.HeartbeatInterval = time.Second * 30
	}

	// configure activity options
	var ao workflow.ActivityOptions
	if opt.ActivityOptions != nil {
		ao = *opt.ActivityOptions
	} else {
		ao = workflow.ActivityOptions{}
	}
	if ao.HeartbeatTimeout == 0 {
		ao.HeartbeatTimeout = opt.HeartbeatInterval * 2
	}
	// 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 = 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 &testSignalSignalHandle{
		cancel: cancel,
		future: workflow.ExecuteActivity(ctx, activityName, &xnsv1.SignalRequest{
			HeartbeatInterval: durationpb.New(opt.HeartbeatInterval),
			WorkflowId:        workflowID,
			RunId:             runID,
			Request:           wreq,
		}),
	}, nil
}

// TestUpdateUpdateOptions are used to configure a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestUpdate update execution
type TestUpdateUpdateOptions struct {
	ActivityOptions       *workflow.ActivityOptions
	HeartbeatInterval     time.Duration
	UpdateWorkflowOptions *client.UpdateWorkflowOptions
}

// NewTestUpdateUpdateOptions initializes a new TestUpdateUpdateOptions value
func NewTestUpdateUpdateOptions() *TestUpdateUpdateOptions {
	return &TestUpdateUpdateOptions{}
}

// Build initializes the update options
func (opt *TestUpdateUpdateOptions) Build(ctx workflow.Context, workflowID string, runID string, input *v1.TestUpdateInput) (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 = 60000000000 // 1 minute
	}
	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 opt.HeartbeatInterval == 0 {
		opt.HeartbeatInterval = 30000000000 // 30 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 := 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 *TestUpdateUpdateOptions) WithActivityOptions(ao workflow.ActivityOptions) *TestUpdateUpdateOptions {
	opts.ActivityOptions = &ao
	return opts
}

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

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

// TestUpdateHandle provides a handle to a test.xnsheartbeat.v1.XnsHeartbeatService.TestUpdate workflow update
type TestUpdateHandle 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.TestUpdateOutput, error)

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

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

// Cancel the underlying workflow update
func (r *testUpdateHandle) 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 *testUpdateHandle) Future() workflow.Future {
	return r.future
}

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

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

// TestUpdate executes a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestUpdate update and blocks until error or response received
func TestUpdate(ctx workflow.Context, workflowID string, runID string, req *v1.TestUpdateInput, opts ...*TestUpdateUpdateOptions) (*v1.TestUpdateOutput, error) {
	run, err := TestUpdateAsync(ctx, workflowID, runID, req, opts...)
	if err != nil {
		return nil, err
	}
	return run.Get(ctx)
}

// TestUpdateAsync executes a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestUpdate update and blocks until error or response received
func TestUpdateAsync(ctx workflow.Context, workflowID string, runID string, input *v1.TestUpdateInput, opts ...*TestUpdateUpdateOptions) (TestUpdateHandle, error) {
	activityName := xnsHeartbeatServiceOptions.filterActivity(v1.TestUpdateUpdateName)
	if activityName == "" {
		return nil, temporal.NewNonRetryableApplicationError(
			fmt.Sprintf("no activity registered for %s", v1.TestUpdateUpdateName),
			"Unimplemented",
			nil,
		)
	}

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

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

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

// CancelXnsHeartbeatServiceWorkflowAsync cancels an existing workflow
func CancelXnsHeartbeatServiceWorkflowAsync(ctx workflow.Context, workflowID string, runID string) workflow.Future {
	activityName := xnsHeartbeatServiceOptions.filterActivity("test.xnsheartbeat.v1.XnsHeartbeatService.CancelWorkflow")
	if activityName == "" {
		f, s := workflow.NewFuture(ctx)
		s.SetError(temporal.NewNonRetryableApplicationError(
			"no activity registered for test.xnsheartbeat.v1.XnsHeartbeatService.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)
}

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

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

// GetTestWorkflow retrieves a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestWorkflow workflow via an activity
func (a *xnsHeartbeatServiceActivities) GetTestWorkflow(ctx context.Context, input *xnsv1.GetWorkflowRequest) (out *v1.TestWorkflowOutput, err error) {
	heartbeatInterval := input.GetHeartbeatInterval().AsDuration()
	if heartbeatInterval == 0 {
		heartbeatInterval = time.Second * 30
	}

	actx, cancel := context.WithCancel(context.Background())
	defer cancel()
	run := a.client.GetTestWorkflow(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, xnsHeartbeatServiceOptions.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, xnsHeartbeatServiceOptions.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, xnsHeartbeatServiceOptions.convertError(err)
					}
				}
				return nil, xnsHeartbeatServiceOptions.convertError(temporal.NewCanceledError(ctx.Err().Error()))
			}

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

// TestWorkflow executes a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestWorkflow workflow via an activity
func (a *xnsHeartbeatServiceActivities) TestWorkflow(ctx context.Context, input *xnsv1.WorkflowRequest) (resp *v1.TestWorkflowOutput, err error) {
	// unmarshal workflow request
	var req v1.TestWorkflowInput
	if err := input.Request.UnmarshalTo(&req); err != nil {
		return nil, xnsHeartbeatServiceOptions.convertError(temporal.NewNonRetryableApplicationError(
			fmt.Sprintf("error unmarshalling workflow request of type %s as github.com/cludden/protoc-gen-go-temporal/gen/test/xnsheartbeat/v1.TestWorkflowInput", 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.TestWorkflowRun
	run, err = a.client.TestWorkflowAsync(actx, &req, v1.NewTestWorkflowOptions().WithStartWorkflowOptions(
		xns.UnmarshalStartWorkflowOptions(input.GetStartWorkflowOptions()),
	))
	if err != nil {
		return nil, xnsHeartbeatServiceOptions.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, xnsHeartbeatServiceOptions.convertError(err)
					}
				}
				return nil, xnsHeartbeatServiceOptions.convertError(temporal.NewCanceledError(ctx.Err().Error()))
			}

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

// TestWorkflowWithTestUpdate executes a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestWorkflow workflow with a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestUpdate update via an activity
func (a *xnsHeartbeatServiceActivities) TestWorkflowWithTestUpdate(ctx context.Context, input *xnsv1.UpdateWithStartRequest) (out *v1.TestUpdateOutput, err error) {
	// unmarshal workflow request
	var req v1.TestWorkflowInput
	if err := input.GetInput().UnmarshalTo(&req); err != nil {
		return nil, xnsHeartbeatServiceOptions.convertError(temporal.NewNonRetryableApplicationError(
			fmt.Sprintf("error unmarshalling workflow request of type %s as github.com/cludden/protoc-gen-go-temporal/gen/test/xnsheartbeat/v1.TestWorkflowInput", input.GetInput().GetTypeUrl()),
			"InvalidArgument",
			err,
		))
	}

	// unmarshal update request
	var update v1.TestUpdateInput
	if err := input.GetUpdate().UnmarshalTo(&update); err != nil {
		return nil, xnsHeartbeatServiceOptions.convertError(temporal.NewNonRetryableApplicationError(
			fmt.Sprintf("error unmarshalling update request of type %s as github.com/cludden/protoc-gen-go-temporal/gen/test/xnsheartbeat/v1.TestUpdateInput", input.GetUpdate().GetTypeUrl()),
			"InvalidArgument",
			err,
		))
	}

	// unmarshal workflow and update options
	swo := xns.UnmarshalStartWorkflowOptions(input.GetStartWorkflowOptions())
	uwo := xns.UnmarshalUpdateWorkflowOptions(input.GetUpdateWorkflowOptions())

	var run v1.TestWorkflowRun
	var handle v1.TestUpdateHandle
	if activity.HasHeartbeatDetails(ctx) {
		// attach to existing update and execution
		var workflowID, runID, updateID string
		if err := activity.GetHeartbeatDetails(ctx, &workflowID, &runID, &updateID); err != nil {
			return nil, xnsHeartbeatServiceOptions.convertError(fmt.Errorf("error getting heartbeat details: %w", err))
		} else if workflowID == "" || runID == "" || updateID == "" {
			return nil, xnsHeartbeatServiceOptions.convertError(fmt.Errorf("invalid heartbeat details: workflowID=%q runID=%q updateID=%s", workflowID, runID, updateID))
		}
		run = a.client.GetTestWorkflow(ctx, workflowID, runID)
		handle, err = a.client.GetTestUpdate(ctx, client.GetWorkflowUpdateHandleOptions{
			RunID:      runID,
			UpdateID:   updateID,
			WorkflowID: workflowID,
		})
		if err != nil {
			return nil, xnsHeartbeatServiceOptions.convertError(fmt.Errorf("error getting update with id %s: %w", updateID, err))
		}
	} else {
		// execute update with start asynchronously
		handle, run, err = a.client.TestWorkflowWithTestUpdateAsync(
			ctx,
			&req,
			&update,
			v1.NewTestWorkflowWithTestUpdateOptions().WithTestWorkflowOptions(
				v1.NewTestWorkflowOptions().WithStartWorkflowOptions(swo),
			).WithTestUpdateOptions(
				v1.NewTestUpdateOptions().WithUpdateWorkflowOptions(uwo).WithWaitPolicy(client.WorkflowUpdateStageAccepted),
			),
		)
		if err != nil {
			return nil, xnsHeartbeatServiceOptions.convertError(fmt.Errorf("error executing update with start: %w", err))
		}
		activity.RecordHeartbeat(ctx, run.ID(), run.RunID(), handle.UpdateID())
	}

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

	// initialize heartbeat interval duration
	heartbeatInterval := input.GetHeartbeatInterval().AsDuration()
	if heartbeatInterval == 0 {
		heartbeatTimeout := activity.GetInfo(ctx).HeartbeatTimeout
		if heartbeatTimeout > 0 {
			heartbeatInterval = heartbeatTimeout / 2
		} else {
			heartbeatInterval = time.Second * 30
		}
	}

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

	// heartbeat activity while waiting for update to complete
	for {
		select {
		case <-time.After(heartbeatInterval):
			activity.RecordHeartbeat(ctx, run.ID(), run.RunID(), handle.UpdateID())

		case <-activity.GetWorkerStopChannel(ctx):
			return nil, xnsHeartbeatServiceOptions.convertError(temporal.NewApplicationError("worker is stopping", "WorkerStopping"))

		// 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, xnsHeartbeatServiceOptions.convertError(temporal.NewApplicationError("worker is stopping", "WorkerStopping"))
			default:
				parentClosePolicy := input.GetParentClosePolicy()
				if parentClosePolicy == temporalv1.ParentClosePolicy_PARENT_CLOSE_POLICY_REQUEST_CANCEL || parentClosePolicy == temporalv1.ParentClosePolicy_PARENT_CLOSE_POLICY_TERMINATE {
					disconnectedCtx, cancel := context.WithTimeout(ctx, 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, xnsHeartbeatServiceOptions.convertError(err)
					}
				}
				return nil, xnsHeartbeatServiceOptions.convertError(temporal.NewCanceledError(ctx.Err().Error()))
			}

		case <-doneCh:
			return out, xnsHeartbeatServiceOptions.convertError(err)
		}
	}
}

// TestSignal executes a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestSignal signal via an activity
func (a *xnsHeartbeatServiceActivities) TestSignal(ctx context.Context, input *xnsv1.SignalRequest) (err error) {
	// unmarshal signal request
	var req v1.TestSignalInput
	if err := input.Request.UnmarshalTo(&req); err != nil {
		return xnsHeartbeatServiceOptions.convertError(temporal.NewNonRetryableApplicationError(
			fmt.Sprintf("error unmarshalling signal request of type %s as github.com/cludden/protoc-gen-go-temporal/gen/test/xnsheartbeat/v1.TestSignalInput", input.Request.GetTypeUrl()),
			"InvalidArgument",
			err,
		))
	}
	// execute signal in child goroutine
	doneCh := make(chan struct{})
	go func() {
		err = a.client.TestSignal(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():
			xnsHeartbeatServiceOptions.convertError(ctx.Err())
		case <-doneCh:
			return xnsHeartbeatServiceOptions.convertError(err)
		}
	}
}

// TestUpdate executes a(n) test.xnsheartbeat.v1.XnsHeartbeatService.TestUpdate update via an activity
func (a *xnsHeartbeatServiceActivities) TestUpdate(ctx context.Context, input *xnsv1.UpdateRequest) (resp *v1.TestUpdateOutput, err error) {
	var handle v1.TestUpdateHandle
	if activity.HasHeartbeatDetails(ctx) {
		// extract update id from heartbeat details
		var updateID string
		if err := activity.GetHeartbeatDetails(ctx, &updateID); err != nil {
			return nil, xnsHeartbeatServiceOptions.convertError(err)
		}

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

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

		// initialize update execution
		handle, err = a.client.TestUpdateAsync(
			ctx,
			input.GetUpdateWorkflowOptions().GetWorkflowId(),
			input.GetUpdateWorkflowOptions().GetRunId(),
			&req,
			v1.NewTestUpdateOptions().WithUpdateWorkflowOptions(uo),
		)
		if err != nil {
			return nil, xnsHeartbeatServiceOptions.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, xnsHeartbeatServiceOptions.convertError(ctx.Err())
		case <-doneCh:
			return resp, xnsHeartbeatServiceOptions.convertError(err)
		}
	}
}

// XnsHeartbeatCallerServiceOptions is used to configure test.xnsheartbeat.v1.XnsHeartbeatCallerService xns activity registration
type XnsHeartbeatCallerServiceOptions 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
}

// NewXnsHeartbeatCallerServiceOptions initializes a new XnsHeartbeatCallerServiceOptions value
func NewXnsHeartbeatCallerServiceOptions() *XnsHeartbeatCallerServiceOptions {
	return &XnsHeartbeatCallerServiceOptions{}
}

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

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

// convertError is applied to all xns activity errors
func (opts *XnsHeartbeatCallerServiceOptions) 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 *XnsHeartbeatCallerServiceOptions) filterActivity(name string) string {
	if opts == nil || opts.filter == nil {
		return name
	}
	return opts.filter(name)
}

// xnsHeartbeatCallerServiceOptions is a reference to the XnsHeartbeatCallerServiceOptions initialized at registration
var xnsHeartbeatCallerServiceOptions *XnsHeartbeatCallerServiceOptions

// RegisterXnsHeartbeatCallerServiceActivities registers test.xnsheartbeat.v1.XnsHeartbeatCallerService cross-namespace activities
func RegisterXnsHeartbeatCallerServiceActivities(r worker.ActivityRegistry, c v1.XnsHeartbeatCallerServiceClient, options ...*XnsHeartbeatCallerServiceOptions) {
	if xnsHeartbeatCallerServiceOptions == nil && len(options) > 0 && options[0] != nil {
		xnsHeartbeatCallerServiceOptions = options[0]
	}
	a := &xnsHeartbeatCallerServiceActivities{c}
	if name := xnsHeartbeatCallerServiceOptions.filterActivity("test.xnsheartbeat.v1.XnsHeartbeatCallerService.CancelWorkflow"); name != "" {
		r.RegisterActivityWithOptions(a.CancelWorkflow, activity.RegisterOptions{Name: name})
	}
	if name := xnsHeartbeatCallerServiceOptions.filterActivity(v1.CallTestWorkflowWorkflowName); name != "" {
		r.RegisterActivityWithOptions(a.CallTestWorkflow, activity.RegisterOptions{Name: name})
	}
	if name := xnsHeartbeatCallerServiceOptions.filterActivity("test.xnsheartbeat.v1.XnsHeartbeatCallerService.GetCallTestWorkflow"); name != "" {
		r.RegisterActivityWithOptions(a.GetCallTestWorkflow, activity.RegisterOptions{Name: name})
	}
}

// CallTestWorkflowWorkflowOptions are used to configure a(n) test.xnsheartbeat.v1.XnsHeartbeatCallerService.CallTestWorkflow workflow execution
type CallTestWorkflowWorkflowOptions struct {
	ActivityOptions      *workflow.ActivityOptions
	Detached             bool
	HeartbeatInterval    time.Duration
	HeartbeatTimeout     time.Duration
	ParentClosePolicy    enumsv1.ParentClosePolicy
	StartWorkflowOptions *client.StartWorkflowOptions
}

// NewCallTestWorkflowWorkflowOptions initializes a new CallTestWorkflowWorkflowOptions value
func NewCallTestWorkflowWorkflowOptions() *CallTestWorkflowWorkflowOptions {
	return &CallTestWorkflowWorkflowOptions{}
}

// Build initializes the activity context and input
func (opts *CallTestWorkflowWorkflowOptions) Build(ctx workflow.Context) (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 := 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 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,
		StartWorkflowOptions: swopb,
	}, nil
}

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

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

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

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

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

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

// CallTestWorkflowRun provides a handle to a test.xnsheartbeat.v1.XnsHeartbeatCallerService.CallTestWorkflow workflow execution
type CallTestWorkflowRun 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

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

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

// Cancel the underlying workflow execution
func (r *callTestWorkflowRun) 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 CancelXnsHeartbeatCallerServiceWorkflow(ctx, r.id, "")
}

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

// Get blocks on activity completion and returns the underlying workflow result
func (r *callTestWorkflowRun) Get(ctx workflow.Context) error {
	ctx, cancel := workflow.WithCancel(ctx)
	if r.future == nil {
		rr := GetCallTestWorkflowAsync(ctx, r.id, "", NewGetCallTestWorkflowOptions().WithParentClosePolicy(r.parentClosePolicy).WithHeartbeatInterval(r.heartbeatInterval)).(*callTestWorkflowRun)
		r.future = rr.future
		r.cancel = cancel
	}
	if err := r.future.Get(ctx, nil); err != nil {
		return err
	}
	return nil
}

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

// CallTestWorkflow executes a(n) test.xnsheartbeat.v1.XnsHeartbeatCallerService.CallTestWorkflow workflow and blocks until error or response is received
func CallTestWorkflow(ctx workflow.Context, opts ...*CallTestWorkflowWorkflowOptions) error {
	run, err := CallTestWorkflowAsync(ctx, opts...)
	if err != nil {
		return err
	}
	return run.Get(ctx)
}

// CallTestWorkflowAsync executes a(n) test.xnsheartbeat.v1.XnsHeartbeatCallerService.CallTestWorkflow workflow and returns a handle to the underlying activity
func CallTestWorkflowAsync(ctx workflow.Context, opts ...*CallTestWorkflowWorkflowOptions) (CallTestWorkflowRun, error) {
	activityName := xnsHeartbeatCallerServiceOptions.filterActivity(v1.CallTestWorkflowWorkflowName)
	if activityName == "" {
		return nil, temporal.NewNonRetryableApplicationError(
			fmt.Sprintf("no activity registered for %s", v1.CallTestWorkflowWorkflowName),
			"Unimplemented",
			nil,
		)
	}

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

// GetCallTestWorkflow returns a(n) test.xnsheartbeat.v1.XnsHeartbeatCallerService.CallTestWorkflow workflow execution
func GetCallTestWorkflow(ctx workflow.Context, workflowID string, runID string, options ...*GetCallTestWorkflowOptions) (err error) {
	err = GetCallTestWorkflowAsync(ctx, workflowID, runID, options...).Get(ctx)
	if err != nil {
		return err
	}
	return nil
}

// GetCallTestWorkflowAsync returns a handle to a(n) test.xnsheartbeat.v1.XnsHeartbeatCallerService.CallTestWorkflow workflow execution
func GetCallTestWorkflowAsync(ctx workflow.Context, workflowID string, runID string, options ...*GetCallTestWorkflowOptions) CallTestWorkflowRun {
	activityName := xnsHeartbeatCallerServiceOptions.filterActivity("test.xnsheartbeat.v1.XnsHeartbeatCallerService.GetCallTestWorkflow")
	if activityName == "" {
		f, set := workflow.NewFuture(ctx)
		set.SetError(temporal.NewNonRetryableApplicationError(fmt.Sprintf("no activity registered for %s", activityName), "Unimplemented", nil))
		return &callTestWorkflowRun{
			future: f,
			id:     workflowID,
		}
	}
	var opt *GetCallTestWorkflowOptions
	if len(options) > 0 && options[0] != nil {
		opt = options[0]
	} else {
		opt = NewGetCallTestWorkflowOptions()
	}
	ctx, req, err := opt.Build(ctx, workflowID, runID)
	if err != nil {
		f, set := workflow.NewFuture(ctx)
		set.SetError(xnsHeartbeatCallerServiceOptions.convertError(temporal.NewNonRetryableApplicationError(fmt.Sprintf("no activity registered for %s", activityName), "Unimplemented", nil)))
		return &callTestWorkflowRun{
			future: f,
			id:     workflowID,
		}
	}
	ctx, cancel := workflow.WithCancel(ctx)
	return &callTestWorkflowRun{
		cancel: cancel,
		future: workflow.ExecuteActivity(ctx, activityName, req),
		id:     workflowID,
	}
}

// GetCallTestWorkflowOptions are used to configure a(n) test.xnsheartbeat.v1.XnsHeartbeatCallerService.CallTestWorkflow workflow execution getter activity
type GetCallTestWorkflowOptions struct {
	activityOptions   *workflow.ActivityOptions
	heartbeatInterval time.Duration
	parentClosePolicy enumsv1.ParentClosePolicy
}

// NewGetCallTestWorkflowOptions initializes a new GetCallTestWorkflowOptions value
func NewGetCallTestWorkflowOptions() *GetCallTestWorkflowOptions {
	return &GetCallTestWorkflowOptions{}
}

// Build initializes the activity context and input
func (opt *GetCallTestWorkflowOptions) 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 *GetCallTestWorkflowOptions) WithActivityOptions(ao workflow.ActivityOptions) *GetCallTestWorkflowOptions {
	o.activityOptions = &ao
	return o
}

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

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

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

// CancelXnsHeartbeatCallerServiceWorkflowAsync cancels an existing workflow
func CancelXnsHeartbeatCallerServiceWorkflowAsync(ctx workflow.Context, workflowID string, runID string) workflow.Future {
	activityName := xnsHeartbeatCallerServiceOptions.filterActivity("test.xnsheartbeat.v1.XnsHeartbeatCallerService.CancelWorkflow")
	if activityName == "" {
		f, s := workflow.NewFuture(ctx)
		s.SetError(temporal.NewNonRetryableApplicationError(
			"no activity registered for test.xnsheartbeat.v1.XnsHeartbeatCallerService.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)
}

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

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

// GetCallTestWorkflow retrieves a(n) test.xnsheartbeat.v1.XnsHeartbeatCallerService.CallTestWorkflow workflow via an activity
func (a *xnsHeartbeatCallerServiceActivities) GetCallTestWorkflow(ctx context.Context, input *xnsv1.GetWorkflowRequest) (err error) {
	heartbeatInterval := input.GetHeartbeatInterval().AsDuration()
	if heartbeatInterval == 0 {
		heartbeatInterval = time.Second * 30
	}

	actx, cancel := context.WithCancel(context.Background())
	defer cancel()
	run := a.client.GetCallTestWorkflow(actx, input.GetWorkflowId(), input.GetRunId())
	done := make(chan struct{})
	go func() {
		defer close(done)
		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 xnsHeartbeatCallerServiceOptions.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 xnsHeartbeatCallerServiceOptions.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 xnsHeartbeatCallerServiceOptions.convertError(err)
					}
				}
				return xnsHeartbeatCallerServiceOptions.convertError(temporal.NewCanceledError(ctx.Err().Error()))
			}

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

// CallTestWorkflow executes a(n) test.xnsheartbeat.v1.XnsHeartbeatCallerService.CallTestWorkflow workflow via an activity
func (a *xnsHeartbeatCallerServiceActivities) CallTestWorkflow(ctx context.Context, input *xnsv1.WorkflowRequest) (err error) {
	// initialize workflow execution
	actx := ctx
	if !input.GetDetached() {
		var cancel context.CancelFunc
		actx, cancel = context.WithCancel(context.Background())
		defer cancel()
	}
	var run v1.CallTestWorkflowRun
	run, err = a.client.CallTestWorkflowAsync(actx, v1.NewCallTestWorkflowOptions().WithStartWorkflowOptions(
		xns.UnmarshalStartWorkflowOptions(input.GetStartWorkflowOptions()),
	))
	if err != nil {
		return xnsHeartbeatCallerServiceOptions.convertError(err)
	}

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

	// otherwise, wait for execution to complete in child goroutine
	doneCh := make(chan struct{})
	go func() {
		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 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 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 xnsHeartbeatCallerServiceOptions.convertError(err)
					}
				}
				return xnsHeartbeatCallerServiceOptions.convertError(temporal.NewCanceledError(ctx.Err().Error()))
			}

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