List<HistoryEvent> decisionCompletionToStartEvents = new ArrayList<HistoryEvent>();
boolean concurrentToDecision = true;
int lastDecisionIndex = -1;
while (eventsIterator.hasNext()) {
HistoryEvent event = eventsIterator.next();
EventType eventType = EventType.valueOf(event.getEventType());
if (eventType == EventType.DecisionTaskCompleted) {
decisionsHelper.setWorkflowContextData(event.getDecisionTaskCompletedEventAttributes().getExecutionContext());
concurrentToDecision = false;
}
else if (eventType == EventType.DecisionTaskStarted) {
decisionsHelper.handleDecisionTaskStartedEvent();
if (!eventsIterator.isNextDecisionTimedOut()) {
long replayCurrentTimeMilliseconds = event.getEventTimestamp().getTime();
workflowClock.setReplayCurrentTimeMilliseconds(replayCurrentTimeMilliseconds);
break;
}
}
else if (eventType == EventType.DecisionTaskScheduled || eventType == EventType.DecisionTaskTimedOut) {
// skip
}
else {
if (concurrentToDecision) {
decisionStartToCompletionEvents.add(event);
}
else {
if (isDecisionEvent(eventType)) {
lastDecisionIndex = decisionCompletionToStartEvents.size();
}
decisionCompletionToStartEvents.add(event);
}
}
}
int size = decisionStartToCompletionEvents.size() + decisionStartToCompletionEvents.size();
// Reorder events to correspond to the order that decider sees them.
// The main difference is that events that were added during decision task execution
// should be processed after events that correspond to the decisions.
// Otherwise the replay is going to break.
reordered = new ArrayList<HistoryEvent>(size);
// First are events that correspond to the previous task decisions
if (lastDecisionIndex >= 0) {
reordered.addAll(decisionCompletionToStartEvents.subList(0, lastDecisionIndex + 1));
}
// Second are events that were added during previous task execution
reordered.addAll(decisionStartToCompletionEvents);
// The last are events that were added after previous task completion
if (decisionCompletionToStartEvents.size() > lastDecisionIndex + 1) {
reordered.addAll(decisionCompletionToStartEvents.subList(lastDecisionIndex + 1,
decisionCompletionToStartEvents.size()));
}
for (HistoryEvent event : reordered) {
if (event.getEventId() >= lastNonReplayedEventId) {
workflowClock.setReplaying(false);
}
EventType eventType = EventType.valueOf(event.getEventType());
processEvent(event, eventType);
eventLoop(event);
}
completeWorkflow();