Cancel timer when Workflow.await condition is satisfied#2799
Open
mfateev wants to merge 3 commits intotemporalio:masterfrom
Open
Cancel timer when Workflow.await condition is satisfied#2799mfateev wants to merge 3 commits intotemporalio:masterfrom
mfateev wants to merge 3 commits intotemporalio:masterfrom
Conversation
…tisfied This change addresses GitHub issue temporalio#2312 by ensuring that Workflow.await(duration, condition) cancels the timer when the condition is satisfied before the timeout expires. Changes: - Add CANCEL_AWAIT_TIMER_ON_CONDITION SDK flag for backward compatibility - Modify SyncWorkflowContext.await() to use a CancellationScope to cancel the timer when condition is satisfied before timeout - Skip timer creation entirely if condition is already satisfied - Add comprehensive tests including replay compatibility test The new behavior is enabled by default for new workflows via the SDK flag mechanism. Old workflows replay correctly with the original behavior.
Follow the Go SDK pattern (PR temporalio#2153) per reviewer feedback: 1. Use checkSdkFlag instead of tryUseSdkFlag so the flag is NOT auto-enabled for new workflows. Add TODO to switch to tryUseSdkFlag in the next release. 2. Remove CANCEL_AWAIT_TIMER_ON_CONDITION from initialFlags. 3. Tests explicitly toggle the flag to verify both old behavior (timer NOT cancelled) and new behavior (timer cancelled).
mjameswh
reviewed
Feb 24, 2026
| replayContext.checkSdkFlag(SdkFlag.CANCEL_AWAIT_TIMER_ON_CONDITION); | ||
|
|
||
| // If new behavior is enabled and condition is already satisfied, skip creating timer | ||
| if (cancelTimerOnCondition && unblockCondition.get()) { |
Contributor
There was a problem hiding this comment.
nit: I'd move this block into the first branch of the if (cancelTimerOnCondition) { below
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Workflow.await(duration, condition)now cancels the timer when the condition is satisfied before the timeout expiresBackground
Fixes #2312. Port of the same fix from the Go SDK: temporalio/sdk-go#2153
Implementation
CANCEL_AWAIT_TIMER_ON_CONDITION(4)SDK flag for replay compatibilityCancellationScopeso it can be cancelled when the condition resolvescheckSdkFlag(nottryUseSdkFlag) so the flag is not auto-enabled for new workflows in this release — it must wait at least 1 release before being enabled by default, per SDK flag rollout policytryUseSdkFlagin the next releaseTest plan
testTimerCancelledWhenFlagEnabled— explicitly enables the flag, verifiesTIMER_CANCELEDin historytestTimerNotCancelledWhenFlagDisabled— default (flag off), verifies timer is NOT cancelled (old behavior)testNoTimerWhenConditionImmediatelySatisfiedWithFlag— verifies no timer created when condition is already truetestAwaitReturnValue— verifies return value semantics (true=condition met, false=timeout)testReplayOldHistoryWithoutFlag— replay compatibility with old workflow histories recorded without the flag