23
23
import com .uber .cadence .TimerFiredEventAttributes ;
24
24
import java .util .HashMap ;
25
25
import java .util .Map ;
26
- import java .util .SortedMap ;
27
- import java .util .TreeMap ;
28
26
import java .util .concurrent .CancellationException ;
29
27
import java .util .concurrent .TimeUnit ;
30
28
import java .util .function .BiConsumer ;
31
29
import java .util .function .Consumer ;
32
30
33
- /**
34
- * Clock that must be used inside workflow definition code to ensure replay determinism. TODO:
35
- * Refactor to become a helper for managing timers instead of the generic clock class.
36
- */
31
+ /** Clock that must be used inside workflow definition code to ensure replay determinism. */
37
32
final class ClockDecisionContext {
38
33
39
34
private final class TimerCancellationHandler implements Consumer <Exception > {
@@ -46,24 +41,14 @@ private final class TimerCancellationHandler implements Consumer<Exception> {
46
41
47
42
@ Override
48
43
public void accept (Exception reason ) {
49
- decisions .cancelTimer (
50
- timerId ,
51
- () -> {
52
- OpenRequestInfo <?, ?> scheduled = scheduledTimers .remove (timerId );
53
- BiConsumer <?, Exception > context = scheduled .getCompletionCallback ();
54
- CancellationException exception = new CancellationException ("Cancelled by request" );
55
- exception .initCause (reason );
56
- context .accept (null , exception );
57
- });
44
+ decisions .cancelTimer (timerId , () -> timerCancelled (timerId , reason ));
58
45
}
59
46
}
60
47
61
48
private final DecisionsHelper decisions ;
62
49
63
50
private final Map <String , OpenRequestInfo <?, Long >> scheduledTimers = new HashMap <>();
64
51
65
- private final SortedMap <Long , String > timersByFiringTime = new TreeMap <>();
66
-
67
52
private long replayCurrentTimeMilliseconds ;
68
53
69
54
private boolean replaying = true ;
@@ -90,60 +75,18 @@ Consumer<Exception> createTimer(long delaySeconds, Consumer<Exception> callback)
90
75
}
91
76
if (delaySeconds == 0 ) {
92
77
callback .accept (null );
93
- return Exception -> {} ;
78
+ return null ;
94
79
}
95
80
long firingTime = currentTimeMillis () + TimeUnit .SECONDS .toMillis (delaySeconds );
96
- // As the timer resolution is 1 second it doesn't really make sense to update a timer
97
- // that is less than one second before the already existing.
98
- if (timersByFiringTime .size () > 0 ) {
99
- long nextTimerFiringTime = timersByFiringTime .firstKey ();
100
- if (firingTime > nextTimerFiringTime
101
- || nextTimerFiringTime - firingTime < TimeUnit .SECONDS .toMillis (1 )) {
102
- return null ;
103
- }
104
- }
105
- Consumer <Exception > result = null ;
106
- if (!timersByFiringTime .containsKey (firingTime )) {
107
- final OpenRequestInfo <?, Long > context = new OpenRequestInfo <>(firingTime );
108
- final StartTimerDecisionAttributes timer = new StartTimerDecisionAttributes ();
109
- timer .setStartToFireTimeoutSeconds (delaySeconds );
110
- final String timerId = decisions .getNextId ();
111
- timer .setTimerId (timerId );
112
- decisions .startTimer (timer , null );
113
- context .setCompletionHandle ((ctx , Exception ) -> callback .accept (null ));
114
- scheduledTimers .put (timerId , context );
115
- timersByFiringTime .put (firingTime , timerId );
116
- result = new ClockDecisionContext .TimerCancellationHandler (timerId );
117
- }
118
- SortedMap <Long , String > toCancel = timersByFiringTime .subMap (0L , firingTime );
119
- for (String timerId : toCancel .values ()) {
120
- decisions .cancelTimer (
121
- timerId ,
122
- () -> {
123
- OpenRequestInfo <?, ?> scheduled = scheduledTimers .remove (timerId );
124
- BiConsumer <?, Exception > context = scheduled .getCompletionCallback ();
125
- CancellationException exception =
126
- new CancellationException ("Cancelled as next unblock time changed" );
127
- context .accept (null , exception );
128
- });
129
- }
130
- toCancel .clear ();
131
- return result ;
132
- }
133
-
134
- void cancelAllTimers () {
135
- for (String timerId : timersByFiringTime .values ()) {
136
- decisions .cancelTimer (
137
- timerId ,
138
- () -> {
139
- OpenRequestInfo <?, ?> scheduled = scheduledTimers .remove (timerId );
140
- BiConsumer <?, Exception > context = scheduled .getCompletionCallback ();
141
- CancellationException exception =
142
- new CancellationException ("Cancelled as next unblock time changed" );
143
- context .accept (null , exception );
144
- });
145
- }
146
- timersByFiringTime .clear ();
81
+ final OpenRequestInfo <?, Long > context = new OpenRequestInfo <>(firingTime );
82
+ final StartTimerDecisionAttributes timer = new StartTimerDecisionAttributes ();
83
+ timer .setStartToFireTimeoutSeconds (delaySeconds );
84
+ final String timerId = decisions .getNextId ();
85
+ timer .setTimerId (timerId );
86
+ decisions .startTimer (timer , null );
87
+ context .setCompletionHandle ((ctx , e ) -> callback .accept (e ));
88
+ scheduledTimers .put (timerId , context );
89
+ return new ClockDecisionContext .TimerCancellationHandler (timerId );
147
90
}
148
91
149
92
void setReplaying (boolean replaying ) {
@@ -157,8 +100,6 @@ void handleTimerFired(TimerFiredEventAttributes attributes) {
157
100
if (scheduled != null ) {
158
101
BiConsumer <?, Exception > completionCallback = scheduled .getCompletionCallback ();
159
102
completionCallback .accept (null , null );
160
- long firingTime = scheduled .getUserContext ();
161
- timersByFiringTime .remove (firingTime );
162
103
}
163
104
}
164
105
}
@@ -167,12 +108,18 @@ void handleTimerCanceled(HistoryEvent event) {
167
108
TimerCanceledEventAttributes attributes = event .getTimerCanceledEventAttributes ();
168
109
String timerId = attributes .getTimerId ();
169
110
if (decisions .handleTimerCanceled (event )) {
170
- OpenRequestInfo <?, ?> scheduled = scheduledTimers .remove (timerId );
171
- if (scheduled != null ) {
172
- BiConsumer <?, Exception > completionCallback = scheduled .getCompletionCallback ();
173
- CancellationException exception = new CancellationException ("Cancelled by request" );
174
- completionCallback .accept (null , exception );
175
- }
111
+ timerCancelled (timerId , null );
112
+ }
113
+ }
114
+
115
+ private void timerCancelled (String timerId , Exception reason ) {
116
+ OpenRequestInfo <?, ?> scheduled = scheduledTimers .remove (timerId );
117
+ if (scheduled == null ) {
118
+ return ;
176
119
}
120
+ BiConsumer <?, Exception > context = scheduled .getCompletionCallback ();
121
+ CancellationException exception = new CancellationException ("Cancelled by request" );
122
+ exception .initCause (reason );
123
+ context .accept (null , exception );
177
124
}
178
125
}
0 commit comments