@@ -27,6 +27,7 @@ package internal
27
27
import (
28
28
"context"
29
29
"crypto/tls"
30
+ "errors"
30
31
"fmt"
31
32
"sync/atomic"
32
33
"time"
@@ -643,9 +644,23 @@ type (
643
644
// Optional: defaulted to Fail.
644
645
WorkflowIDConflictPolicy enumspb.WorkflowIdConflictPolicy
645
646
647
+ // WithStartOperation - Operation to execute with Workflow Start.
648
+ // For example, see NewUpdateWithStartWorkflowOperation to perform Update-with-Start. Note that if the workflow is
649
+ // already running and WorkflowIDConflictPolicy is set to UseExisting, the start is skipped and only the
650
+ // operation is executed. If instead the policy is set to Fail (the default), nothing is executed and
651
+ // an error will be returned (i.e. the option WorkflowExecutionErrorWhenAlreadyStarted is ignored).
652
+ // This option will be ignored when used with Client.SignalWithStartWorkflow.
653
+ //
654
+ // Optional: defaults to nil.
655
+ //
656
+ // NOTE: Experimental
657
+ WithStartOperation WithStartWorkflowOperation
658
+
646
659
// When WorkflowExecutionErrorWhenAlreadyStarted is true, Client.ExecuteWorkflow will return an error if the
647
- // workflow id has already been used and WorkflowIDReusePolicy would disallow a re-run. If it is set to false,
648
- // rather than erroring a WorkflowRun instance representing the current or last run will be returned.
660
+ // workflow id has already been used and WorkflowIDReusePolicy or WorkflowIDConflictPolicy would
661
+ // disallow a re-run. If it is set to false, rather than erroring a WorkflowRun instance representing
662
+ // the current or last run will be returned. However, when WithStartOperation is set, this field is ignored and
663
+ // the WorkflowIDConflictPolicy UseExisting must be used instead to prevent erroring.
649
664
//
650
665
// Optional: defaults to false
651
666
WorkflowExecutionErrorWhenAlreadyStarted bool
@@ -714,6 +729,24 @@ type (
714
729
links []* commonpb.Link
715
730
}
716
731
732
+ // WithStartWorkflowOperation is a type of operation that can be executed as part of a workflow start.
733
+ WithStartWorkflowOperation interface {
734
+ isWithStartWorkflowOperation ()
735
+ }
736
+
737
+ // UpdateWithStartWorkflowOperation is used to perform Update-with-Start.
738
+ // See NewUpdateWithStartWorkflowOperation for details.
739
+ UpdateWithStartWorkflowOperation struct {
740
+ input * ClientUpdateWorkflowInput
741
+ // flag to ensure the operation is only executed once
742
+ executed atomic.Bool
743
+ // channel to indicate that handle or err is available
744
+ doneCh chan struct {}
745
+ // handle and err cannot be accessed before doneCh is closed
746
+ handle WorkflowUpdateHandle
747
+ err error
748
+ }
749
+
717
750
// RetryPolicy defines the retry policy.
718
751
// Note that the history of activity with retry policy will be different: the started event will be written down into
719
752
// history only when the activity completes or "finally" timeouts/fails. And the started event only records the last
@@ -1004,6 +1037,50 @@ func DialCloudOperationsClient(ctx context.Context, options CloudOperationsClien
1004
1037
}, nil
1005
1038
}
1006
1039
1040
+ // NewUpdateWithStartWorkflowOperation returns an UpdateWithStartWorkflowOperation that can be used to perform Update-with-Start.
1041
+ func NewUpdateWithStartWorkflowOperation (options UpdateWorkflowOptions ) * UpdateWithStartWorkflowOperation {
1042
+ res := & UpdateWithStartWorkflowOperation {doneCh : make (chan struct {})}
1043
+
1044
+ input , err := createUpdateWorkflowInput (options )
1045
+ if err != nil {
1046
+ res .set (nil , err )
1047
+ } else if options .RunID != "" {
1048
+ res .set (nil , errors .New ("RunID cannot be set because the workflow might not be running" ))
1049
+ }
1050
+ if options .FirstExecutionRunID != "" {
1051
+ res .set (nil , errors .New ("FirstExecutionRunID cannot be set because the workflow might not be running" ))
1052
+ } else {
1053
+ res .input = input
1054
+ }
1055
+
1056
+ return res
1057
+ }
1058
+
1059
+ // Get blocks until a server response has been received; or the context deadline is exceeded.
1060
+ func (op * UpdateWithStartWorkflowOperation ) Get (ctx context.Context ) (WorkflowUpdateHandle , error ) {
1061
+ select {
1062
+ case <- op .doneCh :
1063
+ return op .handle , op .err
1064
+ case <- ctx .Done ():
1065
+ return nil , ctx .Err ()
1066
+ }
1067
+ }
1068
+
1069
+ func (op * UpdateWithStartWorkflowOperation ) markExecuted () error {
1070
+ if op .executed .Swap (true ) {
1071
+ return fmt .Errorf ("was already executed" )
1072
+ }
1073
+ return nil
1074
+ }
1075
+
1076
+ func (op * UpdateWithStartWorkflowOperation ) set (handle WorkflowUpdateHandle , err error ) {
1077
+ op .handle = handle
1078
+ op .err = err
1079
+ close (op .doneCh )
1080
+ }
1081
+
1082
+ func (op * UpdateWithStartWorkflowOperation ) isWithStartWorkflowOperation () {}
1083
+
1007
1084
// NewNamespaceClient creates an instance of a namespace client, to manager lifecycle of namespaces.
1008
1085
func NewNamespaceClient (options ClientOptions ) (NamespaceClient , error ) {
1009
1086
// Initialize root tags
0 commit comments