Skip to content

Commit 08c5630

Browse files
committed
Keep completion cleanup out of replay mode
When the workflow method completes, blocked handlers unwind once and never run again, so their finally blocks are live rather than replay.
1 parent 2f23e5e commit 08c5630

2 files changed

Lines changed: 51 additions & 3 deletions

File tree

‎temporal-sdk/src/main/java/io/temporal/internal/replay/ReplayWorkflowRunTaskHandler.java‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,9 +338,12 @@ private Map<String, WorkflowQueryResult> executeQueries(Map<String, WorkflowQuer
338338
public void close() {
339339
lock.lock();
340340
try {
341-
// Destroying the workflow threads runs their finally blocks. Treat that as replay so
341+
// Destroying the workflow threads runs their finally blocks. Unless the workflow method has
342+
// completed, they run again after the next cache miss, so treat that as replay so
342343
// replay-aware code, such as logging and tracing, does not act on it.
343-
workflowStateMachines.setReplaying(true);
344+
if (!context.isWorkflowMethodCompleted()) {
345+
workflowStateMachines.setReplaying(true);
346+
}
344347
replayWorkflowExecutor.close();
345348
} finally {
346349
lock.unlock();

‎temporal-sdk/src/test/java/io/temporal/workflow/EvictionIsReplayingTest.java‎

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import io.temporal.testing.internal.SDKTestWorkflowRule;
99
import io.temporal.workflow.unsafe.WorkflowUnsafe;
1010
import java.util.Arrays;
11+
import java.util.Collections;
1112
import java.util.List;
1213
import java.util.concurrent.CopyOnWriteArrayList;
1314
import org.junit.Rule;
@@ -18,10 +19,13 @@ public class EvictionIsReplayingTest {
1819

1920
@Rule
2021
public SDKTestWorkflowRule testWorkflowRule =
21-
SDKTestWorkflowRule.newBuilder().setWorkflowTypes(TestWorkflowImpl.class).build();
22+
SDKTestWorkflowRule.newBuilder()
23+
.setWorkflowTypes(TestWorkflowImpl.class, BlockedHandlerWorkflowImpl.class)
24+
.build();
2225

2326
@Test
2427
public void evictionUnwindsWorkflowCodeAsReplay() {
28+
replayingInFinally.clear();
2529
TestWorkflow workflow = testWorkflowRule.newWorkflowStub(TestWorkflow.class);
2630
WorkflowExecution execution = WorkflowClient.start(workflow::execute);
2731
testWorkflowRule.waitForTheEndOfWFT(execution.getWorkflowId());
@@ -34,6 +38,19 @@ public void evictionUnwindsWorkflowCodeAsReplay() {
3438
assertEquals(Arrays.asList(true, false), replayingInFinally);
3539
}
3640

41+
@Test
42+
public void completionUnwindsBlockedHandlersLive() {
43+
replayingInFinally.clear();
44+
BlockedHandlerWorkflow workflow =
45+
testWorkflowRule.newWorkflowStub(BlockedHandlerWorkflow.class);
46+
WorkflowClient.start(workflow::execute);
47+
48+
workflow.block();
49+
WorkflowStub.fromTyped(workflow).getResult(Void.class);
50+
51+
assertEquals(Collections.singletonList(false), replayingInFinally);
52+
}
53+
3754
@WorkflowInterface
3855
public interface TestWorkflow {
3956
@WorkflowMethod
@@ -60,4 +77,32 @@ public void finish() {
6077
finished = true;
6178
}
6279
}
80+
81+
@WorkflowInterface
82+
public interface BlockedHandlerWorkflow {
83+
@WorkflowMethod
84+
void execute();
85+
86+
@SignalMethod
87+
void block();
88+
}
89+
90+
public static class BlockedHandlerWorkflowImpl implements BlockedHandlerWorkflow {
91+
private boolean blocked;
92+
93+
@Override
94+
public void execute() {
95+
Workflow.await(() -> blocked);
96+
}
97+
98+
@Override
99+
public void block() {
100+
blocked = true;
101+
try {
102+
Workflow.await(() -> false);
103+
} finally {
104+
replayingInFinally.add(WorkflowUnsafe.isReplaying());
105+
}
106+
}
107+
}
63108
}

0 commit comments

Comments
 (0)