diff --git a/internal/internal_worker.go b/internal/internal_worker.go index 76885b413..ebe658b51 100644 --- a/internal/internal_worker.go +++ b/internal/internal_worker.go @@ -700,6 +700,21 @@ func (r *registry) RegisterWorkflowWithOptions( if len(alias) > 0 && r.workflowAliasMap != nil { r.workflowAliasMap[fnName] = alias } + + if r.workflowAliasMap != nil { + // If workflowAliasMap[f] = a and workflowFuncMap[f] exists, invoking "f" will actually trigger workflowFuncMap[a]. + // Unfortunately this is expected behavior when the user disobeys us by not turning on DisableRegistrationAliasing; + // see TestAliasStringNameClash, TestAliasUnqualifiedNameClash, and TestAliasAntialiasing. At least we can warn them. + a, ok1 := r.workflowAliasMap[fnName] + _, ok2 := r.workflowFuncMap[fnName] + if ok1 && ok2 { + fmt.Printf("WARNING: Workflow alias collision detected: invoking workflow \"%v\" will actually trigger \"%v\". Consider turning on 'WorkerOptions.DisableRegistrationAliasing'.\n", fnName, a) + } + a, ok3 := r.workflowAliasMap[registerName] + if ok3 { + fmt.Printf("WARNING: Workflow alias collision detected: invoking workflow \"%v\" will actually trigger \"%v\". Consider turning on 'WorkerOptions.DisableRegistrationAliasing'.\n", registerName, a) + } + } } func (r *registry) RegisterDynamicWorkflow(wf interface{}, options DynamicRegisterWorkflowOptions) { @@ -780,6 +795,21 @@ func (r *registry) RegisterActivityWithOptions( if len(alias) > 0 && r.activityAliasMap != nil { r.activityAliasMap[fnName] = alias } + + if r.activityAliasMap != nil { + // If activityAliasMap[f] = a and activityFuncMap[f] exists, invoking "f" will actually trigger activityFuncMap[a]. + // Unfortunately this is expected behavior when the user disobeys us by not turning on DisableRegistrationAliasing; + // see TestAliasStringNameClash, TestAliasUnqualifiedNameClash, and TestAliasAntialiasing. At least we can warn them. + a, ok1 := r.activityAliasMap[fnName] + _, ok2 := r.activityFuncMap[fnName] + if ok1 && ok2 { + fmt.Printf("WARNING: Activity alias collision detected: invoking activity \"%v\" will actually trigger \"%v\". Consider turning on 'WorkerOptions.DisableRegistrationAliasing'.\n", fnName, a) + } + a, ok3 := r.activityAliasMap[registerName] + if ok3 { + fmt.Printf("WARNING: Activity alias collision detected: invoking activity \"%v\" will actually trigger \"%v\". Consider turning on 'WorkerOptions.DisableRegistrationAliasing'.\n", registerName, a) + } + } } func (r *registry) registerActivityStructWithOptions(aStruct interface{}, options RegisterActivityOptions) error { diff --git a/internal/internal_worker_test.go b/internal/internal_worker_test.go index c08bb1aea..aa5e900c2 100644 --- a/internal/internal_worker_test.go +++ b/internal/internal_worker_test.go @@ -3384,6 +3384,45 @@ func TestAliasUnqualifiedNameClash(t *testing.T) { require.Equal(t, "func1", executeWorkflow(true)) } +type aliasReproV1 struct{} +func (aliasReproV1) MyActivity(context.Context) (string, error) { return "func1", nil } +type aliasReproV2 struct{} +func (aliasReproV2) MyActivity(context.Context) (string, error) { return "func2", nil } + +func TestAliasAntialiasing(t *testing.T) { + w := func(ctx Context) (string, error) { + ctx = WithActivityOptions(ctx, ActivityOptions{ScheduleToCloseTimeout: 5 * time.Second}) + var str1 string + if err := ExecuteActivity(ctx, "MyActivity").Get(ctx, &str1); err != nil { + return "", err + } + var str2 string + if err := ExecuteActivity(ctx, "MyActivity_v2").Get(ctx, &str2); err != nil { + return "", err + } + return str1 + "-" + str2, nil + } + + executeWorkflow := func(disableAlias bool) (result string) { + var suite WorkflowTestSuite + suite.SetDisableRegistrationAliasing(disableAlias) + env := suite.NewTestWorkflowEnvironment() + env.RegisterActivity(aliasReproV1{}.MyActivity) + env.RegisterActivityWithOptions( + aliasReproV2{}.MyActivity, + RegisterActivityOptions{Name: "MyActivity_v2"}, + ) + env.ExecuteWorkflow(w) + require.NoError(t, env.GetWorkflowResult(&result)) + return + } + + // Without disabling alias registration, the alias will choose aliasReproV2 both times. + // With disabling alias, we can disambiguate them properly. + require.Equal(t, "func2-func2", executeWorkflow(false)) + require.Equal(t, "func1-func2", executeWorkflow(true)) +} + func (s *internalWorkerTestSuite) TestReservedTemporalName() { // workflow worker := createWorker(s.service) diff --git a/internal/worker.go b/internal/worker.go index b93eec33d..acf86b463 100644 --- a/internal/worker.go +++ b/internal/worker.go @@ -326,8 +326,7 @@ type ( // Users are strongly recommended to set this as true if they register any // workflow or activity functions with custom names. By leaving this as // false, the historical default, ambiguity can occur between function names - // and aliased names when not using string names when executing child - // workflow or activities. + // and aliased names. DisableRegistrationAliasing bool // Assign a BuildID to this worker. This replaces the deprecated binary checksum concept,