go.uber.org/cadence@v1.2.9/internal/workflow.go (about)

     1  // Copyright (c) 2017-2020 Uber Technologies Inc.
     2  // Portions of the Software are attributed to Copyright (c) 2020 Temporal Technologies Inc.
     3  //
     4  // Permission is hereby granted, free of charge, to any person obtaining a copy
     5  // of this software and associated documentation files (the "Software"), to deal
     6  // in the Software without restriction, including without limitation the rights
     7  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     8  // copies of the Software, and to permit persons to whom the Software is
     9  // furnished to do so, subject to the following conditions:
    10  //
    11  // The above copyright notice and this permission notice shall be included in
    12  // all copies or substantial portions of the Software.
    13  //
    14  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    15  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    16  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    17  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    18  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    19  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    20  // THE SOFTWARE.
    21  
    22  package internal
    23  
    24  import (
    25  	"errors"
    26  	"fmt"
    27  	"reflect"
    28  	"strings"
    29  	"time"
    30  
    31  	"github.com/uber-go/tally"
    32  	"go.uber.org/zap"
    33  
    34  	s "go.uber.org/cadence/.gen/go/shared"
    35  	"go.uber.org/cadence/internal/common"
    36  	"go.uber.org/cadence/internal/common/backoff"
    37  )
    38  
    39  var (
    40  	errDomainNotSet                  = errors.New("domain is not set")
    41  	errTaskListNotSet                = errors.New("task list is not set")
    42  	errWorkflowIDNotSet              = errors.New("workflowId is not set")
    43  	errLocalActivityParamsBadRequest = errors.New("missing local activity parameters through context, check LocalActivityOptions")
    44  	errActivityParamsBadRequest      = errors.New("missing activity parameters through context, check ActivityOptions")
    45  	errWorkflowOptionBadRequest      = errors.New("missing workflow options through context, check WorkflowOptions")
    46  	errSearchAttributesNotSet        = errors.New("search attributes is empty")
    47  )
    48  
    49  type (
    50  	// Channel must be used in workflows instead of a native Go chan.
    51  	//
    52  	// Use workflow.NewChannel(ctx) to create an unbuffered Channel instance,
    53  	// workflow.NewBufferedChannel(ctx, size) to create a Channel which has a buffer,
    54  	// or workflow.GetSignalChannel(ctx, "name") to get a Channel that contains data sent to this workflow by a call to
    55  	// SignalWorkflow (e.g. on the Client, or similar methods like SignalExternalWorkflow or SignalChildWorkflow).
    56  	//
    57  	// Both NewChannel and NewBufferedChannel have "Named" constructors as well.
    58  	// These names will be visible in stack-trace queries, so they can help with debugging, but they do not otherwise
    59  	// impact behavior at all, and are not recorded anywhere (so you can change them without versioning your code).
    60  	//
    61  	// Also note that channels created by NewChannel and NewBufferedChannel do not do any serialization or
    62  	// deserialization - you will receive whatever value was sent, and non-(de)serializable values like function
    63  	// references and interfaces are fine, the same as using a normal Go channel.
    64  	//
    65  	// Signal channels, however, contain whatever bytes were sent to your workflow, and the values must be decoded into
    66  	// the output value.  By default, this means that Receive(ctx, &out) will use json.Unmarshal(data, &out), but this
    67  	// can be overridden at a worker level (worker.Options) or at a context level (workflow.WithDataConverter(ctx, dc)).
    68  	//
    69  	// You are able to send values to your own signal channels, and these values will behave the same as they do in
    70  	// normal channels (i.e. they will not be (de)serialized).  However, doing so is not generally recommended, as
    71  	// mixing the value types can increase the risk that you fail to read a value, causing values to be lost.  See
    72  	// Receive for more details about that behavior.
    73  	Channel interface {
    74  		// Receive blocks until it receives a value, and then assigns the received value to the provided pointer.
    75  		// It returns false when the Channel is closed and all data has already been consumed from the Channel, in the
    76  		// same way as Go channel reads work, but the assignment only occurs if there was a value in the Channel.
    77  		//
    78  		// This is technically equivalent to:
    79  		//  received, ok := <- aChannel:
    80  		//  if ok {
    81  		//  	*valuePtr = received
    82  		//  }
    83  		//
    84  		// But if your output values are zero values, this is equivalent to a normal channel read:
    85  		//  value, ok <- aChannel
    86  		//
    87  		// valuePtr must be assignable, and will be used to assign (for in-memory data in regular channels) or decode
    88  		// (for signal channels) the data in the channel.
    89  		//
    90  		// If decoding or assigning fails:
    91  		// - an error will be logged
    92  		// - the value will be dropped from the channel
    93  		// - Receive will automatically try again
    94  		// - This will continue until a successful value is found, or the channel is emptied and it resumes blocking.
    95  		//   Closed channels with no values will always succeed, but they will not change valuePtr.
    96  		//
    97  		// Go would normally prevent incorrect-type failures like this at compile time, but the same cannot be done
    98  		// here.  If you need to "try" to assign to multiple things, similar to a Future you can use:
    99  		// - for signal channels, a []byte pointer.  This will give you the raw data that Cadence received, and no
   100  		//   decoding will be attempted, so you can try it yourself.
   101  		// - for other channels, an interface{} pointer.  All values are interfaces, so this will never fail, and you
   102  		//   can inspect the type with reflection or type assertions.
   103  		Receive(ctx Context, valuePtr interface{}) (ok bool)
   104  
   105  		// ReceiveAsync tries to Receive from Channel without blocking.
   106  		// If there is data available from the Channel, it assigns the data to valuePtr and returns true.
   107  		// Otherwise, it returns false immediately.
   108  		//
   109  		// This is technically equivalent to:
   110  		//  select {
   111  		//  case received, ok := <- aChannel:
   112  		//  	if ok {
   113  		//  		*valuePtr = received
   114  		//  	}
   115  		//  default:
   116  		//  	// no value was read
   117  		//  	ok = false
   118  		//  }
   119  		//
   120  		// But if your output values are zero values, this is equivalent to a simpler form:
   121  		//  select {
   122  		//  case value, ok := <- aChannel:
   123  		//  default:
   124  		//  	// no value was read
   125  		//  	ok = false
   126  		//  }
   127  		//
   128  		// Decoding or assigning failures are handled like Receive.
   129  		ReceiveAsync(valuePtr interface{}) (ok bool)
   130  
   131  		// ReceiveAsyncWithMoreFlag is the same as ReceiveAsync, with an extra return to indicate if there could be
   132  		// more values from the Channel in the future.
   133  		// `more` is false only when Channel is closed and the read failed (empty).
   134  		//
   135  		// This is technically equivalent to:
   136  		//  select {
   137  		//  case received, ok := <- aChannel:
   138  		//  	if ok {
   139  		//  		*valuePtr = received
   140  		//  	}
   141  		//  	more = ok
   142  		//  default:
   143  		//  	// no value was read
   144  		//  	ok = false
   145  		//  	// but the read would have blocked, so the channel is not closed
   146  		//  	more = true
   147  		//  }
   148  		//
   149  		// But if your output values are zero values, this is equivalent to a simpler form:
   150  		//  select {
   151  		//  case value, ok := <- aChannel:
   152  		//  	more = ok
   153  		//  default:
   154  		//  	// no value was read
   155  		//  	ok = false
   156  		//  	// but the read would have blocked, so the channel is not closed
   157  		//  	more = true
   158  		//  }
   159  		//
   160  		// Decoding or assigning failures are handled like Receive.
   161  		ReceiveAsyncWithMoreFlag(valuePtr interface{}) (ok bool, more bool)
   162  
   163  		// Send blocks until the data is sent.
   164  		//
   165  		// This is equivalent to `aChannel <- v`.
   166  		Send(ctx Context, v interface{})
   167  
   168  		// SendAsync will try to send without blocking.
   169  		// It returns true if the data was sent (i.e. there was room in the buffer, or a reader was waiting to receive
   170  		// it), otherwise it returns false.
   171  		//
   172  		// This is equivalent to:
   173  		//  select {
   174  		//  case aChannel <- v: ok = true
   175  		//  default: ok = false
   176  		//  }
   177  		SendAsync(v interface{}) (ok bool)
   178  
   179  		// Close closes the Channel, and prohibits subsequent sends.
   180  		// As with a normal Go channel that has been closed, sending to a closed channel will panic.
   181  		Close()
   182  	}
   183  
   184  	// Selector must be used in workflows instead of a native Go select statement.
   185  	//
   186  	// Use workflow.NewSelector(ctx) to create a Selector instance, and then add cases to it with its methods.
   187  	// The interface is intended to simulate Go's select statement, and any Go select can be fairly trivially rewritten
   188  	// for a Selector with effectively identical behavior.
   189  	//
   190  	// For example, normal Go code like below (which will receive values forever, until idle for an hour):
   191  	//  chA := make(chan int)
   192  	//  chB := make(chan int)
   193  	//  counter := 0
   194  	//  for {
   195  	//  	select {
   196  	//  	case x := <- chA:
   197  	//  		counter += i
   198  	//  	case y := <- chB:
   199  	//  		counter += i
   200  	//  	case <- time.After(time.Hour):
   201  	//  		break
   202  	//  	}
   203  	//  }
   204  	// can be written as:
   205  	//  chA := workflow.NewChannel(ctx)
   206  	//  chB := workflow.NewChannel(ctx)
   207  	//  counter := 0
   208  	//  for {
   209  	//  	timedout := false
   210  	//  	s := workflow.NewSelector(ctx)
   211  	//  	s.AddReceive(chA, func(c workflow.Channel, more bool) {
   212  	//  		var x int
   213  	//  		c.Receive(ctx, &x)
   214  	//  		counter += i
   215  	//  	})
   216  	//  	s.AddReceive(chB, func(c workflow.Channel, more bool) {
   217  	//  		var y int
   218  	//  		c.Receive(ctx, &y)
   219  	//  		counter += i
   220  	//  	})
   221  	//  	s.AddFuture(workflow.NewTimer(ctx, time.Hour), func(f workflow.Future) {
   222  	//  		timedout = true
   223  	//  	})
   224  	//  	s.Select(ctx)
   225  	//  	if timedout {
   226  	//  		break
   227  	//  	}
   228  	//  }
   229  	//
   230  	// You can create a new Selector as needed or mutate one and call Select multiple times, but note that:
   231  	//
   232  	// 1. AddFuture will not behave the same across both patterns.  Read AddFuture for more details.
   233  	//
   234  	// 2. There is no way to remove a case from a Selector, so you must make a new Selector to "remove" them.
   235  	//
   236  	// Finally, note that Select will not return until a condition's needs are met, like a Go selector - canceling the
   237  	// Context used to construct the Selector, or the Context used to Select, will not (directly) unblock a Select call.
   238  	// Read Select for more details.
   239  	Selector interface {
   240  		// AddReceive waits until a value can be received from a channel.
   241  		// f is invoked when the channel has data or is closed.
   242  		//
   243  		// This is equivalent to `case v, ok := <- aChannel`, and `ok` will only be false when
   244  		// the channel is both closed and no data was received.
   245  		//
   246  		// When f is invoked, the data (or closed state) remains untouched in the channel, so
   247  		// you need to `c.Receive(ctx, &out)` (or `c.ReceiveAsync(&out)`) to remove and decode the value.
   248  		// Failure to do this is not an error - the value will simply remain in the channel until a future
   249  		// Receive retrieves it.
   250  		//
   251  		// The `ok` argument will match what a call to c.Receive would return (on a successful read), so it
   252  		// may be used to check for closed + empty channels without needing to try to read from the channel.
   253  		// See Channel.Receive for additional details about reading from channels.
   254  		AddReceive(c Channel, f func(c Channel, ok bool)) Selector
   255  		// AddSend waits to send a value to a channel.
   256  		// f is invoked when the value was successfully sent to the channel.
   257  		//
   258  		// This is equivalent to `case aChannel <- value`.
   259  		//
   260  		// Unlike AddReceive, the value has already been sent on the channel when f is invoked.
   261  		AddSend(c Channel, v interface{}, f func()) Selector
   262  		// AddFuture waits until a Future is ready, and then invokes f only once.
   263  		// If the Future is ready before Select is called, it is eligible to be invoked immediately.
   264  		//
   265  		// There is no direct equivalent in a native Go select statement.
   266  		// It was added because Futures are common in Cadence code, and some patterns are much simpler with it.
   267  		//
   268  		// Each call to AddFuture will invoke its f at most one time, regardless of how many times Select is called.
   269  		// This means, for a Future that is (or will be) ready:
   270  		// - Adding the Future once, then calling Select twice, will invoke the callback once with the first Select
   271  		//   call, and then wait for other Selector conditions in the second Select call (or block forever if there are
   272  		//   no other eligible conditions).
   273  		// - Adding the same Future twice, then calling Select twice, will invoke each callback once.
   274  		// - Adding the same Future to two different Selectors, then calling Select once on each Selector, will invoke
   275  		//   each Selector's callback once.
   276  		//
   277  		// Therefore, with a Future "f" that is or will become ready, this is an infinite loop that will consume as much
   278  		// CPU as possible:
   279  		//  for {
   280  		//  	workflow.NewSelector(ctx).AddFuture(f, func(f workflow.Future){}).Select(ctx)
   281  		//  }
   282  		// While this will loop once, and then wait idle forever:
   283  		//  s := workflow.NewSelector(ctx).AddFuture(f, func(f workflow.Future){})
   284  		//  for {
   285  		//  	s.Select(ctx)
   286  		//  }
   287  		AddFuture(future Future, f func(f Future)) Selector
   288  		// AddDefault adds a default branch to the selector.
   289  		// f is invoked immediately when none of the other conditions (AddReceive, AddSend, AddFuture) are met for a
   290  		// Select call.
   291  		//
   292  		// This is equivalent to a `default:` case.
   293  		//
   294  		// Note that this applies to each Select call.  If you create a Selector with only one AddDefault, and then call
   295  		// Select on it twice, f will be invoked twice.
   296  		AddDefault(f func())
   297  		// Select waits for one of the added conditions to be met and invokes the callback as described above.
   298  		// If no condition is met, Select will block until one or more are available, then one callback will be invoked.
   299  		// If no condition is ever met, Select will block forever.
   300  		//
   301  		// Note that Select does not return an error, and does not stop waiting if its Context is canceled.
   302  		// This mimics a native Go select statement, which has no way to be interrupted except for its listed cases.
   303  		//
   304  		// If you wish to stop Selecting when the Context is canceled, use AddReceive with the Context's Done() channel,
   305  		// in the same way as you would use a `case <- ctx.Done():` in a Go select statement.  E.g.:
   306  		//  cancelled := false
   307  		//  s := workflow.NewSelector(ctx)
   308  		//  s.AddFuture(f, func(f workflow.Future) {}) // assume this is never ready
   309  		//  s.AddReceive(ctx.Done(), func(c workflow.Channel, more bool) {
   310  		//  	// this will be invoked when the Context is cancelled for any reason,
   311  		//  	// and more will be false.
   312  		//  	cancelled = true
   313  		//  })
   314  		//  s.Select(ctx)
   315  		//  if cancelled {
   316  		//  	// this will be executed
   317  		//  }
   318  		Select(ctx Context)
   319  	}
   320  
   321  	// WaitGroup must be used instead of native go sync.WaitGroup by
   322  	// workflow code.  Use workflow.NewWaitGroup(ctx) method to create
   323  	// a new WaitGroup instance
   324  	WaitGroup interface {
   325  		Add(delta int)
   326  		Done()
   327  		Wait(ctx Context)
   328  	}
   329  
   330  	// Future represents the result of an asynchronous computation.
   331  	Future interface {
   332  		// Get blocks until the future is ready.
   333  		// When ready it either returns the Future's contained error, or assigns the contained value to the output var.
   334  		// Failures to assign or decode the value will panic.
   335  		//
   336  		// Two common patterns to retrieve data are:
   337  		//  var out string
   338  		//  // this will assign the string value, which may be "", or an error and leave out as "".
   339  		//  err := f.Get(ctx, &out)
   340  		// and
   341  		//  var out *string
   342  		//  // this will assign the string value, which may be "" or nil, or an error and leave out as nil.
   343  		//  err := f.Get(ctx, &out)
   344  		//
   345  		// The valuePtr parameter can be nil when the encoded result value is not needed:
   346  		//  err := f.Get(ctx, nil)
   347  		//
   348  		// Futures with values set in-memory via a call to their Settable's methods can be retrieved without knowing the
   349  		// type with an interface, i.e. this will not ever panic:
   350  		//  var out interface{}
   351  		//  // this will assign the same value that was set,
   352  		//  // and you can check its type with reflection or type assertions.
   353  		//  err := f.Get(ctx, &out)
   354  		//
   355  		// Futures with encoded data from e.g. activities or child workflows can bypass decoding with a byte slice, and
   356  		// similarly this will not ever panic:
   357  		//  var out []byte
   358  		//  // out will contain the raw bytes given to Cadence's servers, you should decode it however is necessary
   359  		//  err := f.Get(ctx, &out) // err can only be the Future's contained error
   360  		Get(ctx Context, valuePtr interface{}) error
   361  
   362  		// IsReady will return true Get is guaranteed to not block.
   363  		IsReady() bool
   364  	}
   365  
   366  	// Settable is used to set value or error on a future.
   367  	// See more: workflow.NewFuture(ctx).
   368  	Settable interface {
   369  		Set(value interface{}, err error)
   370  		SetValue(value interface{})
   371  		SetError(err error)
   372  		Chain(future Future) // Value (or error) of the future become the same of the chained one.
   373  	}
   374  
   375  	// ChildWorkflowFuture represents the result of a child workflow execution
   376  	ChildWorkflowFuture interface {
   377  		Future
   378  		// GetChildWorkflowExecution returns a future that will be ready when child workflow execution started. You can
   379  		// get the WorkflowExecution of the child workflow from the future. Then you can use Workflow ID and RunID of
   380  		// child workflow to cancel or send signal to child workflow.
   381  		//  childWorkflowFuture := workflow.ExecuteChildWorkflow(ctx, child, ...)
   382  		//  var childWE WorkflowExecution
   383  		//  if err := childWorkflowFuture.GetChildWorkflowExecution().Get(ctx, &childWE); err == nil {
   384  		//      // child workflow started, you can use childWE to get the WorkflowID and RunID of child workflow
   385  		//  }
   386  		GetChildWorkflowExecution() Future
   387  
   388  		// SignalWorkflowByID sends a signal to the child workflow. This call will block until child workflow is started.
   389  		SignalChildWorkflow(ctx Context, signalName string, data interface{}) Future
   390  	}
   391  
   392  	// WorkflowType identifies a workflow type.
   393  	WorkflowType struct {
   394  		Name string
   395  	}
   396  
   397  	// WorkflowExecution Details.
   398  	WorkflowExecution struct {
   399  		ID    string
   400  		RunID string
   401  	}
   402  
   403  	// EncodedValue is type alias used to encapsulate/extract encoded result from workflow/activity.
   404  	EncodedValue struct {
   405  		value         []byte
   406  		dataConverter DataConverter
   407  	}
   408  	// Version represents a change version. See GetVersion call.
   409  	Version int
   410  
   411  	// ChildWorkflowOptions stores all child workflow specific parameters that will be stored inside of a Context.
   412  	// The current timeout resolution implementation is in seconds and uses math.Ceil(d.Seconds()) as the duration. But is
   413  	// subjected to change in the future.
   414  	ChildWorkflowOptions struct {
   415  		// Domain of the child workflow.
   416  		// Optional: the current workflow (parent)'s domain will be used if this is not provided.
   417  		Domain string
   418  
   419  		// WorkflowID of the child workflow to be scheduled.
   420  		// Optional: an auto generated workflowID will be used if this is not provided.
   421  		WorkflowID string
   422  
   423  		// TaskList that the child workflow needs to be scheduled on.
   424  		// Optional: the parent workflow task list will be used if this is not provided.
   425  		TaskList string
   426  
   427  		// ExecutionStartToCloseTimeout - The end to end timeout for the child workflow execution.
   428  		// Mandatory: no default
   429  		ExecutionStartToCloseTimeout time.Duration
   430  
   431  		// TaskStartToCloseTimeout - The decision task timeout for the child workflow.
   432  		// Optional: default is 10s if this is not provided (or if 0 is provided).
   433  		TaskStartToCloseTimeout time.Duration
   434  
   435  		// WaitForCancellation - Whether to wait for cancelled child workflow to be ended (child workflow can be ended
   436  		// as: completed/failed/timedout/terminated/canceled)
   437  		// Optional: default false
   438  		WaitForCancellation bool
   439  
   440  		// WorkflowIDReusePolicy - Whether server allow reuse of workflow ID, can be useful
   441  		// for dedup logic if set to WorkflowIdReusePolicyRejectDuplicate
   442  		WorkflowIDReusePolicy WorkflowIDReusePolicy
   443  
   444  		// RetryPolicy specify how to retry child workflow if error happens.
   445  		// Optional: default is no retry
   446  		RetryPolicy *RetryPolicy
   447  
   448  		// CronSchedule - Optional cron schedule for workflow. If a cron schedule is specified, the workflow will run
   449  		// as a cron based on the schedule. The scheduling will be based on UTC time. Schedule for next run only happen
   450  		// after the current run is completed/failed/timeout. If a RetryPolicy is also supplied, and the workflow failed
   451  		// or timeout, the workflow will be retried based on the retry policy. While the workflow is retrying, it won't
   452  		// schedule its next run. If next schedule is due while workflow is running (or retrying), then it will skip that
   453  		// schedule. Cron workflow will not stop until it is terminated or cancelled (by returning cadence.CanceledError).
   454  		// The cron spec is as following:
   455  		// ┌───────────── minute (0 - 59)
   456  		// │ ┌───────────── hour (0 - 23)
   457  		// │ │ ┌───────────── day of the month (1 - 31)
   458  		// │ │ │ ┌───────────── month (1 - 12)
   459  		// │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday)
   460  		// │ │ │ │ │
   461  		// │ │ │ │ │
   462  		// * * * * *
   463  		CronSchedule string
   464  
   465  		// Memo - Optional non-indexed info that will be shown in list workflow.
   466  		Memo map[string]interface{}
   467  
   468  		// SearchAttributes - Optional indexed info that can be used in query of List/Scan/Count workflow APIs (only
   469  		// supported when Cadence server is using ElasticSearch). The key and value type must be registered on Cadence server side.
   470  		// Use GetSearchAttributes API to get valid key and corresponding value type.
   471  		SearchAttributes map[string]interface{}
   472  
   473  		// ParentClosePolicy - Optional policy to decide what to do for the child.
   474  		// Default is Terminate (if onboarded to this feature)
   475  		ParentClosePolicy ParentClosePolicy
   476  
   477  		// Bugports allows opt-in enabling of older, possibly buggy behavior, primarily intended to allow temporarily
   478  		// emulating old behavior until a fix is deployed.
   479  		//
   480  		// Bugports are always deprecated and may be removed in future versions.
   481  		// Generally speaking they will *likely* remain in place for one minor version, and then they may be removed to
   482  		// allow cleaning up the additional code complexity that they cause.
   483  		//
   484  		// Deprecated: All bugports are always deprecated and may be removed at any time.
   485  		Bugports Bugports
   486  	}
   487  
   488  	// Bugports allows opt-in enabling of older, possibly buggy behavior, primarily intended to allow temporarily
   489  	// emulating old behavior until a fix is deployed.
   490  	// By default, bugs (especially rarely-occurring ones) are fixed and all users are opted into the new behavior.
   491  	// Back-ported buggy behavior *may* be available via these flags.
   492  	//
   493  	// Fields in here are NOT guaranteed to be stable.  They will almost certainly be removed in the next major
   494  	// release, and might be removed earlier if a need arises, e.g. if the historical behavior causes too much of an
   495  	// increase in code complexity.
   496  	//
   497  	// See each individual field for details.
   498  	//
   499  	// Bugports are always deprecated and may be removed in future versions.
   500  	// Generally speaking they will *likely* remain in place for one minor version, and then they may be removed to
   501  	// allow cleaning up the additional code complexity that they cause.
   502  	//
   503  	// DEPRECATED: All bugports are always deprecated and may be removed at any time.
   504  	Bugports struct {
   505  		// StartChildWorkflowsOnCanceledContext allows emulating older, buggy behavior that existed prior to v0.18.4.
   506  		//
   507  		// Prior to the fix, child workflows would be started and keep running when their context was canceled in two
   508  		// situations:
   509  		// 1) when the context was canceled before ExecuteChildWorkflow is called, and
   510  		// 2) when the context was canceled after ExecuteChildWorkflow but before the child workflow was started.
   511  		//
   512  		// 1 is unfortunately easy to trigger, though many workflows will encounter an error earlier and not reach the
   513  		// child-workflow-executing code.  2 is expected to be very rare in practice.
   514  		//
   515  		// To permanently emulate old behavior, use a disconnected context when starting child workflows, and
   516  		// cancel it only after `childfuture.GetWorkflowExecution().Get(...)` returns.  This can be used when this flag
   517  		// is removed in the future.
   518  		//
   519  		// If you have currently-broken workflows and need to repair them, there are two primary options:
   520  		//
   521  		// 1: Check the BinaryChecksum value of your new deploy and/or of the decision that is currently failing
   522  		// workflows.  Then set this flag when replaying history on those not-fixed checksums.  Concretely, this means
   523  		// checking both `workflow.GetInfo(ctx).BinaryChecksum` (note that sufficiently old clients may not have
   524  		// recorded a value, and it may be nil) and `workflow.IsReplaying(ctx)`.
   525  		//
   526  		// 2: Reset broken workflows back to either before the buggy behavior was recorded, or before the fixed behavior
   527  		// was deployed.  A "bad binary" reset type can do the latter in bulk, see the CLI's
   528  		// `cadence workflow reset-batch --reset_type BadBinary --help` for details.  For the former, check the failing
   529  		// histories, identify the point at which the bug occurred, and reset to prior to that decision task.
   530  		//
   531  		// Added in 0.18.4, this may be removed in or after v0.19.0, so please migrate off of it ASAP.
   532  		//
   533  		// Deprecated: All bugports are always deprecated and may be removed at any time.
   534  		StartChildWorkflowsOnCanceledContext bool
   535  	}
   536  )
   537  
   538  // RegisterWorkflowOptions consists of options for registering a workflow
   539  type RegisterWorkflowOptions struct {
   540  	Name string
   541  	// Workflow type name is equal to function name instead of fully qualified name including function package.
   542  	// This option has no effect when explicit Name is provided.
   543  	EnableShortName               bool
   544  	DisableAlreadyRegisteredCheck bool
   545  }
   546  
   547  // RegisterWorkflow - registers a workflow function with the framework.
   548  // The public form is: workflow.Register(...)
   549  // A workflow takes a cadence context and input and returns a (result, error) or just error.
   550  // Examples:
   551  //
   552  //	func sampleWorkflow(ctx workflow.Context, input []byte) (result []byte, err error)
   553  //	func sampleWorkflow(ctx workflow.Context, arg1 int, arg2 string) (result []byte, err error)
   554  //	func sampleWorkflow(ctx workflow.Context) (result []byte, err error)
   555  //	func sampleWorkflow(ctx workflow.Context, arg1 int) (result string, err error)
   556  //
   557  // Serialization of all primitive types, structures is supported ... except channels, functions, variadic, unsafe pointer.
   558  // This method calls panic if workflowFunc doesn't comply with the expected format.
   559  // Deprecated: Global workflow registration methods are replaced by equivalent Worker instance methods.
   560  // This method is kept to maintain backward compatibility and should not be used.
   561  func RegisterWorkflow(workflowFunc interface{}) {
   562  	RegisterWorkflowWithOptions(workflowFunc, RegisterWorkflowOptions{})
   563  }
   564  
   565  // RegisterWorkflowWithOptions registers the workflow function with options.
   566  // The public form is: workflow.RegisterWithOptions(...)
   567  // The user can use options to provide an external name for the workflow or leave it empty if no
   568  // external name is required. This can be used as
   569  //
   570  //	workflow.RegisterWithOptions(sampleWorkflow, RegisterWorkflowOptions{})
   571  //	workflow.RegisterWithOptions(sampleWorkflow, RegisterWorkflowOptions{Name: "foo"})
   572  //
   573  // A workflow takes a cadence context and input and returns a (result, error) or just error.
   574  // Examples:
   575  //
   576  //	func sampleWorkflow(ctx workflow.Context, input []byte) (result []byte, err error)
   577  //	func sampleWorkflow(ctx workflow.Context, arg1 int, arg2 string) (result []byte, err error)
   578  //	func sampleWorkflow(ctx workflow.Context) (result []byte, err error)
   579  //	func sampleWorkflow(ctx workflow.Context, arg1 int) (result string, err error)
   580  //
   581  // Serialization of all primitive types, structures is supported ... except channels, functions, variadic, unsafe pointer.
   582  // This method calls panic if workflowFunc doesn't comply with the expected format or tries to register the same workflow
   583  // type name twice. Use workflow.RegisterOptions.DisableAlreadyRegisteredCheck to allow multiple registrations.
   584  // Deprecated: Global workflow registration methods are replaced by equivalent Worker instance methods.
   585  // This method is kept to maintain backward compatibility and should not be used.
   586  func RegisterWorkflowWithOptions(workflowFunc interface{}, opts RegisterWorkflowOptions) {
   587  	registry := getGlobalRegistry()
   588  	registry.RegisterWorkflowWithOptions(workflowFunc, opts)
   589  }
   590  
   591  // GetRegisteredWorkflowTypes returns the registered workflow function/alias names.
   592  // The public form is: workflow.GetRegisteredWorkflowTypes(...)
   593  func GetRegisteredWorkflowTypes() []string {
   594  	registry := getGlobalRegistry()
   595  	return registry.GetRegisteredWorkflowTypes()
   596  }
   597  
   598  // Await blocks the calling thread until condition() returns true
   599  // Returns CanceledError if the ctx is canceled.
   600  func Await(ctx Context, condition func() bool) error {
   601  	state := getState(ctx)
   602  	defer state.unblocked()
   603  
   604  	for !condition() {
   605  		doneCh := ctx.Done()
   606  		// TODO: Consider always returning a channel
   607  		if doneCh != nil {
   608  			if _, more := doneCh.ReceiveAsyncWithMoreFlag(nil); !more {
   609  				return NewCanceledError("Await context cancelled")
   610  			}
   611  		}
   612  		state.yield("Await")
   613  	}
   614  	return nil
   615  }
   616  
   617  // NewChannel create new Channel instance
   618  func NewChannel(ctx Context) Channel {
   619  	state := getState(ctx)
   620  	state.dispatcher.channelSequence++
   621  	return NewNamedChannel(ctx, fmt.Sprintf("chan-%v", state.dispatcher.channelSequence))
   622  }
   623  
   624  // NewNamedChannel create new Channel instance with a given human readable name.
   625  // Name appears in stack traces that are blocked on this channel.
   626  func NewNamedChannel(ctx Context, name string) Channel {
   627  	env := getWorkflowEnvironment(ctx)
   628  	return &channelImpl{name: name, dataConverter: getDataConverterFromWorkflowContext(ctx), env: env}
   629  }
   630  
   631  // NewBufferedChannel create new buffered Channel instance
   632  func NewBufferedChannel(ctx Context, size int) Channel {
   633  	env := getWorkflowEnvironment(ctx)
   634  	return &channelImpl{size: size, dataConverter: getDataConverterFromWorkflowContext(ctx), env: env}
   635  }
   636  
   637  // NewNamedBufferedChannel create new BufferedChannel instance with a given human readable name.
   638  // Name appears in stack traces that are blocked on this Channel.
   639  func NewNamedBufferedChannel(ctx Context, name string, size int) Channel {
   640  	env := getWorkflowEnvironment(ctx)
   641  	return &channelImpl{name: name, size: size, dataConverter: getDataConverterFromWorkflowContext(ctx), env: env}
   642  }
   643  
   644  // NewSelector creates a new Selector instance.
   645  func NewSelector(ctx Context) Selector {
   646  	state := getState(ctx)
   647  	state.dispatcher.selectorSequence++
   648  	return NewNamedSelector(ctx, fmt.Sprintf("selector-%v", state.dispatcher.selectorSequence))
   649  }
   650  
   651  // NewNamedSelector creates a new Selector instance with a given human readable name.
   652  // Name appears in stack traces that are blocked on this Selector.
   653  func NewNamedSelector(ctx Context, name string) Selector {
   654  	return &selectorImpl{name: name}
   655  }
   656  
   657  // NewWaitGroup creates a new WaitGroup instance.
   658  func NewWaitGroup(ctx Context) WaitGroup {
   659  	f, s := NewFuture(ctx)
   660  	return &waitGroupImpl{future: f, settable: s}
   661  }
   662  
   663  // Go creates a new coroutine. It has similar semantic to goroutine in a context of the workflow.
   664  func Go(ctx Context, f func(ctx Context)) {
   665  	state := getState(ctx)
   666  	state.dispatcher.newCoroutine(ctx, f)
   667  }
   668  
   669  // GoNamed creates a new coroutine with a given human readable name.
   670  // It has similar semantic to goroutine in a context of the workflow.
   671  // Name appears in stack traces that are blocked on this Channel.
   672  func GoNamed(ctx Context, name string, f func(ctx Context)) {
   673  	state := getState(ctx)
   674  	state.dispatcher.newNamedCoroutine(ctx, name, f)
   675  }
   676  
   677  // NewFuture creates a new future as well as associated Settable that is used to set its value.
   678  func NewFuture(ctx Context) (Future, Settable) {
   679  	impl := &futureImpl{channel: NewChannel(ctx).(*channelImpl)}
   680  	return impl, impl
   681  }
   682  
   683  func (wc *workflowEnvironmentInterceptor) ExecuteWorkflow(ctx Context, workflowType string, inputArgs ...interface{}) (results []interface{}) {
   684  	args := []reflect.Value{reflect.ValueOf(ctx)}
   685  	for _, arg := range inputArgs {
   686  		// []byte arguments are not serialized
   687  		switch arg.(type) {
   688  		case []byte:
   689  			args = append(args, reflect.ValueOf(arg))
   690  		default:
   691  			args = append(args, reflect.ValueOf(arg).Elem())
   692  		}
   693  	}
   694  	fnValue := reflect.ValueOf(wc.fn)
   695  	retValues := fnValue.Call(args)
   696  	for _, r := range retValues {
   697  		results = append(results, r.Interface())
   698  	}
   699  	return
   700  }
   701  
   702  // ExecuteActivity requests activity execution in the context of a workflow.
   703  // Context can be used to pass the settings for this activity.
   704  // For example: task list that this need to be routed, timeouts that need to be configured.
   705  // Use ActivityOptions to pass down the options.
   706  //
   707  //	 ao := ActivityOptions{
   708  //		    TaskList: "exampleTaskList",
   709  //		    ScheduleToStartTimeout: 10 * time.Second,
   710  //		    StartToCloseTimeout: 5 * time.Second,
   711  //		    ScheduleToCloseTimeout: 10 * time.Second,
   712  //		    HeartbeatTimeout: 0,
   713  //		}
   714  //		ctx := WithActivityOptions(ctx, ao)
   715  //
   716  // Or to override a single option
   717  //
   718  //	ctx := WithTaskList(ctx, "exampleTaskList")
   719  //
   720  // Input activity is either an activity name (string) or a function representing an activity that is getting scheduled.
   721  // Input args are the arguments that need to be passed to the scheduled activity.
   722  //
   723  // If the activity failed to complete then the future get error would indicate the failure, and it can be one of
   724  // CustomError, TimeoutError, CanceledError, PanicError, GenericError.
   725  // You can cancel the pending activity using context(workflow.WithCancel(ctx)) and that will fail the activity with
   726  // error CanceledError.
   727  //
   728  // ExecuteActivity returns Future with activity result or failure.
   729  func ExecuteActivity(ctx Context, activity interface{}, args ...interface{}) Future {
   730  	i := getWorkflowInterceptor(ctx)
   731  	registry := getRegistryFromWorkflowContext(ctx)
   732  	activityType := getActivityFunctionName(registry, activity)
   733  	return i.ExecuteActivity(ctx, activityType, args...)
   734  }
   735  
   736  func (wc *workflowEnvironmentInterceptor) ExecuteActivity(ctx Context, typeName string, args ...interface{}) Future {
   737  	// Validate type and its arguments.
   738  	dataConverter := getDataConverterFromWorkflowContext(ctx)
   739  	registry := getRegistryFromWorkflowContext(ctx)
   740  	future, settable := newDecodeFuture(ctx, typeName)
   741  	activityType, err := getValidatedActivityFunction(typeName, args, registry)
   742  	if err != nil {
   743  		settable.Set(nil, err)
   744  		return future
   745  	}
   746  	// Validate context options.
   747  	options, err := getValidatedActivityOptions(ctx)
   748  	if err != nil {
   749  		settable.Set(nil, err)
   750  		return future
   751  	}
   752  
   753  	// Validate session state.
   754  	if sessionInfo := getSessionInfo(ctx); sessionInfo != nil {
   755  		isCreationActivity := isSessionCreationActivity(typeName)
   756  		if sessionInfo.sessionState == sessionStateFailed && !isCreationActivity {
   757  			settable.Set(nil, ErrSessionFailed)
   758  			return future
   759  		}
   760  		if sessionInfo.sessionState == sessionStateOpen && !isCreationActivity {
   761  			// Use session tasklist
   762  			oldTaskListName := options.TaskListName
   763  			options.TaskListName = sessionInfo.tasklist
   764  			defer func() {
   765  				options.TaskListName = oldTaskListName
   766  			}()
   767  		}
   768  	}
   769  
   770  	// Retrieve headers from context to pass them on
   771  	header := getHeadersFromContext(ctx)
   772  
   773  	input, err := encodeArgs(dataConverter, args)
   774  	if err != nil {
   775  		panic(err)
   776  	}
   777  
   778  	params := executeActivityParams{
   779  		activityOptions: *options,
   780  		ActivityType:    *activityType,
   781  		Input:           input,
   782  		DataConverter:   dataConverter,
   783  		Header:          header,
   784  	}
   785  
   786  	ctxDone, cancellable := ctx.Done().(*channelImpl)
   787  	cancellationCallback := &receiveCallback{}
   788  	a := getWorkflowEnvironment(ctx).ExecuteActivity(params, func(r []byte, e error) {
   789  		settable.Set(r, e)
   790  		if cancellable {
   791  			// future is done, we don't need the cancellation callback anymore.
   792  			ctxDone.removeReceiveCallback(cancellationCallback)
   793  		}
   794  	})
   795  
   796  	if cancellable {
   797  		cancellationCallback.fn = func(v interface{}, more bool) bool {
   798  			if ctx.Err() == ErrCanceled {
   799  				wc.env.RequestCancelActivity(a.activityID)
   800  			}
   801  			return false
   802  		}
   803  		_, ok, more := ctxDone.receiveAsyncImpl(cancellationCallback)
   804  		if ok || !more {
   805  			cancellationCallback.fn(nil, more)
   806  		}
   807  	}
   808  	return future
   809  }
   810  
   811  // ExecuteLocalActivity requests to run a local activity. A local activity is like a regular activity with some key
   812  // differences:
   813  // * Local activity is scheduled and run by the workflow worker locally.
   814  // * Local activity does not need Cadence server to schedule activity task and does not rely on activity worker.
   815  // * No need to register local activity.
   816  // * The parameter activity to ExecuteLocalActivity() must be a function.
   817  // * Local activity is for short living activities (usually finishes within seconds).
   818  // * Local activity cannot heartbeat.
   819  //
   820  // Context can be used to pass the settings for this local activity.
   821  // For now there is only one setting for timeout to be set:
   822  //
   823  //	 lao := LocalActivityOptions{
   824  //		    ScheduleToCloseTimeout: 5 * time.Second,
   825  //		}
   826  //		ctx := WithLocalActivityOptions(ctx, lao)
   827  //
   828  // The timeout here should be relative shorter than the DecisionTaskStartToCloseTimeout of the workflow. If you need a
   829  // longer timeout, you probably should not use local activity and instead should use regular activity. Local activity is
   830  // designed to be used for short living activities (usually finishes within seconds).
   831  //
   832  // Input args are the arguments that will to be passed to the local activity. The input args will be hand over directly
   833  // to local activity function without serialization/deserialization because we don't need to pass the input across process
   834  // boundary. However, the result will still go through serialization/deserialization because we need to record the result
   835  // as history to cadence server so if the workflow crashes, a different worker can replay the history without running
   836  // the local activity again.
   837  //
   838  // If the activity failed to complete then the future get error would indicate the failure, and it can be one of
   839  // CustomError, TimeoutError, CanceledError, PanicError, GenericError.
   840  // You can cancel the pending activity by cancel the context(workflow.WithCancel(ctx)) and that will fail the activity
   841  // with error CanceledError.
   842  //
   843  // ExecuteLocalActivity returns Future with local activity result or failure.
   844  func ExecuteLocalActivity(ctx Context, activity interface{}, args ...interface{}) Future {
   845  	i := getWorkflowInterceptor(ctx)
   846  	env := getWorkflowEnvironment(ctx)
   847  	activityType := getActivityFunctionName(env.GetRegistry(), activity)
   848  	ctx = WithValue(ctx, localActivityFnContextKey, activity)
   849  	return i.ExecuteLocalActivity(ctx, activityType, args...)
   850  }
   851  
   852  func (wc *workflowEnvironmentInterceptor) ExecuteLocalActivity(ctx Context, activityType string, args ...interface{}) Future {
   853  	header := getHeadersFromContext(ctx)
   854  	activityFn := ctx.Value(localActivityFnContextKey)
   855  	if activityFn == nil {
   856  		panic("ExecuteLocalActivity: Expected context key " + localActivityFnContextKey + " is missing")
   857  	}
   858  
   859  	future, settable := newDecodeFuture(ctx, activityFn)
   860  	if err := validateFunctionArgs(activityFn, args, false); err != nil {
   861  		settable.Set(nil, err)
   862  		return future
   863  	}
   864  	options, err := getValidatedLocalActivityOptions(ctx)
   865  	if err != nil {
   866  		settable.Set(nil, err)
   867  		return future
   868  	}
   869  	params := &executeLocalActivityParams{
   870  		localActivityOptions: *options,
   871  		ActivityFn:           activityFn,
   872  		ActivityType:         activityType,
   873  		InputArgs:            args,
   874  		WorkflowInfo:         GetWorkflowInfo(ctx),
   875  		DataConverter:        getDataConverterFromWorkflowContext(ctx),
   876  		ScheduledTime:        Now(ctx), // initial scheduled time
   877  		Header:               header,
   878  	}
   879  
   880  	Go(ctx, func(ctx Context) {
   881  		for {
   882  			f := wc.scheduleLocalActivity(ctx, params)
   883  			var result []byte
   884  			err := f.Get(ctx, &result)
   885  			if retryErr, ok := err.(*needRetryError); ok && retryErr.Backoff > 0 {
   886  				// Backoff for retry
   887  				Sleep(ctx, retryErr.Backoff)
   888  				// increase the attempt, and retry the local activity
   889  				params.Attempt = retryErr.Attempt + 1
   890  				continue
   891  			}
   892  
   893  			// not more retry, return whatever is received.
   894  			settable.Set(result, err)
   895  			return
   896  		}
   897  	})
   898  
   899  	return future
   900  }
   901  
   902  type needRetryError struct {
   903  	Backoff time.Duration
   904  	Attempt int32
   905  }
   906  
   907  func (e *needRetryError) Error() string {
   908  	return fmt.Sprintf("Retry backoff: %v, Attempt: %v", e.Backoff, e.Attempt)
   909  }
   910  
   911  func (wc *workflowEnvironmentInterceptor) scheduleLocalActivity(ctx Context, params *executeLocalActivityParams) Future {
   912  	f := &futureImpl{channel: NewChannel(ctx).(*channelImpl)}
   913  	ctxDone, cancellable := ctx.Done().(*channelImpl)
   914  	cancellationCallback := &receiveCallback{}
   915  	la := wc.env.ExecuteLocalActivity(*params, func(lar *localActivityResultWrapper) {
   916  		if cancellable {
   917  			// future is done, we don't need cancellation anymore
   918  			ctxDone.removeReceiveCallback(cancellationCallback)
   919  		}
   920  
   921  		if lar.err == nil || IsCanceledError(lar.err) || lar.backoff <= 0 {
   922  			f.Set(lar.result, lar.err)
   923  			return
   924  		}
   925  
   926  		// set retry error, and it will be handled by workflow.ExecuteLocalActivity().
   927  		f.Set(nil, &needRetryError{Backoff: lar.backoff, Attempt: lar.attempt})
   928  		return
   929  	})
   930  
   931  	if cancellable {
   932  		cancellationCallback.fn = func(v interface{}, more bool) bool {
   933  			if ctx.Err() == ErrCanceled {
   934  				getWorkflowEnvironment(ctx).RequestCancelLocalActivity(la.activityID)
   935  			}
   936  			return false
   937  		}
   938  		_, ok, more := ctxDone.receiveAsyncImpl(cancellationCallback)
   939  		if ok || !more {
   940  			cancellationCallback.fn(nil, more)
   941  		}
   942  	}
   943  
   944  	return f
   945  }
   946  
   947  // ExecuteChildWorkflow requests child workflow execution in the context of a workflow.
   948  // Context can be used to pass the settings for the child workflow.
   949  // For example: task list that this child workflow should be routed, timeouts that need to be configured.
   950  // Use ChildWorkflowOptions to pass down the options.
   951  //
   952  //	 cwo := ChildWorkflowOptions{
   953  //		    ExecutionStartToCloseTimeout: 10 * time.Minute,
   954  //		    TaskStartToCloseTimeout: time.Minute,
   955  //		}
   956  //	 ctx := WithChildWorkflowOptions(ctx, cwo)
   957  //
   958  // Input childWorkflow is either a workflow name or a workflow function that is getting scheduled.
   959  // Input args are the arguments that need to be passed to the child workflow function represented by childWorkflow.
   960  // If the child workflow failed to complete then the future get error would indicate the failure and it can be one of
   961  // CustomError, TimeoutError, CanceledError, GenericError.
   962  // You can cancel the pending child workflow using context(workflow.WithCancel(ctx)) and that will fail the workflow with
   963  // error CanceledError.
   964  // ExecuteChildWorkflow returns ChildWorkflowFuture.
   965  func ExecuteChildWorkflow(ctx Context, childWorkflow interface{}, args ...interface{}) ChildWorkflowFuture {
   966  	i := getWorkflowInterceptor(ctx)
   967  	env := getWorkflowEnvironment(ctx)
   968  	workflowType := getWorkflowFunctionName(env.GetRegistry(), childWorkflow)
   969  	return i.ExecuteChildWorkflow(ctx, workflowType, args...)
   970  }
   971  
   972  func (wc *workflowEnvironmentInterceptor) ExecuteChildWorkflow(ctx Context, childWorkflowType string, args ...interface{}) ChildWorkflowFuture {
   973  	mainFuture, mainSettable := newDecodeFuture(ctx, childWorkflowType)
   974  	executionFuture, executionSettable := NewFuture(ctx)
   975  	result := &childWorkflowFutureImpl{
   976  		decodeFutureImpl: mainFuture.(*decodeFutureImpl),
   977  		executionFuture:  executionFuture.(*futureImpl),
   978  	}
   979  	// clients prior to v0.18.4 would incorrectly start child workflows that were started with cancelled contexts,
   980  	// and did not react to cancellation between requested and started.
   981  	correctChildCancellation := true
   982  	workflowOptionsFromCtx := getWorkflowEnvOptions(ctx)
   983  
   984  	// Starting with a canceled context should immediately fail, no need to even try.
   985  	if ctx.Err() != nil {
   986  		if workflowOptionsFromCtx.bugports.StartChildWorkflowsOnCanceledContext {
   987  			// backport the bug
   988  			correctChildCancellation = false
   989  		} else {
   990  			mainSettable.SetError(ctx.Err())
   991  			executionSettable.SetError(ctx.Err())
   992  			return result
   993  		}
   994  	}
   995  
   996  	dc := workflowOptionsFromCtx.dataConverter
   997  	env := getWorkflowEnvironment(ctx)
   998  	wfType, input, err := getValidatedWorkflowFunction(childWorkflowType, args, dc, env.GetRegistry())
   999  	if err != nil {
  1000  		executionSettable.Set(nil, err)
  1001  		mainSettable.Set(nil, err)
  1002  		return result
  1003  	}
  1004  	options, err := getValidatedWorkflowOptions(ctx)
  1005  	if err != nil {
  1006  		executionSettable.Set(nil, err)
  1007  		mainSettable.Set(nil, err)
  1008  		return result
  1009  	}
  1010  	options.dataConverter = dc
  1011  	options.contextPropagators = workflowOptionsFromCtx.contextPropagators
  1012  	options.memo = workflowOptionsFromCtx.memo
  1013  	options.searchAttributes = workflowOptionsFromCtx.searchAttributes
  1014  
  1015  	params := executeWorkflowParams{
  1016  		workflowOptions: *options,
  1017  		input:           input,
  1018  		workflowType:    wfType,
  1019  		header:          getWorkflowHeader(ctx, options.contextPropagators),
  1020  		scheduledTime:   Now(ctx), /* this is needed for test framework, and is not send to server */
  1021  	}
  1022  
  1023  	var childWorkflowExecution *WorkflowExecution
  1024  
  1025  	ctxDone, cancellable := ctx.Done().(*channelImpl)
  1026  	cancellationCallback := &receiveCallback{}
  1027  	shouldCancelAsync := false
  1028  	err = getWorkflowEnvironment(ctx).ExecuteChildWorkflow(params, func(r []byte, e error) {
  1029  		mainSettable.Set(r, e)
  1030  		if cancellable {
  1031  			// future is done, we don't need cancellation anymore
  1032  			ctxDone.removeReceiveCallback(cancellationCallback)
  1033  		}
  1034  	}, func(r WorkflowExecution, e error) {
  1035  		if e == nil {
  1036  			childWorkflowExecution = &r
  1037  		}
  1038  		executionSettable.Set(r, e)
  1039  
  1040  		// forward the delayed cancellation if necessary
  1041  		if shouldCancelAsync && e == nil && !mainFuture.IsReady() {
  1042  			if workflowOptionsFromCtx.bugports.StartChildWorkflowsOnCanceledContext {
  1043  				// do nothing: buggy behavior did not forward the cancellation
  1044  			} else {
  1045  				getWorkflowEnvironment(ctx).RequestCancelChildWorkflow(*options.domain, childWorkflowExecution.ID)
  1046  			}
  1047  		}
  1048  	})
  1049  
  1050  	if err != nil {
  1051  		executionSettable.Set(nil, err)
  1052  		mainSettable.Set(nil, err)
  1053  		return result
  1054  	}
  1055  
  1056  	if cancellable {
  1057  		cancellationCallback.fn = func(v interface{}, more bool) bool {
  1058  			if ctx.Err() == ErrCanceled {
  1059  				if childWorkflowExecution != nil && !mainFuture.IsReady() {
  1060  					// child workflow started, and ctx cancelled.  forward cancel to the child.
  1061  					getWorkflowEnvironment(ctx).RequestCancelChildWorkflow(*options.domain, childWorkflowExecution.ID)
  1062  				} else if childWorkflowExecution == nil && correctChildCancellation {
  1063  					// decision to start the child has been made, but it has not yet started.
  1064  
  1065  					// TODO: ideal, but not strictly necessary for correctness:
  1066  					// if it's in the same decision, revoke that cancel synchronously.
  1067  
  1068  					// if the decision has already gone through: wait for it to be started, and then cancel it.
  1069  					shouldCancelAsync = true
  1070  				}
  1071  			}
  1072  			return false
  1073  		}
  1074  		_, ok, more := ctxDone.receiveAsyncImpl(cancellationCallback)
  1075  		if ok || !more {
  1076  			cancellationCallback.fn(nil, more)
  1077  		}
  1078  	}
  1079  
  1080  	return result
  1081  }
  1082  
  1083  func getWorkflowHeader(ctx Context, ctxProps []ContextPropagator) *s.Header {
  1084  	header := &s.Header{
  1085  		Fields: make(map[string][]byte),
  1086  	}
  1087  	writer := NewHeaderWriter(header)
  1088  	for _, ctxProp := range ctxProps {
  1089  		ctxProp.InjectFromWorkflow(ctx, writer)
  1090  	}
  1091  	return header
  1092  }
  1093  
  1094  // WorkflowInfo information about currently executing workflow
  1095  type WorkflowInfo struct {
  1096  	WorkflowExecution                   WorkflowExecution
  1097  	OriginalRunId                       string // The original runID before resetting. Using it instead of current runID can make workflow decision determinstic after reset
  1098  	WorkflowType                        WorkflowType
  1099  	TaskListName                        string
  1100  	ExecutionStartToCloseTimeoutSeconds int32
  1101  	TaskStartToCloseTimeoutSeconds      int32
  1102  	Domain                              string
  1103  	Attempt                             int32 // Attempt starts from 0 and increased by 1 for every retry if retry policy is specified.
  1104  	lastCompletionResult                []byte
  1105  	CronSchedule                        *string
  1106  	ContinuedExecutionRunID             *string
  1107  	ParentWorkflowDomain                *string
  1108  	ParentWorkflowExecution             *WorkflowExecution
  1109  	Memo                                *s.Memo             // Value can be decoded using data converter (DefaultDataConverter, or custom one if set).
  1110  	SearchAttributes                    *s.SearchAttributes // Value can be decoded using DefaultDataConverter.
  1111  	BinaryChecksum                      *string             // The identifier(generated by md5sum by default) of worker code that is making the current decision(can be used for auto-reset feature)
  1112  	DecisionStartedEventID              int64               // the eventID of DecisionStarted that is making the current decision(can be used for reset API)
  1113  	RetryPolicy                         *s.RetryPolicy
  1114  	TotalHistoryBytes                   int64
  1115  	HistoryBytesServer                  int64
  1116  	HistoryCount                        int64
  1117  }
  1118  
  1119  // GetBinaryChecksum returns the binary checksum(identifier) of this worker
  1120  // It is the identifier(generated by md5sum by default) of worker code that is making the current decision(can be used for auto-reset feature)
  1121  // In replay mode, it's from DecisionTaskCompleted event. In non-replay mode, it's from the currently executing worker.
  1122  func (wInfo *WorkflowInfo) GetBinaryChecksum() string {
  1123  	if wInfo.BinaryChecksum == nil {
  1124  		return getBinaryChecksum()
  1125  	}
  1126  	return *wInfo.BinaryChecksum
  1127  }
  1128  
  1129  // GetDecisionCompletedEventID returns the eventID of DecisionStartedEvent that is making the current decision(can be used for reset API: decisionFinishEventID = DecisionStartedEventID + 1)
  1130  func (wInfo *WorkflowInfo) GetDecisionStartedEventID() int64 {
  1131  	return wInfo.DecisionStartedEventID
  1132  }
  1133  
  1134  // GetWorkflowInfo extracts info of a current workflow from a context.
  1135  func GetWorkflowInfo(ctx Context) *WorkflowInfo {
  1136  	i := getWorkflowInterceptor(ctx)
  1137  	return i.GetWorkflowInfo(ctx)
  1138  }
  1139  
  1140  func (wc *workflowEnvironmentInterceptor) GetWorkflowInfo(ctx Context) *WorkflowInfo {
  1141  	return wc.env.WorkflowInfo()
  1142  }
  1143  
  1144  // GetLogger returns a logger to be used in workflow's context
  1145  func GetLogger(ctx Context) *zap.Logger {
  1146  	i := getWorkflowInterceptor(ctx)
  1147  	return i.GetLogger(ctx)
  1148  }
  1149  
  1150  func (wc *workflowEnvironmentInterceptor) GetLogger(ctx Context) *zap.Logger {
  1151  	return wc.env.GetLogger()
  1152  }
  1153  
  1154  // GetMetricsScope returns a metrics scope to be used in workflow's context
  1155  func GetMetricsScope(ctx Context) tally.Scope {
  1156  	i := getWorkflowInterceptor(ctx)
  1157  	return i.GetMetricsScope(ctx)
  1158  }
  1159  
  1160  func (wc *workflowEnvironmentInterceptor) GetMetricsScope(ctx Context) tally.Scope {
  1161  	return wc.env.GetMetricsScope()
  1162  }
  1163  
  1164  // GetTotalEstimatedHistoryBytes returns the current history size of that workflow
  1165  func GetTotalEstimatedHistoryBytes(ctx Context) int64 {
  1166  	i := getWorkflowInterceptor(ctx)
  1167  	return i.GetWorkflowInfo(ctx).TotalHistoryBytes
  1168  }
  1169  
  1170  // GetHistoryCount returns the current number of history events of that workflow
  1171  func GetHistoryCount(ctx Context) int64 {
  1172  	i := getWorkflowInterceptor(ctx)
  1173  	return i.GetWorkflowInfo(ctx).HistoryCount
  1174  }
  1175  
  1176  // Now returns the current time in UTC. It corresponds to the time when the decision task is started or replayed.
  1177  // Workflow needs to use this method to get the wall clock time instead of the one from the golang library.
  1178  func Now(ctx Context) time.Time {
  1179  	i := getWorkflowInterceptor(ctx)
  1180  	return i.Now(ctx).UTC()
  1181  }
  1182  
  1183  func (wc *workflowEnvironmentInterceptor) Now(ctx Context) time.Time {
  1184  	return wc.env.Now()
  1185  }
  1186  
  1187  // NewTimer returns immediately and the future becomes ready after the specified duration d. The workflow needs to use
  1188  // this NewTimer() to get the timer instead of the Go lang library one(timer.NewTimer()). You can cancel the pending
  1189  // timer by cancel the Context (using context from workflow.WithCancel(ctx)) and that will cancel the timer. After timer
  1190  // is canceled, the returned Future become ready, and Future.Get() will return *CanceledError.
  1191  // The current timer resolution implementation is in seconds and uses math.Ceil(d.Seconds()) as the duration. But is
  1192  // subjected to change in the future.
  1193  func NewTimer(ctx Context, d time.Duration) Future {
  1194  	i := getWorkflowInterceptor(ctx)
  1195  	return i.NewTimer(ctx, d)
  1196  }
  1197  
  1198  func (wc *workflowEnvironmentInterceptor) NewTimer(ctx Context, d time.Duration) Future {
  1199  	future, settable := NewFuture(ctx)
  1200  	if d <= 0 {
  1201  		settable.Set(true, nil)
  1202  		return future
  1203  	}
  1204  
  1205  	ctxDone, cancellable := ctx.Done().(*channelImpl)
  1206  	cancellationCallback := &receiveCallback{}
  1207  	t := wc.env.NewTimer(d, func(r []byte, e error) {
  1208  		settable.Set(nil, e)
  1209  		if cancellable {
  1210  			// future is done, we don't need cancellation anymore
  1211  			ctxDone.removeReceiveCallback(cancellationCallback)
  1212  		}
  1213  	})
  1214  
  1215  	if t != nil && cancellable {
  1216  		cancellationCallback.fn = func(v interface{}, more bool) bool {
  1217  			if !future.IsReady() {
  1218  				wc.env.RequestCancelTimer(t.timerID)
  1219  			}
  1220  			return false
  1221  		}
  1222  		_, ok, more := ctxDone.receiveAsyncImpl(cancellationCallback)
  1223  		if ok || !more {
  1224  			cancellationCallback.fn(nil, more)
  1225  		}
  1226  	}
  1227  	return future
  1228  }
  1229  
  1230  // Sleep pauses the current workflow for at least the duration d. A negative or zero duration causes Sleep to return
  1231  // immediately. Workflow code needs to use this Sleep() to sleep instead of the Go lang library one(timer.Sleep()).
  1232  // You can cancel the pending sleep by cancel the Context (using context from workflow.WithCancel(ctx)).
  1233  // Sleep() returns nil if the duration d is passed, or it returns *CanceledError if the ctx is canceled. There are 2
  1234  // reasons the ctx could be canceled: 1) your workflow code cancel the ctx (with workflow.WithCancel(ctx));
  1235  // 2) your workflow itself is canceled by external request.
  1236  // The current timer resolution implementation is in seconds and uses math.Ceil(d.Seconds()) as the duration. But is
  1237  // subjected to change in the future.
  1238  func Sleep(ctx Context, d time.Duration) (err error) {
  1239  	i := getWorkflowInterceptor(ctx)
  1240  	return i.Sleep(ctx, d)
  1241  }
  1242  
  1243  func (wc *workflowEnvironmentInterceptor) Sleep(ctx Context, d time.Duration) (err error) {
  1244  	t := NewTimer(ctx, d)
  1245  	err = t.Get(ctx, nil)
  1246  	return
  1247  }
  1248  
  1249  // RequestCancelExternalWorkflow can be used to request cancellation of an external workflow.
  1250  // Input workflowID is the workflow ID of target workflow.
  1251  // Input runID indicates the instance of a workflow. Input runID is optional (default is ""). When runID is not specified,
  1252  // then the currently running instance of that workflowID will be used.
  1253  // By default, the current workflow's domain will be used as target domain. However, you can specify a different domain
  1254  // of the target workflow using the context like:
  1255  //
  1256  //	ctx := WithWorkflowDomain(ctx, "domain-name")
  1257  //
  1258  // RequestCancelExternalWorkflow return Future with failure or empty success result.
  1259  func RequestCancelExternalWorkflow(ctx Context, workflowID, runID string) Future {
  1260  	i := getWorkflowInterceptor(ctx)
  1261  	return i.RequestCancelExternalWorkflow(ctx, workflowID, runID)
  1262  }
  1263  
  1264  func (wc *workflowEnvironmentInterceptor) RequestCancelExternalWorkflow(ctx Context, workflowID, runID string) Future {
  1265  	ctx1 := setWorkflowEnvOptionsIfNotExist(ctx)
  1266  	options := getWorkflowEnvOptions(ctx1)
  1267  	future, settable := NewFuture(ctx1)
  1268  
  1269  	if options.domain == nil || *options.domain == "" {
  1270  		settable.Set(nil, errDomainNotSet)
  1271  		return future
  1272  	}
  1273  
  1274  	if workflowID == "" {
  1275  		settable.Set(nil, errWorkflowIDNotSet)
  1276  		return future
  1277  	}
  1278  
  1279  	resultCallback := func(result []byte, err error) {
  1280  		settable.Set(result, err)
  1281  	}
  1282  
  1283  	wc.env.RequestCancelExternalWorkflow(
  1284  		*options.domain,
  1285  		workflowID,
  1286  		runID,
  1287  		resultCallback,
  1288  	)
  1289  
  1290  	return future
  1291  }
  1292  
  1293  // SignalExternalWorkflow can be used to send signal info to an external workflow.
  1294  // Input workflowID is the workflow ID of target workflow.
  1295  // Input runID indicates the instance of a workflow. Input runID is optional (default is ""). When runID is not specified,
  1296  // then the currently running instance of that workflowID will be used.
  1297  // By default, the current workflow's domain will be used as target domain. However, you can specify a different domain
  1298  // of the target workflow using the context like:
  1299  //
  1300  //	ctx := WithWorkflowDomain(ctx, "domain-name")
  1301  //
  1302  // SignalExternalWorkflow return Future with failure or empty success result.
  1303  func SignalExternalWorkflow(ctx Context, workflowID, runID, signalName string, arg interface{}) Future {
  1304  	i := getWorkflowInterceptor(ctx)
  1305  	return i.SignalExternalWorkflow(ctx, workflowID, runID, signalName, arg)
  1306  }
  1307  
  1308  func (wc *workflowEnvironmentInterceptor) SignalExternalWorkflow(ctx Context, workflowID, runID, signalName string, arg interface{}) Future {
  1309  	const childWorkflowOnly = false // this means we are not limited to child workflow
  1310  	return signalExternalWorkflow(ctx, workflowID, runID, signalName, arg, childWorkflowOnly)
  1311  }
  1312  
  1313  func signalExternalWorkflow(ctx Context, workflowID, runID, signalName string, arg interface{}, childWorkflowOnly bool) Future {
  1314  	env := getWorkflowEnvironment(ctx)
  1315  	ctx1 := setWorkflowEnvOptionsIfNotExist(ctx)
  1316  	options := getWorkflowEnvOptions(ctx1)
  1317  	future, settable := NewFuture(ctx1)
  1318  
  1319  	if options.domain == nil || *options.domain == "" {
  1320  		settable.Set(nil, errDomainNotSet)
  1321  		return future
  1322  	}
  1323  
  1324  	if workflowID == "" {
  1325  		settable.Set(nil, errWorkflowIDNotSet)
  1326  		return future
  1327  	}
  1328  
  1329  	input, err := encodeArg(options.dataConverter, arg)
  1330  	if err != nil {
  1331  		settable.Set(nil, err)
  1332  		return future
  1333  	}
  1334  
  1335  	resultCallback := func(result []byte, err error) {
  1336  		settable.Set(result, err)
  1337  	}
  1338  	env.SignalExternalWorkflow(
  1339  		*options.domain,
  1340  		workflowID,
  1341  		runID,
  1342  		signalName,
  1343  		input,
  1344  		arg,
  1345  		childWorkflowOnly,
  1346  		resultCallback,
  1347  	)
  1348  
  1349  	return future
  1350  }
  1351  
  1352  // UpsertSearchAttributes is used to add or update workflow search attributes.
  1353  // The search attributes can be used in query of List/Scan/Count workflow APIs.
  1354  // The key and value type must be registered on cadence server side;
  1355  // The value has to deterministic when replay;
  1356  // The value has to be Json serializable.
  1357  // UpsertSearchAttributes will merge attributes to existing map in workflow, for example workflow code:
  1358  //
  1359  //	  func MyWorkflow(ctx workflow.Context, input string) error {
  1360  //		   attr1 := map[string]interface{}{
  1361  //			   "CustomIntField": 1,
  1362  //			   "CustomBoolField": true,
  1363  //		   }
  1364  //		   workflow.UpsertSearchAttributes(ctx, attr1)
  1365  //
  1366  //		   attr2 := map[string]interface{}{
  1367  //			   "CustomIntField": 2,
  1368  //			   "CustomKeywordField": "seattle",
  1369  //		   }
  1370  //		   workflow.UpsertSearchAttributes(ctx, attr2)
  1371  //	  }
  1372  //
  1373  // will eventually have search attributes:
  1374  //
  1375  //	map[string]interface{}{
  1376  //		"CustomIntField": 2,
  1377  //		"CustomBoolField": true,
  1378  //		"CustomKeywordField": "seattle",
  1379  //	}
  1380  //
  1381  // This is only supported when using ElasticSearch.
  1382  func UpsertSearchAttributes(ctx Context, attributes map[string]interface{}) error {
  1383  	i := getWorkflowInterceptor(ctx)
  1384  	return i.UpsertSearchAttributes(ctx, attributes)
  1385  }
  1386  
  1387  func (wc *workflowEnvironmentInterceptor) UpsertSearchAttributes(ctx Context, attributes map[string]interface{}) error {
  1388  	if _, ok := attributes[CadenceChangeVersion]; ok {
  1389  		return errors.New("CadenceChangeVersion is a reserved key that cannot be set, please use other key")
  1390  	}
  1391  	return wc.env.UpsertSearchAttributes(attributes)
  1392  }
  1393  
  1394  // WithChildWorkflowOptions adds all workflow options to the context.
  1395  // The current timeout resolution implementation is in seconds and uses math.Ceil(d.Seconds()) as the duration. But is
  1396  // subjected to change in the future.
  1397  func WithChildWorkflowOptions(ctx Context, cwo ChildWorkflowOptions) Context {
  1398  	ctx1 := setWorkflowEnvOptionsIfNotExist(ctx)
  1399  	wfOptions := getWorkflowEnvOptions(ctx1)
  1400  	wfOptions.domain = common.StringPtr(cwo.Domain)
  1401  	wfOptions.taskListName = common.StringPtr(cwo.TaskList)
  1402  	wfOptions.workflowID = cwo.WorkflowID
  1403  	wfOptions.executionStartToCloseTimeoutSeconds = common.Int32Ptr(common.Int32Ceil(cwo.ExecutionStartToCloseTimeout.Seconds()))
  1404  	wfOptions.taskStartToCloseTimeoutSeconds = common.Int32Ptr(common.Int32Ceil(cwo.TaskStartToCloseTimeout.Seconds()))
  1405  	wfOptions.waitForCancellation = cwo.WaitForCancellation
  1406  	wfOptions.workflowIDReusePolicy = cwo.WorkflowIDReusePolicy
  1407  	wfOptions.retryPolicy = convertRetryPolicy(cwo.RetryPolicy)
  1408  	wfOptions.cronSchedule = cwo.CronSchedule
  1409  	wfOptions.memo = cwo.Memo
  1410  	wfOptions.searchAttributes = cwo.SearchAttributes
  1411  	wfOptions.parentClosePolicy = cwo.ParentClosePolicy
  1412  	wfOptions.bugports = cwo.Bugports
  1413  
  1414  	return ctx1
  1415  }
  1416  
  1417  // WithWorkflowDomain adds a domain to the context.
  1418  func WithWorkflowDomain(ctx Context, name string) Context {
  1419  	ctx1 := setWorkflowEnvOptionsIfNotExist(ctx)
  1420  	getWorkflowEnvOptions(ctx1).domain = common.StringPtr(name)
  1421  	return ctx1
  1422  }
  1423  
  1424  // WithWorkflowTaskList adds a task list to the context.
  1425  func WithWorkflowTaskList(ctx Context, name string) Context {
  1426  	ctx1 := setWorkflowEnvOptionsIfNotExist(ctx)
  1427  	getWorkflowEnvOptions(ctx1).taskListName = common.StringPtr(name)
  1428  	return ctx1
  1429  }
  1430  
  1431  // GetWorkflowTaskList retrieves current workflow tasklist from context
  1432  func GetWorkflowTaskList(ctx Context) *string {
  1433  	wo := getWorkflowEnvOptions(ctx)
  1434  	if wo == nil || wo.taskListName == nil {
  1435  		return nil
  1436  	}
  1437  	tl := *wo.taskListName // copy
  1438  	return &tl
  1439  }
  1440  
  1441  // WithWorkflowID adds a workflowID to the context.
  1442  func WithWorkflowID(ctx Context, workflowID string) Context {
  1443  	ctx1 := setWorkflowEnvOptionsIfNotExist(ctx)
  1444  	getWorkflowEnvOptions(ctx1).workflowID = workflowID
  1445  	return ctx1
  1446  }
  1447  
  1448  // WithExecutionStartToCloseTimeout adds a workflow execution timeout to the context.
  1449  // The current timeout resolution implementation is in seconds and uses math.Ceil(d.Seconds()) as the duration. But is
  1450  // subjected to change in the future.
  1451  func WithExecutionStartToCloseTimeout(ctx Context, d time.Duration) Context {
  1452  	ctx1 := setWorkflowEnvOptionsIfNotExist(ctx)
  1453  	getWorkflowEnvOptions(ctx1).executionStartToCloseTimeoutSeconds = common.Int32Ptr(common.Int32Ceil(d.Seconds()))
  1454  	return ctx1
  1455  }
  1456  
  1457  // WithWorkflowTaskStartToCloseTimeout adds a decision timeout to the context.
  1458  // The current timeout resolution implementation is in seconds and uses math.Ceil(d.Seconds()) as the duration. But is
  1459  // subjected to change in the future.
  1460  func WithWorkflowTaskStartToCloseTimeout(ctx Context, d time.Duration) Context {
  1461  	ctx1 := setWorkflowEnvOptionsIfNotExist(ctx)
  1462  	getWorkflowEnvOptions(ctx1).taskStartToCloseTimeoutSeconds = common.Int32Ptr(common.Int32Ceil(d.Seconds()))
  1463  	return ctx1
  1464  }
  1465  
  1466  // WithDataConverter adds DataConverter to the context.
  1467  func WithDataConverter(ctx Context, dc DataConverter) Context {
  1468  	if dc == nil {
  1469  		panic("data converter is nil for WithDataConverter")
  1470  	}
  1471  	ctx1 := setWorkflowEnvOptionsIfNotExist(ctx)
  1472  	getWorkflowEnvOptions(ctx1).dataConverter = dc
  1473  	return ctx1
  1474  }
  1475  
  1476  // withContextPropagators adds ContextPropagators to the context.
  1477  func withContextPropagators(ctx Context, contextPropagators []ContextPropagator) Context {
  1478  	ctx1 := setWorkflowEnvOptionsIfNotExist(ctx)
  1479  	getWorkflowEnvOptions(ctx1).contextPropagators = contextPropagators
  1480  	return ctx1
  1481  }
  1482  
  1483  // GetSignalChannel returns channel corresponding to the signal name.
  1484  func GetSignalChannel(ctx Context, signalName string) Channel {
  1485  	i := getWorkflowInterceptor(ctx)
  1486  	return i.GetSignalChannel(ctx, signalName)
  1487  }
  1488  
  1489  func (wc *workflowEnvironmentInterceptor) GetSignalChannel(ctx Context, signalName string) Channel {
  1490  	return getWorkflowEnvOptions(ctx).getSignalChannel(ctx, signalName)
  1491  }
  1492  
  1493  func newEncodedValue(value []byte, dc DataConverter) Value {
  1494  	if dc == nil {
  1495  		dc = getDefaultDataConverter()
  1496  	}
  1497  	return &EncodedValue{value, dc}
  1498  }
  1499  
  1500  // Get extract data from encoded data to desired value type. valuePtr is pointer to the actual value type.
  1501  func (b EncodedValue) Get(valuePtr interface{}) error {
  1502  	if !b.HasValue() {
  1503  		return ErrNoData
  1504  	}
  1505  	return decodeArg(b.dataConverter, b.value, valuePtr)
  1506  }
  1507  
  1508  // HasValue return whether there is value
  1509  func (b EncodedValue) HasValue() bool {
  1510  	return b.value != nil
  1511  }
  1512  
  1513  // SideEffect executes the provided function once, records its result into the workflow history. The recorded result on
  1514  // history will be returned without executing the provided function during replay. This guarantees the deterministic
  1515  // requirement for workflow as the exact same result will be returned in replay.
  1516  // Common use case is to run some short non-deterministic code in workflow, like getting random number or new UUID.
  1517  // The only way to fail SideEffect is to panic which causes decision task failure. The decision task after timeout is
  1518  // rescheduled and re-executed giving SideEffect another chance to succeed.
  1519  //
  1520  // Caution: do not use SideEffect to modify closures. Always retrieve result from SideEffect's encoded return value.
  1521  // For example this code is BROKEN:
  1522  //
  1523  //	// Bad example:
  1524  //	var random int
  1525  //	workflow.SideEffect(func(ctx workflow.Context) interface{} {
  1526  //	       random = rand.Intn(100)
  1527  //	       return nil
  1528  //	})
  1529  //	// random will always be 0 in replay, thus this code is non-deterministic
  1530  //	if random < 50 {
  1531  //	       ....
  1532  //	} else {
  1533  //	       ....
  1534  //	}
  1535  //
  1536  // On replay the provided function is not executed, the random will always be 0, and the workflow could takes a
  1537  // different path breaking the determinism.
  1538  //
  1539  // Here is the correct way to use SideEffect:
  1540  //
  1541  //	// Good example:
  1542  //	encodedRandom := SideEffect(func(ctx workflow.Context) interface{} {
  1543  //	      return rand.Intn(100)
  1544  //	})
  1545  //	var random int
  1546  //	encodedRandom.Get(&random)
  1547  //	if random < 50 {
  1548  //	       ....
  1549  //	} else {
  1550  //	       ....
  1551  //	}
  1552  func SideEffect(ctx Context, f func(ctx Context) interface{}) Value {
  1553  	i := getWorkflowInterceptor(ctx)
  1554  	return i.SideEffect(ctx, f)
  1555  }
  1556  
  1557  func (wc *workflowEnvironmentInterceptor) SideEffect(ctx Context, f func(ctx Context) interface{}) Value {
  1558  	dc := getDataConverterFromWorkflowContext(ctx)
  1559  	future, settable := NewFuture(ctx)
  1560  	wrapperFunc := func() ([]byte, error) {
  1561  		r := f(ctx)
  1562  		return encodeArg(dc, r)
  1563  	}
  1564  	resultCallback := func(result []byte, err error) {
  1565  		settable.Set(EncodedValue{result, dc}, err)
  1566  	}
  1567  	wc.env.SideEffect(wrapperFunc, resultCallback)
  1568  	var encoded EncodedValue
  1569  	if err := future.Get(ctx, &encoded); err != nil {
  1570  		panic(err)
  1571  	}
  1572  	return encoded
  1573  }
  1574  
  1575  // MutableSideEffect executes the provided function once, then it looks up the history for the value with the given id.
  1576  // If there is no existing value, then it records the function result as a value with the given id on history;
  1577  // otherwise, it compares whether the existing value from history has changed from the new function result by calling the
  1578  // provided equals function. If they are equal, it returns the value without recording a new one in history;
  1579  //
  1580  //	otherwise, it records the new value with the same id on history.
  1581  //
  1582  // Caution: do not use MutableSideEffect to modify closures. Always retrieve result from MutableSideEffect's encoded
  1583  // return value.
  1584  //
  1585  // The difference between MutableSideEffect() and SideEffect() is that every new SideEffect() call in non-replay will
  1586  // result in a new marker being recorded on history. However, MutableSideEffect() only records a new marker if the value
  1587  // changed. During replay, MutableSideEffect() will not execute the function again, but it will return the exact same
  1588  // value as it was returning during the non-replay run.
  1589  //
  1590  // One good use case of MutableSideEffect() is to access dynamically changing config without breaking determinism.
  1591  func MutableSideEffect(ctx Context, id string, f func(ctx Context) interface{}, equals func(a, b interface{}) bool) Value {
  1592  	i := getWorkflowInterceptor(ctx)
  1593  	return i.MutableSideEffect(ctx, id, f, equals)
  1594  }
  1595  
  1596  func (wc *workflowEnvironmentInterceptor) MutableSideEffect(ctx Context, id string, f func(ctx Context) interface{}, equals func(a, b interface{}) bool) Value {
  1597  	wrapperFunc := func() interface{} {
  1598  		return f(ctx)
  1599  	}
  1600  	return wc.env.MutableSideEffect(id, wrapperFunc, equals)
  1601  }
  1602  
  1603  // DefaultVersion is a version returned by GetVersion for code that wasn't versioned before
  1604  const DefaultVersion Version = -1
  1605  
  1606  // CadenceChangeVersion is used as search attributes key to find workflows with specific change version.
  1607  const CadenceChangeVersion = "CadenceChangeVersion"
  1608  
  1609  // GetVersion is used to safely perform backwards incompatible changes to workflow definitions.
  1610  // It is not allowed to update workflow code while there are workflows running as it is going to break
  1611  // determinism. The solution is to have both old code that is used to replay existing workflows
  1612  // as well as the new one that is used when it is executed for the first time.
  1613  // GetVersion returns maxSupported version when is executed for the first time. This version is recorded into the
  1614  // workflow history as a marker event. Even if maxSupported version is changed the version that was recorded is
  1615  // returned on replay. DefaultVersion constant contains version of code that wasn't versioned before.
  1616  // For example initially workflow has the following code:
  1617  //
  1618  //	err = workflow.ExecuteActivity(ctx, foo).Get(ctx, nil)
  1619  //
  1620  // it should be updated to
  1621  //
  1622  //	err = workflow.ExecuteActivity(ctx, bar).Get(ctx, nil)
  1623  //
  1624  // The backwards compatible way to execute the update is
  1625  //
  1626  //	v :=  GetVersion(ctx, "fooChange", DefaultVersion, 1)
  1627  //	if v  == DefaultVersion {
  1628  //	    err = workflow.ExecuteActivity(ctx, foo).Get(ctx, nil)
  1629  //	} else {
  1630  //	    err = workflow.ExecuteActivity(ctx, bar).Get(ctx, nil)
  1631  //	}
  1632  //
  1633  // Then bar has to be changed to baz:
  1634  //
  1635  //	v :=  GetVersion(ctx, "fooChange", DefaultVersion, 2)
  1636  //	if v  == DefaultVersion {
  1637  //	    err = workflow.ExecuteActivity(ctx, foo).Get(ctx, nil)
  1638  //	} else if v == 1 {
  1639  //	    err = workflow.ExecuteActivity(ctx, bar).Get(ctx, nil)
  1640  //	} else {
  1641  //	    err = workflow.ExecuteActivity(ctx, baz).Get(ctx, nil)
  1642  //	}
  1643  //
  1644  // Later when there are no workflow executions running DefaultVersion the correspondent branch can be removed:
  1645  //
  1646  //	v :=  GetVersion(ctx, "fooChange", 1, 2)
  1647  //	if v == 1 {
  1648  //	    err = workflow.ExecuteActivity(ctx, bar).Get(ctx, nil)
  1649  //	} else {
  1650  //	    err = workflow.ExecuteActivity(ctx, baz).Get(ctx, nil)
  1651  //	}
  1652  //
  1653  // It is recommended to keep the GetVersion() call even if single branch is left:
  1654  //
  1655  //	GetVersion(ctx, "fooChange", 2, 2)
  1656  //	err = workflow.ExecuteActivity(ctx, baz).Get(ctx, nil)
  1657  //
  1658  // The reason to keep it is: 1) it ensures that if there is older version execution still running, it will fail here
  1659  // and not proceed; 2) if you ever need to make more changes for “fooChange”, for example change activity from baz to qux,
  1660  // you just need to update the maxVersion from 2 to 3.
  1661  //
  1662  // Note that, you only need to preserve the first call to GetVersion() for each changeID. All subsequent call to GetVersion()
  1663  // with same changeID are safe to remove. However, if you really want to get rid of the first GetVersion() call as well,
  1664  // you can do so, but you need to make sure: 1) all older version executions are completed; 2) you can no longer use “fooChange”
  1665  // as changeID. If you ever need to make changes to that same part like change from baz to qux, you would need to use a
  1666  // different changeID like “fooChange-fix2”, and start minVersion from DefaultVersion again. The code would looks like:
  1667  //
  1668  //	v := workflow.GetVersion(ctx, "fooChange-fix2", workflow.DefaultVersion, 1)
  1669  //	if v == workflow.DefaultVersion {
  1670  //	  err = workflow.ExecuteActivity(ctx, baz, data).Get(ctx, nil)
  1671  //	} else {
  1672  //	  err = workflow.ExecuteActivity(ctx, qux, data).Get(ctx, nil)
  1673  //	}
  1674  func GetVersion(ctx Context, changeID string, minSupported, maxSupported Version) Version {
  1675  	i := getWorkflowInterceptor(ctx)
  1676  	return i.GetVersion(ctx, changeID, minSupported, maxSupported)
  1677  }
  1678  
  1679  func (wc *workflowEnvironmentInterceptor) GetVersion(ctx Context, changeID string, minSupported, maxSupported Version) Version {
  1680  	return wc.env.GetVersion(changeID, minSupported, maxSupported)
  1681  }
  1682  
  1683  // SetQueryHandler sets the query handler to handle workflow query. The queryType specify which query type this handler
  1684  // should handle. The handler must be a function that returns 2 values. The first return value must be a serializable
  1685  // result. The second return value must be an error. The handler function could receive any number of input parameters.
  1686  // All the input parameter must be serializable. You should call workflow.SetQueryHandler() at the beginning of the workflow
  1687  // code. When client calls Client.QueryWorkflow() to cadence server, a task will be generated on server that will be dispatched
  1688  // to a workflow worker, which will replay the history events and then execute a query handler based on the query type.
  1689  // The query handler will be invoked out of the context of the workflow, meaning that the handler code must not use cadence
  1690  // context to do things like workflow.NewChannel(), workflow.Go() or to call any workflow blocking functions like
  1691  // Channel.Get() or Future.Get(). Trying to do so in query handler code will fail the query and client will receive
  1692  // QueryFailedError.
  1693  // Example of workflow code that support query type "current_state":
  1694  //
  1695  //	func MyWorkflow(ctx workflow.Context, input string) error {
  1696  //	  currentState := "started" // this could be any serializable struct
  1697  //	  err := workflow.SetQueryHandler(ctx, "current_state", func() (string, error) {
  1698  //	    return currentState, nil
  1699  //	  })
  1700  //	  if err != nil {
  1701  //	    currentState = "failed to register query handler"
  1702  //	    return err
  1703  //	  }
  1704  //	  // your normal workflow code begins here, and you update the currentState as the code makes progress.
  1705  //	  currentState = "waiting timer"
  1706  //	  err = NewTimer(ctx, time.Hour).Get(ctx, nil)
  1707  //	  if err != nil {
  1708  //	    currentState = "timer failed"
  1709  //	    return err
  1710  //	  }
  1711  //
  1712  //	  currentState = "waiting activity"
  1713  //	  ctx = WithActivityOptions(ctx, myActivityOptions)
  1714  //	  err = ExecuteActivity(ctx, MyActivity, "my_input").Get(ctx, nil)
  1715  //	  if err != nil {
  1716  //	    currentState = "activity failed"
  1717  //	    return err
  1718  //	  }
  1719  //	  currentState = "done"
  1720  //	  return nil
  1721  //	}
  1722  func SetQueryHandler(ctx Context, queryType string, handler interface{}) error {
  1723  	i := getWorkflowInterceptor(ctx)
  1724  	return i.SetQueryHandler(ctx, queryType, handler)
  1725  }
  1726  
  1727  func (wc *workflowEnvironmentInterceptor) SetQueryHandler(ctx Context, queryType string, handler interface{}) error {
  1728  	if strings.HasPrefix(queryType, "__") {
  1729  		return errors.New("queryType starts with '__' is reserved for internal use")
  1730  	}
  1731  	return setQueryHandler(ctx, queryType, handler)
  1732  }
  1733  
  1734  // IsReplaying returns whether the current workflow code is replaying.
  1735  //
  1736  // Warning! Never make decisions, like schedule activity/childWorkflow/timer or send/wait on future/channel, based on
  1737  // this flag as it is going to break workflow determinism requirement.
  1738  // The only reasonable use case for this flag is to avoid some external actions during replay, like custom logging or
  1739  // metric reporting. Please note that Cadence already provide standard logging/metric via workflow.GetLogger(ctx) and
  1740  // workflow.GetMetricsScope(ctx), and those standard mechanism are replay-aware and it will automatically suppress during
  1741  // replay. Only use this flag if you need custom logging/metrics reporting, for example if you want to log to kafka.
  1742  //
  1743  // Warning! Any action protected by this flag should not fail or if it does fail should ignore that failure or panic
  1744  // on the failure. If workflow don't want to be blocked on those failure, it should ignore those failure; if workflow do
  1745  // want to make sure it proceed only when that action succeed then it should panic on that failure. Panic raised from a
  1746  // workflow causes decision task to fail and cadence server will rescheduled later to retry.
  1747  func IsReplaying(ctx Context) bool {
  1748  	i := getWorkflowInterceptor(ctx)
  1749  	return i.IsReplaying(ctx)
  1750  }
  1751  
  1752  func (wc *workflowEnvironmentInterceptor) IsReplaying(ctx Context) bool {
  1753  	return wc.env.IsReplaying()
  1754  }
  1755  
  1756  // HasLastCompletionResult checks if there is completion result from previous runs.
  1757  // This is used in combination with cron schedule. A workflow can be started with an optional cron schedule.
  1758  // If a cron workflow wants to pass some data to next schedule, it can return any data and that data will become
  1759  // available when next run starts.
  1760  // This HasLastCompletionResult() checks if there is such data available passing down from previous successful run.
  1761  func HasLastCompletionResult(ctx Context) bool {
  1762  	i := getWorkflowInterceptor(ctx)
  1763  	return i.HasLastCompletionResult(ctx)
  1764  }
  1765  
  1766  func (wc *workflowEnvironmentInterceptor) HasLastCompletionResult(ctx Context) bool {
  1767  	info := wc.GetWorkflowInfo(ctx)
  1768  	return len(info.lastCompletionResult) > 0
  1769  }
  1770  
  1771  // GetLastCompletionResult extract last completion result from previous run for this cron workflow.
  1772  // This is used in combination with cron schedule. A workflow can be started with an optional cron schedule.
  1773  // If a cron workflow wants to pass some data to next schedule, it can return any data and that data will become
  1774  // available when next run starts.
  1775  // This GetLastCompletionResult() extract the data into expected data structure.
  1776  func GetLastCompletionResult(ctx Context, d ...interface{}) error {
  1777  	i := getWorkflowInterceptor(ctx)
  1778  	return i.GetLastCompletionResult(ctx, d...)
  1779  }
  1780  
  1781  func (wc *workflowEnvironmentInterceptor) GetLastCompletionResult(ctx Context, d ...interface{}) error {
  1782  	info := wc.GetWorkflowInfo(ctx)
  1783  	if len(info.lastCompletionResult) == 0 {
  1784  		return ErrNoData
  1785  	}
  1786  
  1787  	encodedVal := newEncodedValues(info.lastCompletionResult, getDataConverterFromWorkflowContext(ctx))
  1788  	return encodedVal.Get(d...)
  1789  }
  1790  
  1791  // WithActivityOptions adds all options to the copy of the context.
  1792  // The current timeout resolution implementation is in seconds and uses math.Ceil(d.Seconds()) as the duration. But is
  1793  // subjected to change in the future.
  1794  func WithActivityOptions(ctx Context, options ActivityOptions) Context {
  1795  	ctx1 := setActivityParametersIfNotExist(ctx)
  1796  	eap := getActivityOptions(ctx1)
  1797  
  1798  	eap.TaskListName = options.TaskList
  1799  	eap.ScheduleToCloseTimeoutSeconds = common.Int32Ceil(options.ScheduleToCloseTimeout.Seconds())
  1800  	eap.StartToCloseTimeoutSeconds = common.Int32Ceil(options.StartToCloseTimeout.Seconds())
  1801  	eap.ScheduleToStartTimeoutSeconds = common.Int32Ceil(options.ScheduleToStartTimeout.Seconds())
  1802  	eap.HeartbeatTimeoutSeconds = common.Int32Ceil(options.HeartbeatTimeout.Seconds())
  1803  	eap.WaitForCancellation = options.WaitForCancellation
  1804  	eap.ActivityID = common.StringPtr(options.ActivityID)
  1805  	eap.RetryPolicy = convertRetryPolicy(options.RetryPolicy)
  1806  	return ctx1
  1807  }
  1808  
  1809  // WithLocalActivityOptions adds local activity options to the copy of the context.
  1810  // The current timeout resolution implementation is in seconds and uses math.Ceil(d.Seconds()) as the duration. But is
  1811  // subjected to change in the future.
  1812  func WithLocalActivityOptions(ctx Context, options LocalActivityOptions) Context {
  1813  	ctx1 := setLocalActivityParametersIfNotExist(ctx)
  1814  	opts := getLocalActivityOptions(ctx1)
  1815  
  1816  	opts.ScheduleToCloseTimeoutSeconds = common.Int32Ceil(options.ScheduleToCloseTimeout.Seconds())
  1817  	opts.RetryPolicy = options.RetryPolicy
  1818  	return ctx1
  1819  }
  1820  
  1821  // WithTaskList adds a task list to the copy of the context.
  1822  // Note this shall not confuse with WithWorkflowTaskList. This is the tasklist for activities
  1823  func WithTaskList(ctx Context, name string) Context {
  1824  	ctx1 := setActivityParametersIfNotExist(ctx)
  1825  	getActivityOptions(ctx1).TaskListName = name
  1826  	return ctx1
  1827  }
  1828  
  1829  // GetActivityTaskList retrieves tasklist info from context
  1830  func GetActivityTaskList(ctx Context) *string {
  1831  	ao := getActivityOptions(ctx)
  1832  	if ao == nil {
  1833  		return nil
  1834  	}
  1835  	tl := ao.TaskListName // copy
  1836  	return &tl
  1837  }
  1838  
  1839  // WithScheduleToCloseTimeout adds a timeout to the copy of the context.
  1840  // The current timeout resolution implementation is in seconds and uses math.Ceil(d.Seconds()) as the duration. But is
  1841  // subjected to change in the future.
  1842  func WithScheduleToCloseTimeout(ctx Context, d time.Duration) Context {
  1843  	ctx1 := setActivityParametersIfNotExist(ctx)
  1844  	getActivityOptions(ctx1).ScheduleToCloseTimeoutSeconds = common.Int32Ceil(d.Seconds())
  1845  	return ctx1
  1846  }
  1847  
  1848  // WithScheduleToStartTimeout adds a timeout to the copy of the context.
  1849  // The current timeout resolution implementation is in seconds and uses math.Ceil(d.Seconds()) as the duration. But is
  1850  // subjected to change in the future.
  1851  func WithScheduleToStartTimeout(ctx Context, d time.Duration) Context {
  1852  	ctx1 := setActivityParametersIfNotExist(ctx)
  1853  	getActivityOptions(ctx1).ScheduleToStartTimeoutSeconds = common.Int32Ceil(d.Seconds())
  1854  	return ctx1
  1855  }
  1856  
  1857  // WithStartToCloseTimeout adds a timeout to the copy of the context.
  1858  // The current timeout resolution implementation is in seconds and uses math.Ceil(d.Seconds()) as the duration. But is
  1859  // subjected to change in the future.
  1860  func WithStartToCloseTimeout(ctx Context, d time.Duration) Context {
  1861  	ctx1 := setActivityParametersIfNotExist(ctx)
  1862  	getActivityOptions(ctx1).StartToCloseTimeoutSeconds = common.Int32Ceil(d.Seconds())
  1863  	return ctx1
  1864  }
  1865  
  1866  // WithHeartbeatTimeout adds a timeout to the copy of the context.
  1867  // The current timeout resolution implementation is in seconds and uses math.Ceil(d.Seconds()) as the duration. But is
  1868  // subjected to change in the future.
  1869  func WithHeartbeatTimeout(ctx Context, d time.Duration) Context {
  1870  	ctx1 := setActivityParametersIfNotExist(ctx)
  1871  	getActivityOptions(ctx1).HeartbeatTimeoutSeconds = common.Int32Ceil(d.Seconds())
  1872  	return ctx1
  1873  }
  1874  
  1875  // WithWaitForCancellation adds wait for the cacellation to the copy of the context.
  1876  func WithWaitForCancellation(ctx Context, wait bool) Context {
  1877  	ctx1 := setActivityParametersIfNotExist(ctx)
  1878  	getActivityOptions(ctx1).WaitForCancellation = wait
  1879  	return ctx1
  1880  }
  1881  
  1882  // WithRetryPolicy adds retry policy to the copy of the context
  1883  func WithRetryPolicy(ctx Context, retryPolicy RetryPolicy) Context {
  1884  	ctx1 := setActivityParametersIfNotExist(ctx)
  1885  	getActivityOptions(ctx1).RetryPolicy = convertRetryPolicy(&retryPolicy)
  1886  	return ctx1
  1887  }
  1888  
  1889  func convertRetryPolicy(retryPolicy *RetryPolicy) *s.RetryPolicy {
  1890  	if retryPolicy == nil {
  1891  		return nil
  1892  	}
  1893  	if retryPolicy.BackoffCoefficient == 0 {
  1894  		retryPolicy.BackoffCoefficient = backoff.DefaultBackoffCoefficient
  1895  	}
  1896  	thriftRetryPolicy := s.RetryPolicy{
  1897  		InitialIntervalInSeconds:    common.Int32Ptr(common.Int32Ceil(retryPolicy.InitialInterval.Seconds())),
  1898  		MaximumIntervalInSeconds:    common.Int32Ptr(common.Int32Ceil(retryPolicy.MaximumInterval.Seconds())),
  1899  		BackoffCoefficient:          &retryPolicy.BackoffCoefficient,
  1900  		MaximumAttempts:             &retryPolicy.MaximumAttempts,
  1901  		NonRetriableErrorReasons:    retryPolicy.NonRetriableErrorReasons,
  1902  		ExpirationIntervalInSeconds: common.Int32Ptr(common.Int32Ceil(retryPolicy.ExpirationInterval.Seconds())),
  1903  	}
  1904  	return &thriftRetryPolicy
  1905  }