Skip to content

Fix reuse + conflict policy validation#9728

Merged
stephanos merged 5 commits intomainfrom
stephanos/fix-conflict-policy-validation
Apr 9, 2026
Merged

Fix reuse + conflict policy validation#9728
stephanos merged 5 commits intomainfrom
stephanos/fix-conflict-policy-validation

Conversation

@stephanos
Copy link
Copy Markdown
Contributor

@stephanos stephanos commented Mar 28, 2026

What changed?

Fix setting of default reuse + conflict policy.

Why?

Currently when the frontend request is retried, the request can suddenly be in a bad state that doesn't pass validation if the conflict policy was originally unset and the reuse policy was terminate-if-running because setting the defaults will set a conflict policy - which is not allowed when reuse policy terminate-if-running is used.

How did you test it?

  • built
  • run locally and tested manually
  • covered by existing tests
  • added new unit test(s)
  • added new functional test(s)

)
}

func MigrateWorkflowIdReusePolicyForRunningWorkflow(
Copy link
Copy Markdown
Contributor Author

@stephanos stephanos Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved this into SetDefaultWorkflowIdPolicies

@stephanos stephanos force-pushed the stephanos/fix-conflict-policy-validation branch from c4dd8c4 to 3260462 Compare March 28, 2026 00:40
Comment thread common/enums/defaults.go
enumspb "go.temporal.io/api/enums/v1"
)

func SetDefaultWorkflowIdReusePolicy(f *enumspb.WorkflowIdReusePolicy) {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still used elsewhere

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should it be used elsewhere by itself? or should we always use a function that handles these two together?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's used in handleCommandStartChildWorkflow and child workflows don't have a conflict policy

@stephanos stephanos force-pushed the stephanos/fix-conflict-policy-validation branch 4 times, most recently from 0dd2220 to 2b67de7 Compare March 28, 2026 00:49
Comment thread common/enums/defaults.go Outdated

func SetDefaultWorkflowIdConflictPolicy(
// SetDefaultWorkflowIdPolicies migrates and applies defaults to both WorkflowId policies.
func SetDefaultWorkflowIdPolicies(
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One to rule them all

@stephanos stephanos force-pushed the stephanos/fix-conflict-policy-validation branch 2 times, most recently from 3bf57ef to 98b7061 Compare March 28, 2026 00:52
@stephanos stephanos changed the title Fix reuse/conflict policy validation Fix reuse + conflict policy validation Mar 28, 2026
@stephanos stephanos force-pushed the stephanos/fix-conflict-policy-validation branch from 98b7061 to e76f4d6 Compare March 28, 2026 00:56
@stephanos stephanos force-pushed the stephanos/fix-conflict-policy-validation branch from e76f4d6 to 97fa22b Compare March 28, 2026 00:57
Comment thread common/enums/defaults.go
if *reusePolicy == enumspb.WORKFLOW_ID_REUSE_POLICY_TERMINATE_IF_RUNNING {
// Migrate the deprecated TERMINATE_IF_RUNNING.
*conflictPolicy = enumspb.WORKFLOW_ID_CONFLICT_POLICY_TERMINATE_EXISTING
*reusePolicy = enumspb.WORKFLOW_ID_REUSE_POLICY_ALLOW_DUPLICATE
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same default as in MigrateWorkflowIdReusePolicyForRunningWorkflow

@stephanos stephanos marked this pull request as ready for review March 28, 2026 01:00
@stephanos stephanos requested review from a team as code owners March 28, 2026 01:00
Comment thread common/enums/defaults.go
enumspb "go.temporal.io/api/enums/v1"
)

func SetDefaultWorkflowIdReusePolicy(f *enumspb.WorkflowIdReusePolicy) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should it be used elsewhere by itself? or should we always use a function that handles these two together?

enumspb.WORKFLOW_ID_CONFLICT_POLICY_USE_EXISTING)

api.MigrateWorkflowIdReusePolicyForRunningWorkflow(
enums.SetDefaultWorkflowIDPolicies(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be moved higher near the start of this function, like ones in workflow_handler.go and startworkflow/api.go? it's above "validation" here but could be earlier.

also, if we do this in frontend, why do we need to do it here?

Copy link
Copy Markdown
Contributor Author

@stephanos stephanos Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, if we do this in frontend, why do we need to do it here?

I'll answer in https://github.com/temporalio/temporal/pull/9728/changes#r3030624859

return nil, err
}

// TODO: remove this call in 1.25
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is the todo wrong? should we remove the call now (long past 1.25)?

Copy link
Copy Markdown
Contributor Author

@stephanos stephanos Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I considered removing the calls because IIRC this was only needed for the "mixed brain" scenario (what the comment implies). When I put the PR together I wasn't quite sure and opted to leave it - but thinking about it more, unless you can think of a reason to keep it, it seems safe to remove altogether (same in service/history/api/startworkflow/api.go). I'll do that.

@stephanos stephanos force-pushed the stephanos/fix-conflict-policy-validation branch from 5d53822 to c03bd51 Compare April 2, 2026 22:33
@@ -120,15 +119,6 @@ func NewStarter(
func (s *Starter) prepare(ctx context.Context) error {
request := s.request.StartRequest

// TODO: remove this call in 1.25
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dropping these now since they were only needed in-between versions but now frontend ensures policies are correct

@stephanos stephanos requested a review from dnr April 2, 2026 22:37
@stephanos stephanos merged commit 0f8e068 into main Apr 9, 2026
46 checks passed
@stephanos stephanos deleted the stephanos/fix-conflict-policy-validation branch April 9, 2026 22:49
stephanos added a commit that referenced this pull request Apr 13, 2026
## What changed?

Fix setting of default reuse + conflict policy.

## Why?

Currently when the frontend request is retried, the request can suddenly
be in a bad state that doesn't pass validation if the conflict policy
was originally unset and the reuse policy was terminate-if-running
because setting the defaults will set a conflict policy - which is not
allowed when reuse policy terminate-if-running is used.

## How did you test it?
- [ ] built
- [ ] run locally and tested manually
- [ ] covered by existing tests
- [x] added new unit test(s)
- [ ] added new functional test(s)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants