Skip to content

Commit f6b29d0

Browse files
temporal-spring-ai: disable workflow caching in side-effect replay tests
Configure TestWorkflowEnvironment with WorkflowCacheSize(0) so the worker replays from history on every workflow task instead of resuming from in-memory cached state. That is the regime in which side-effect safety actually has to hold: a missing Workflow.sideEffect wrap or an un-guarded in-workflow mutation would run on each replay, which cached resumes mask. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent f5058af commit f6b29d0

3 files changed

Lines changed: 34 additions & 3 deletions

File tree

temporal-spring-ai/src/test/java/io/temporal/springai/replay/ActivityToolSideEffectTest.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
import io.temporal.springai.activity.ChatModelActivityImpl;
1313
import io.temporal.springai.chat.TemporalChatClient;
1414
import io.temporal.springai.model.ActivityChatModel;
15+
import io.temporal.testing.TestEnvironmentOptions;
1516
import io.temporal.testing.TestWorkflowEnvironment;
1617
import io.temporal.testing.WorkflowReplayer;
1718
import io.temporal.worker.Worker;
19+
import io.temporal.worker.WorkerFactoryOptions;
1820
import io.temporal.workflow.Workflow;
1921
import io.temporal.workflow.WorkflowInterface;
2022
import io.temporal.workflow.WorkflowMethod;
@@ -48,7 +50,15 @@ class ActivityToolSideEffectTest {
4850

4951
@BeforeEach
5052
void setUp() {
51-
testEnv = TestWorkflowEnvironment.newInstance();
53+
// WorkflowCacheSize(0) forces the worker to replay from history on every workflow task
54+
// instead of resuming from in-memory cached state — the regime in which a missing
55+
// Workflow.sideEffect wrap or an un-guarded in-workflow mutation would actually bite.
56+
testEnv =
57+
TestWorkflowEnvironment.newInstance(
58+
TestEnvironmentOptions.newBuilder()
59+
.setWorkerFactoryOptions(
60+
WorkerFactoryOptions.newBuilder().setWorkflowCacheSize(0).build())
61+
.build());
5262
client = testEnv.getWorkflowClient();
5363
addActivity = new AddActivityImpl();
5464
}

temporal-spring-ai/src/test/java/io/temporal/springai/replay/ChatModelSideEffectTest.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88
import io.temporal.common.WorkflowExecutionHistory;
99
import io.temporal.springai.activity.ChatModelActivityImpl;
1010
import io.temporal.springai.model.ActivityChatModel;
11+
import io.temporal.testing.TestEnvironmentOptions;
1112
import io.temporal.testing.TestWorkflowEnvironment;
1213
import io.temporal.testing.WorkflowReplayer;
1314
import io.temporal.worker.Worker;
15+
import io.temporal.worker.WorkerFactoryOptions;
1416
import io.temporal.workflow.WorkflowInterface;
1517
import io.temporal.workflow.WorkflowMethod;
1618
import java.util.List;
@@ -43,7 +45,16 @@ class ChatModelSideEffectTest {
4345

4446
@BeforeEach
4547
void setUp() {
46-
testEnv = TestWorkflowEnvironment.newInstance();
48+
// WorkflowCacheSize(0) forces the worker to replay from history on every workflow task
49+
// instead of resuming from in-memory cached state, which is what we actually need to
50+
// assert side-effect safety: any un-wrapped side effect in workflow code would run on
51+
// each replay and bump the counter.
52+
testEnv =
53+
TestWorkflowEnvironment.newInstance(
54+
TestEnvironmentOptions.newBuilder()
55+
.setWorkerFactoryOptions(
56+
WorkerFactoryOptions.newBuilder().setWorkflowCacheSize(0).build())
57+
.build());
4758
client = testEnv.getWorkflowClient();
4859
model = new CountingChatModel("pong");
4960
}

temporal-spring-ai/src/test/java/io/temporal/springai/replay/SideEffectToolReplayTest.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@
1010
import io.temporal.springai.chat.TemporalChatClient;
1111
import io.temporal.springai.model.ActivityChatModel;
1212
import io.temporal.springai.tool.SideEffectTool;
13+
import io.temporal.testing.TestEnvironmentOptions;
1314
import io.temporal.testing.TestWorkflowEnvironment;
1415
import io.temporal.testing.WorkflowReplayer;
1516
import io.temporal.worker.Worker;
17+
import io.temporal.worker.WorkerFactoryOptions;
1618
import io.temporal.workflow.WorkflowInterface;
1719
import io.temporal.workflow.WorkflowMethod;
1820
import java.util.List;
@@ -51,7 +53,15 @@ class SideEffectToolReplayTest {
5153
@BeforeEach
5254
void setUp() {
5355
CALL_COUNT.set(0);
54-
testEnv = TestWorkflowEnvironment.newInstance();
56+
// WorkflowCacheSize(0) forces the worker to replay from history on every workflow task.
57+
// This is exactly the regime a missing Workflow.sideEffect wrap would fail in: every
58+
// tick the @Tool body would run again and bump the counter past 1.
59+
testEnv =
60+
TestWorkflowEnvironment.newInstance(
61+
TestEnvironmentOptions.newBuilder()
62+
.setWorkerFactoryOptions(
63+
WorkerFactoryOptions.newBuilder().setWorkflowCacheSize(0).build())
64+
.build());
5565
client = testEnv.getWorkflowClient();
5666
}
5767

0 commit comments

Comments
 (0)