@@ -604,6 +604,36 @@ type (
604604 // NOTE: Experimental
605605 TimerOptions TimerOptions
606606 }
607+
608+ // SideEffectOptions are options for executing a side effect.
609+ //
610+ // NOTE: Experimental
611+ //
612+ // Exposed as: [go.temporal.io/sdk/workflow.SideEffectOptions]
613+ SideEffectOptions struct {
614+ // Summary is a single-line summary of this side effect that will appear in UI/CLI.
615+ // This can be in single-line Temporal Markdown format.
616+ //
617+ // Optional: defaults to none/empty.
618+ //
619+ // NOTE: Experimental
620+ Summary string
621+ }
622+
623+ // MutableSideEffectOptions are options for executing a mutable side effect.
624+ //
625+ // NOTE: Experimental
626+ //
627+ // Exposed as: [go.temporal.io/sdk/workflow.MutableSideEffectOptions]
628+ MutableSideEffectOptions struct {
629+ // Summary is a single-line summary of this side effect that will appear in UI/CLI.
630+ // This can be in single-line Temporal Markdown format.
631+ //
632+ // Optional: defaults to none/empty.
633+ //
634+ // NOTE: Experimental
635+ Summary string
636+ }
607637)
608638
609639// Await blocks the calling thread until condition() returns true
@@ -2057,12 +2087,32 @@ func (b EncodedValue) HasValue() bool {
20572087//
20582088// Exposed as: [go.temporal.io/sdk/workflow.SideEffect]
20592089func SideEffect (ctx Context , f func (ctx Context ) interface {}) converter.EncodedValue {
2090+ return SideEffectWithOptions (ctx , SideEffectOptions {}, f )
2091+ }
2092+
2093+ // SideEffectWithOptions executes the provided function once, records its result into the workflow history.
2094+ // The recorded result on history will be returned without executing the provided function during replay.
2095+ // This guarantees the deterministic requirement for workflow as the exact same result will be returned in replay.
2096+ // Common use case is to run some short non-deterministic code in workflow, like getting random number or new UUID.
2097+ // The only way to fail SideEffect is to panic which causes workflow task failure. The workflow task after timeout is
2098+ // rescheduled and re-executed giving SideEffect another chance to succeed.
2099+ //
2100+ // The options parameter allows specifying additional options like a summary that will be displayed in UI/CLI.
2101+ //
2102+ // NOTE: Experimental
2103+ //
2104+ // Exposed as: [go.temporal.io/sdk/workflow.SideEffectWithOptions]
2105+ func SideEffectWithOptions (ctx Context , options SideEffectOptions , f func (ctx Context ) interface {}) converter.EncodedValue {
20602106 assertNotInReadOnlyState (ctx )
20612107 i := getWorkflowOutboundInterceptor (ctx )
2062- return i .SideEffect (ctx , f )
2108+ return i .SideEffectWithOptions (ctx , options , f )
20632109}
20642110
20652111func (wc * workflowEnvironmentInterceptor ) SideEffect (ctx Context , f func (ctx Context ) interface {}) converter.EncodedValue {
2112+ return wc .SideEffectWithOptions (ctx , SideEffectOptions {}, f )
2113+ }
2114+
2115+ func (wc * workflowEnvironmentInterceptor ) SideEffectWithOptions (ctx Context , options SideEffectOptions , f func (ctx Context ) interface {}) converter.EncodedValue {
20662116 dc := getDataConverterFromWorkflowContext (ctx )
20672117 future , settable := NewFuture (ctx )
20682118 wrapperFunc := func () (* commonpb.Payloads , error ) {
@@ -2075,7 +2125,7 @@ func (wc *workflowEnvironmentInterceptor) SideEffect(ctx Context, f func(ctx Con
20752125 resultCallback := func (result * commonpb.Payloads , err error ) {
20762126 settable .Set (EncodedValue {result , dc }, err )
20772127 }
2078- wc .env .SideEffect (wrapperFunc , resultCallback )
2128+ wc .env .SideEffect (wrapperFunc , resultCallback , options . Summary )
20792129 var encoded EncodedValue
20802130 if err := future .Get (ctx , & encoded ); err != nil {
20812131 panic (err )
@@ -2102,19 +2152,38 @@ func (wc *workflowEnvironmentInterceptor) SideEffect(ctx Context, f func(ctx Con
21022152//
21032153// Exposed as: [go.temporal.io/sdk/workflow.MutableSideEffect]
21042154func MutableSideEffect (ctx Context , id string , f func (ctx Context ) interface {}, equals func (a , b interface {}) bool ) converter.EncodedValue {
2155+ return MutableSideEffectWithOptions (ctx , id , MutableSideEffectOptions {}, f , equals )
2156+ }
2157+
2158+ // MutableSideEffectWithOptions executes the provided function once, then it looks up the history for the value with the given id.
2159+ // If there is no existing value, then it records the function result as a value with the given id on history;
2160+ // otherwise, it compares whether the existing value from history has changed from the new function result by calling
2161+ // the provided equals function. If they are equal, it returns the value without recording a new one in history;
2162+ // otherwise, it records the new value with the same id on history.
2163+ //
2164+ // The options parameter allows specifying additional options like a summary that will be displayed in UI/CLI.
2165+ //
2166+ // NOTE: Experimental
2167+ //
2168+ // Exposed as: [go.temporal.io/sdk/workflow.MutableSideEffectWithOptions]
2169+ func MutableSideEffectWithOptions (ctx Context , id string , options MutableSideEffectOptions , f func (ctx Context ) interface {}, equals func (a , b interface {}) bool ) converter.EncodedValue {
21052170 assertNotInReadOnlyState (ctx )
21062171 i := getWorkflowOutboundInterceptor (ctx )
2107- return i .MutableSideEffect (ctx , id , f , equals )
2172+ return i .MutableSideEffectWithOptions (ctx , id , options , f , equals )
21082173}
21092174
21102175func (wc * workflowEnvironmentInterceptor ) MutableSideEffect (ctx Context , id string , f func (ctx Context ) interface {}, equals func (a , b interface {}) bool ) converter.EncodedValue {
2176+ return wc .MutableSideEffectWithOptions (ctx , id , MutableSideEffectOptions {}, f , equals )
2177+ }
2178+
2179+ func (wc * workflowEnvironmentInterceptor ) MutableSideEffectWithOptions (ctx Context , id string , options MutableSideEffectOptions , f func (ctx Context ) interface {}, equals func (a , b interface {}) bool ) converter.EncodedValue {
21112180 wrapperFunc := func () interface {} {
21122181 coroutineState := getState (ctx )
21132182 defer coroutineState .dispatcher .setIsReadOnly (false )
21142183 coroutineState .dispatcher .setIsReadOnly (true )
21152184 return f (ctx )
21162185 }
2117- return wc .env .MutableSideEffect (id , wrapperFunc , equals )
2186+ return wc .env .MutableSideEffect (id , wrapperFunc , equals , options . Summary )
21182187}
21192188
21202189// DefaultVersion is a version returned by GetVersion for code that wasn't versioned before
0 commit comments