1717
1818package com .uber .cadence .internal .worker ;
1919
20- import com .uber .cadence .GetWorkflowExecutionHistoryRequest ;
21- import com .uber .cadence .GetWorkflowExecutionHistoryResponse ;
22- import com .uber .cadence .History ;
23- import com .uber .cadence .HistoryEvent ;
24- import com .uber .cadence .PollForDecisionTaskResponse ;
25- import com .uber .cadence .RespondDecisionTaskCompletedRequest ;
26- import com .uber .cadence .RespondDecisionTaskFailedRequest ;
27- import com .uber .cadence .RespondQueryTaskCompletedRequest ;
28- import com .uber .cadence .WorkflowExecution ;
29- import com .uber .cadence .WorkflowExecutionStartedEventAttributes ;
30- import com .uber .cadence .WorkflowQuery ;
20+ import com .uber .cadence .*;
3121import com .uber .cadence .common .RetryOptions ;
3222import com .uber .cadence .internal .common .Retryer ;
3323import com .uber .cadence .internal .common .WorkflowExecutionUtils ;
@@ -250,23 +240,39 @@ private void sendReply(
250240
251241 private class DecisionTaskWithHistoryIteratorImpl implements DecisionTaskWithHistoryIterator {
252242
253- private long start = System .currentTimeMillis ();
243+ private final Duration retryServiceOperationInitialInterval = Duration .ofMillis (200 );
244+ private final Duration retryServiceOperationMaxInterval = Duration .ofSeconds (4 );
245+ private final Duration paginationStart = Duration .ofMillis (System .currentTimeMillis ());
246+ private Duration decisionTaskStartToCloseTimeout ;
247+
248+ private final Duration retryServiceOperationExpirationInterval () {
249+ Duration passed = Duration .ofMillis (System .currentTimeMillis ()).minus (paginationStart );
250+ return decisionTaskStartToCloseTimeout .minus (passed );
251+ }
252+
254253 private final PollForDecisionTaskResponse task ;
255254 private Iterator <HistoryEvent > current ;
256255 private byte [] nextPageToken ;
257- private WorkflowExecutionStartedEventAttributes startedEvent ;
258256
259257 DecisionTaskWithHistoryIteratorImpl (PollForDecisionTaskResponse task ) {
260258 this .task = task ;
261259 History history = task .getHistory ();
262- HistoryEvent firstEvent = history .getEvents ().get (0 );
263- this .startedEvent = firstEvent .getWorkflowExecutionStartedEventAttributes ();
264- if (this .startedEvent == null ) {
265- throw new IllegalArgumentException (
266- "First event in the history is not WorkflowExecutionStarted" );
267- }
268260 current = history .getEventsIterator ();
269261 nextPageToken = task .getNextPageToken ();
262+
263+ for (int i = history .events .size () - 1 ; i >= 0 ; i --) {
264+ DecisionTaskScheduledEventAttributes attributes =
265+ history .events .get (i ).getDecisionTaskScheduledEventAttributes ();
266+ if (attributes != null ) {
267+ decisionTaskStartToCloseTimeout =
268+ Duration .ofSeconds (attributes .getStartToCloseTimeoutSeconds ());
269+ break ;
270+ }
271+ }
272+
273+ if (decisionTaskStartToCloseTimeout == null ){
274+ throw new IllegalArgumentException (String .format ("PollForDecisionTaskResponse is missing DecisionTaskScheduled event. RunId: %s, WorkflowId: %s" , task .getWorkflowExecution ().runId , task .getWorkflowExecution ().workflowId ));
275+ }
270276 }
271277
272278 @ Override
@@ -287,21 +293,15 @@ public HistoryEvent next() {
287293 if (current .hasNext ()) {
288294 return current .next ();
289295 }
290- Duration passed = Duration .ofMillis (System .currentTimeMillis () - start );
291- Duration timeout = Duration .ofSeconds (startedEvent .getTaskStartToCloseTimeoutSeconds ());
292- Duration expiration = timeout .minus (passed );
293- if (expiration .isZero () || expiration .isNegative ()) {
294- throw new Error ("History pagination time exceeded TaskStartToCloseTimeout" );
295- }
296296
297297 options .getMetricsScope ().counter (MetricsType .WORKFLOW_GET_HISTORY_COUNTER ).inc (1 );
298298 Stopwatch sw =
299299 options .getMetricsScope ().timer (MetricsType .WORKFLOW_GET_HISTORY_LATENCY ).start ();
300300 RetryOptions retryOptions =
301301 new RetryOptions .Builder ()
302- .setExpiration (expiration )
303- .setInitialInterval (Duration . ofMillis ( 50 ) )
304- .setMaximumInterval (Duration . ofSeconds ( 1 ) )
302+ .setExpiration (retryServiceOperationExpirationInterval () )
303+ .setInitialInterval (retryServiceOperationInitialInterval )
304+ .setMaximumInterval (retryServiceOperationMaxInterval )
305305 .build ();
306306
307307 GetWorkflowExecutionHistoryRequest request = new GetWorkflowExecutionHistoryRequest ();
@@ -330,35 +330,25 @@ public HistoryEvent next() {
330330 }
331331 };
332332 }
333-
334- @ Override
335- public WorkflowExecutionStartedEventAttributes getStartedEvent () {
336- return startedEvent ;
337- }
338333 }
339334
340335 private static class ReplayDecisionTaskWithHistoryIterator
341336 implements DecisionTaskWithHistoryIterator {
342337
343338 private final Iterator <HistoryEvent > history ;
344339 private final PollForDecisionTaskResponse task ;
345- private final WorkflowExecutionStartedEventAttributes startedEvent ;
346340 private HistoryEvent first ;
347341
348342 private ReplayDecisionTaskWithHistoryIterator (
349343 WorkflowExecution execution , Iterator <HistoryEvent > history ) {
350344 this .history = history ;
351345 first = history .next ();
352- this .startedEvent = first .getWorkflowExecutionStartedEventAttributes ();
353- if (startedEvent == null ) {
354- throw new IllegalArgumentException (
355- "First history event is not WorkflowExecutionStarted, but: " + first .getEventType ());
356- }
346+
357347 task = new PollForDecisionTaskResponse ();
358348 task .setWorkflowExecution (execution );
359349 task .setStartedEventId (Long .MAX_VALUE );
360350 task .setPreviousStartedEventId (Long .MAX_VALUE );
361- task .setWorkflowType (startedEvent .getWorkflowType ());
351+ task .setWorkflowType (task .getWorkflowType ());
362352 }
363353
364354 @ Override
@@ -385,10 +375,5 @@ public HistoryEvent next() {
385375 }
386376 };
387377 }
388-
389- @ Override
390- public WorkflowExecutionStartedEventAttributes getStartedEvent () {
391- return startedEvent ;
392- }
393378 }
394379}
0 commit comments