Skip to content

Deduplicate ResetWorkflowExecution requests - #12042

Open
Qian-Cheng-nju wants to merge 1 commit into
temporalio:mainfrom
Qian-Cheng-nju:fix/reset-workflow-request-idempotency
Open

Deduplicate ResetWorkflowExecution requests#12042
Qian-Cheng-nju wants to merge 1 commit into
temporalio:mainfrom
Qian-Cheng-nju:fix/reset-workflow-request-idempotency

Conversation

@Qian-Cheng-nju

Copy link
Copy Markdown

What changed?

Persist the public reset request ID in the new reset run's existing RequestIds map and use that marker when deduplicating ResetWorkflowExecution retries.

The marker does not replace CreateRequestId, which continues to hold the original workflow-start request ID used by scheduler callback identity. It is distinguishable from history-event request IDs and CHASM-attached request IDs, and does not require a persistence schema change. History-based rebuild paths preserve the marker from the existing mutable state because no history event can recreate it. Internal reset paths do not add a public reset marker.

Unit tests cover marker classification and preservation during mutable-state rebuilds. The functional test covers immediate retries and retries after RebuildMutableState, both with and without an explicit run ID. It also checks that a different request ID still creates a new reset run.

Why?

When a client retries ResetWorkflowExecution with the same request_id after losing a successful response, Temporal can create a second reset run and terminate the run created by the first request. tests/workflow_reset_test.go reproduces this by sending the same request twice and observing that the retry returns a different run ID and terminates the first reset run.

The deduplication check only compared the current run's CreateRequestId. Reset runs retain the original workflow-start request ID in that field for scheduler callback identity, so the reset request ID was unavailable for deduplication. A reset marker without a corresponding history event must also be copied when mutable state is rebuilt.

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)

Commands:

go test -tags test_dep -p 4 ./service/history/api/resetworkflow ./service/history/ndc -count=1
go test -tags test_dep -p 4 ./service/history ./service/history/api/reapplyevents -run '^$'
go test -tags test_dep -p 4 ./tests -run '^TestWorkflowResetTestSuite$/^TestResetWorkflowExecutionDeduplicatesRequestID$' -count=3
go test -tags test_dep -p 4 ./tests -run '^TestAdminRebuildMutableState_(ChasmDisabled|ChasmEnabled)$' -count=1
make lint-code-fast

On the base revision, retrying with the same request ID returns a different reset run ID. With this change, the test returns the original reset run ID before and after RebuildMutableState, and confirms that the marker remains present after the rebuild.

Potential risks

Each public reset run stores one additional request-ID entry. Rebuild preservation is limited to the Reset marker shape. Reset runs created before this change cannot gain the marker retroactively.

@Qian-Cheng-nju
Qian-Cheng-nju requested review from a team as code owners September 12, 2026 13:52
@CLAassistant

CLAassistant commented Sep 12, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

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