Skip to content

Commit 2feecc1

Browse files
authored
Fix race condition in side effect function. (#212)
* Added SideEffectRaceConditionTest * Fixed race condition in DynamicTransitionAction
1 parent b76b22e commit 2feecc1

File tree

2 files changed

+96
-8
lines changed

2 files changed

+96
-8
lines changed

src/main/java/io/temporal/internal/statemachines/DynamicTransitionAction.java

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ class DynamicTransitionAction<State, Data> implements TransitionAction<State, Da
2727

2828
final DynamicCallback<State, Data> callback;
2929
State[] expectedStates;
30-
State state;
3130

3231
DynamicTransitionAction(State[] expectedStates, DynamicCallback<State, Data> callback) {
3332
this.expectedStates = expectedStates;
@@ -36,7 +35,7 @@ class DynamicTransitionAction<State, Data> implements TransitionAction<State, Da
3635

3736
@Override
3837
public State apply(Data data) {
39-
state = callback.apply(data);
38+
State state = callback.apply(data);
4039
for (State s : expectedStates) {
4140
if (s.equals(state)) {
4241
return state;
@@ -53,11 +52,6 @@ public List<State> getAllowedStates() {
5352

5453
@Override
5554
public String toString() {
56-
return "DynamicTransitionAction{"
57-
+ ", state="
58-
+ state
59-
+ "expectedStates="
60-
+ Arrays.toString(expectedStates)
61-
+ '}';
55+
return "DynamicTransitionAction{" + "expectedStates=" + Arrays.toString(expectedStates) + '}';
6256
}
6357
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* Copyright (C) 2020 Temporal Technologies, Inc. All Rights Reserved.
3+
*
4+
* Copyright 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
5+
*
6+
* Modifications copyright (C) 2017 Uber Technologies, Inc.
7+
*
8+
* Licensed under the Apache License, Version 2.0 (the "License"). You may not
9+
* use this file except in compliance with the License. A copy of the License is
10+
* located at
11+
*
12+
* http://aws.amazon.com/apache2.0
13+
*
14+
* or in the "license" file accompanying this file. This file is distributed on
15+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
16+
* express or implied. See the License for the specific language governing
17+
* permissions and limitations under the License.
18+
*/
19+
20+
package io.temporal.workflow;
21+
22+
import io.temporal.client.WorkflowClient;
23+
import io.temporal.client.WorkflowOptions;
24+
import io.temporal.testing.TestEnvironmentOptions;
25+
import io.temporal.testing.TestWorkflowEnvironment;
26+
import io.temporal.worker.Worker;
27+
import java.time.Duration;
28+
import java.util.ArrayList;
29+
import java.util.List;
30+
import java.util.Random;
31+
import java.util.concurrent.CompletableFuture;
32+
import java.util.concurrent.ExecutionException;
33+
import org.junit.After;
34+
import org.junit.Before;
35+
import org.junit.Test;
36+
37+
public class SideEffectRaceConditionTest {
38+
39+
private static final String TASK_QUEUE = "test-workflow";
40+
41+
private TestWorkflowEnvironment testEnvironment;
42+
private Worker worker;
43+
44+
@Before
45+
public void setUp() {
46+
TestEnvironmentOptions options = TestEnvironmentOptions.newBuilder().build();
47+
testEnvironment = TestWorkflowEnvironment.newInstance(options);
48+
worker = testEnvironment.newWorker(TASK_QUEUE);
49+
}
50+
51+
@After
52+
public void tearDown() {
53+
testEnvironment.close();
54+
}
55+
56+
@WorkflowInterface
57+
public interface TestWorkflow {
58+
@WorkflowMethod
59+
void execute();
60+
}
61+
62+
public static class TestSideEffectBenchWorkflowImpl implements TestWorkflow {
63+
64+
@Override
65+
public void execute() {
66+
for (int i = 0; i < 100; i++) {
67+
Workflow.sideEffect(long.class, () -> new Random().nextLong());
68+
Workflow.sleep(Duration.ofMillis(100));
69+
Workflow.sideEffect(long.class, () -> new Random().nextLong());
70+
}
71+
}
72+
}
73+
74+
@Test
75+
public void testSideEffectBench() throws ExecutionException, InterruptedException {
76+
worker.registerWorkflowImplementationTypes(TestSideEffectBenchWorkflowImpl.class);
77+
testEnvironment.start();
78+
List<CompletableFuture<Void>> results = new ArrayList<>();
79+
int count = 100;
80+
for (int i = 0; i < count; i++) {
81+
TestWorkflow workflowStub =
82+
testEnvironment
83+
.getWorkflowClient()
84+
.newWorkflowStub(
85+
TestWorkflow.class,
86+
WorkflowOptions.newBuilder().setTaskQueue(TASK_QUEUE).build());
87+
CompletableFuture<Void> result = WorkflowClient.execute(workflowStub::execute);
88+
results.add(result);
89+
}
90+
for (int i = 0; i < count; i++) {
91+
results.get(i).get();
92+
}
93+
}
94+
}

0 commit comments

Comments
 (0)