Skip to content

Commit 4ef37a2

Browse files
committed
add public GetVersion
1 parent 243e756 commit 4ef37a2

File tree

3 files changed

+92
-17
lines changed

3 files changed

+92
-17
lines changed

internal/internal_event_handlers.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,7 @@ func (wc *workflowEnvironmentImpl) GetVersion(changeID string, minSupported, max
612612
}
613613

614614
// Apply options to determine which version to use
615-
options := &getVersionOptions{}
615+
options := &GetVersionOptions{}
616616
for _, opt := range opts {
617617
opt(options)
618618
}
@@ -625,11 +625,11 @@ func (wc *workflowEnvironmentImpl) GetVersion(changeID string, minSupported, max
625625
version = DefaultVersion
626626

627627
// If ExecuteWithVersion option is used, use the custom version provided
628-
case options.customVersion != nil:
629-
version = *options.customVersion
628+
case options.CustomVersion != nil:
629+
version = *options.CustomVersion
630630

631631
// If ExecuteWithMinVersion option is set, use the minimum supported version
632-
case options.useMinVersion:
632+
case options.UseMinVersion:
633633
version = minSupported
634634

635635
// Otherwise, use the maximum supported version

internal/workflow.go

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1567,17 +1567,18 @@ const DefaultVersion Version = -1
15671567
// CadenceChangeVersion is used as search attributes key to find workflows with specific change version.
15681568
const CadenceChangeVersion = "CadenceChangeVersion"
15691569

1570-
// GetVersionOption represents a function that configures GetVersion behavior
1571-
type GetVersionOption func(*getVersionOptions)
1570+
// GetVersionOption configures GetVersion behavior
1571+
type GetVersionOption func(*GetVersionOptions)
15721572

1573-
type getVersionOptions struct {
1574-
// customVersion is used to force GetVersion to return a specific version
1573+
// GetVersionOptions contains options for GetVersion
1574+
type GetVersionOptions struct {
1575+
// CustomVersion is used to force GetVersion to return a specific version
15751576
// instead of maxSupported version. Set up via ExecuteWithVersion option.
1576-
customVersion *Version
1577+
CustomVersion *Version
15771578

1578-
// useMinVersion is used to force GetVersion to return minSupported version
1579+
// UseMinVersion is used to force GetVersion to return minSupported version
15791580
// instead of maxSupported version. Set up via ExecuteWithMinVersion option.
1580-
useMinVersion bool
1581+
UseMinVersion bool
15811582
}
15821583

15831584
// ExecuteWithVersion returns a GetVersionOption that forces a specific version to be returned
@@ -1637,17 +1638,17 @@ type getVersionOptions struct {
16371638
// ExecuteWithVersion option is useful when you want to ensure that your changes can be safely rolled back if needed, as
16381639
// both versions of the workflow code are compatible with each other.
16391640
func ExecuteWithVersion(version Version) GetVersionOption {
1640-
return func(o *getVersionOptions) {
1641-
o.customVersion = &version
1641+
return func(o *GetVersionOptions) {
1642+
o.CustomVersion = &version
16421643
}
16431644
}
16441645

16451646
// ExecuteWithMinVersion returns a GetVersionOption that makes GetVersion return minSupported version
16461647
// when executed for the first time, instead of returning maxSupported version.
16471648
// To see how this option can be used, see the ExecuteWithVersion option
16481649
func ExecuteWithMinVersion() GetVersionOption {
1649-
return func(o *getVersionOptions) {
1650-
o.useMinVersion = true
1650+
return func(o *GetVersionOptions) {
1651+
o.UseMinVersion = true
16511652
}
16521653
}
16531654

workflow/workflow.go

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ type (
4545
// Version represents a change version. See GetVersion call.
4646
Version = internal.Version
4747

48+
// GetVersionOption configures GetVersion behaviour
49+
GetVersionOption = internal.GetVersionOption
50+
4851
// ChildWorkflowOptions stores all child workflow specific parameters that will be stored inside of a Context.
4952
ChildWorkflowOptions = internal.ChildWorkflowOptions
5053

@@ -353,6 +356,77 @@ func MutableSideEffect(ctx Context, id string, f func(ctx Context) interface{},
353356
// DefaultVersion is a version returned by GetVersion for code that wasn't versioned before
354357
const DefaultVersion Version = internal.DefaultVersion
355358

359+
// ExecuteWithVersion returns a GetVersionOption that forces a specific version to be returned
360+
// when executed for the first time, instead of returning maxSupported version.
361+
//
362+
// This option can be used when you want to separate the versioning of the workflow code and
363+
// activation of the new logic in the workflow code, to ensure that your changes can be safely rolled back
364+
// if needed. For example, initially a workflow has the following code:
365+
//
366+
// err = workflow.ExecuteActivity(ctx, foo).Get(ctx, nil)
367+
//
368+
// It should be updated to:
369+
//
370+
// err = workflow.ExecuteActivity(ctx, bar).Get(ctx, nil)
371+
//
372+
// Step 1
373+
// To roll out your changes safely, both versions of your workflow code should be compatible with each other.
374+
// To achieve that, you can use GetVersion with ExecuteWithVersion option.
375+
// When GetVersion is executed for the first time, it will return DefaultVersion instead of maxSupported version:
376+
//
377+
// v := GetVersion(ctx, "fooChange", DefaultVersion, 1, ExecuteWithVersion(DefaultVersion))
378+
// if v == DefaultVersion {
379+
// err = workflow.ExecuteActivity(ctx, foo).Get(ctx, nil)
380+
// } else {
381+
// err = workflow.ExecuteActivity(ctx, bar).Get(ctx, nil)
382+
// }
383+
//
384+
// At this step, the previous version of the code supports only DefaultVersion, however new version of the code
385+
// supports both DefaultVersion and 1. At the same time, the new version of the code is not yet activated,
386+
// so the workflow started on the new version of the code will still execute foo activity - previous version of the code.
387+
// This makes it possible to safely roll back your changes if needed, as the previous code supports DefaultVersion.
388+
//
389+
// Step 2
390+
// When the previous version of the code is no longer running, there is no need to start new workflow executions
391+
// with DefaultVersion anymore, and you can the maxSupported version to activate the new code. To achieve that you can
392+
// remove the usage of ExecuteWithVersion option. When GetVersion is executed for the first time, it will return maxSupported version:
393+
//
394+
// v := GetVersion(ctx, "fooChange", DefaultVersion, 1)
395+
// if v == DefaultVersion {
396+
// err = workflow.ExecuteActivity(ctx, foo).Get(ctx, nil)
397+
// } else {
398+
// err = workflow.ExecuteActivity(ctx, bar).Get(ctx, nil)
399+
// }
400+
//
401+
// At this step, the previous and old versions of the code support both versions DefaultVersion and 1,
402+
// however the new version of the code is activated, so the workflow started on the new version of the code
403+
// will execute bar activity - new version of the code. This makes it possible to safely roll back your changes if needed,
404+
// because both versions of the code support both versions DefaultVersion and 1.
405+
//
406+
// Step 3
407+
// When there are no running previous version of the code and there are no workflow executions
408+
// running DefaultVersion the correspondent branch can be removed:
409+
//
410+
// GetVersion(ctx, "fooChange", 1, 1)
411+
// err = workflow.ExecuteActivity(ctx, bar).Get(ctx, nil)
412+
//
413+
// ExecuteWithVersion option is useful when you want to ensure that your changes can be safely rolled back if needed, as
414+
// both versions of the workflow code are compatible with each other.
415+
func ExecuteWithVersion(version Version) GetVersionOption {
416+
return func(o *internal.GetVersionOptions) {
417+
o.CustomVersion = &version
418+
}
419+
}
420+
421+
// ExecuteWithMinVersion returns a GetVersionOption that makes GetVersion return minSupported version
422+
// when executed for the first time, instead of returning maxSupported version.
423+
// To see how this option can be used, see the ExecuteWithVersion option
424+
func ExecuteWithMinVersion() GetVersionOption {
425+
return func(o *internal.GetVersionOptions) {
426+
o.UseMinVersion = true
427+
}
428+
}
429+
356430
// GetVersion is used to safely perform backwards incompatible changes to workflow definitions.
357431
// It is not allowed to update workflow code while there are workflows running as it is going to break
358432
// determinism. The solution is to have both old code that is used to replay existing workflows
@@ -418,8 +492,8 @@ const DefaultVersion Version = internal.DefaultVersion
418492
// } else {
419493
// err = workflow.ExecuteActivity(ctx, qux, data).Get(ctx, nil)
420494
// }
421-
func GetVersion(ctx Context, changeID string, minSupported, maxSupported Version) Version {
422-
return internal.GetVersion(ctx, changeID, minSupported, maxSupported)
495+
func GetVersion(ctx Context, changeID string, minSupported, maxSupported Version, opts ...GetVersionOption) Version {
496+
return internal.GetVersion(ctx, changeID, minSupported, maxSupported, opts...)
423497
}
424498

425499
// SetQueryHandler sets the query handler to handle workflow query. The queryType specify which query type this handler

0 commit comments

Comments
 (0)