// Waits for any one of the given DurableTasks to complete and outputs the first DurableTask that does so public void WaitAny( IReadOnlyCollection <DurableTask> tasksToWaitFor, OrchestrationContext context, Action <object> output) { context.OrchestrationActionCollector.NextBatch(); var completedTasks = new List <DurableTask>(); DurableTask firstCompletedTask = null; int firstCompletedHistoryEventIndex = -1; foreach (var task in tasksToWaitFor) { var scheduledHistoryEvent = task.GetScheduledHistoryEvent(context); var completedHistoryEvent = task.GetCompletedHistoryEvent(context, scheduledHistoryEvent); // We must mark this event as processed even if it has not completed; subsequent completed history events // corresponding to an awaited task will not have their IsProcessed value ever set to true. if (scheduledHistoryEvent != null) { scheduledHistoryEvent.IsProcessed = true; } if (completedHistoryEvent != null) { completedTasks.Add(task); int completedHistoryEventIndex = Array.IndexOf(context.History, completedHistoryEvent); if (firstCompletedHistoryEventIndex < 0 || completedHistoryEventIndex < firstCompletedHistoryEventIndex) { firstCompletedHistoryEventIndex = completedHistoryEventIndex; firstCompletedTask = task; } completedHistoryEvent.IsProcessed = true; } } var anyTaskCompleted = completedTasks.Count > 0; if (anyTaskCompleted) { CurrentUtcDateTimeUpdater.UpdateCurrentUtcDateTime(context); // Return a reference to the first completed task output(firstCompletedTask); } else { InitiateAndWaitForStop(context); } }
public void StopAndInitiateDurableTaskOrReplay( DurableTask task, OrchestrationContext context, bool noWait, Action <object> output) { context.OrchestrationActionCollector.Add(task.CreateOrchestrationAction()); if (noWait) { output(task); } else { var scheduledHistoryEvent = task.GetScheduledHistoryEvent(context); var completedHistoryEvent = task.GetCompletedHistoryEvent(context, scheduledHistoryEvent); // We must check if the task has been completed first, otherwise external events will always wait upon replays if (completedHistoryEvent != null) { CurrentUtcDateTimeUpdater.UpdateCurrentUtcDateTime(context); if (GetEventResult(completedHistoryEvent) != null) { output(GetEventResult(completedHistoryEvent)); } if (scheduledHistoryEvent != null) { scheduledHistoryEvent.IsProcessed = true; } completedHistoryEvent.IsProcessed = true; } else if (scheduledHistoryEvent == null) { InitiateAndWaitForStop(context); } } }
public void StopAndInitiateDurableTaskOrReplay( DurableTask task, OrchestrationContext context, bool noWait, Action <object> output, Action <string> onFailure, RetryOptions retryOptions = null) { context.OrchestrationActionCollector.Add(task.CreateOrchestrationAction()); if (noWait) { output(task); } else { context.OrchestrationActionCollector.NextBatch(); var scheduledHistoryEvent = task.GetScheduledHistoryEvent(context); var completedHistoryEvent = task.GetCompletedHistoryEvent(context, scheduledHistoryEvent); // We must check if the task has been completed first, otherwise external events will always wait upon replays if (completedHistoryEvent != null) { CurrentUtcDateTimeUpdater.UpdateCurrentUtcDateTime(context); if (scheduledHistoryEvent != null) { scheduledHistoryEvent.IsProcessed = true; } completedHistoryEvent.IsProcessed = true; switch (completedHistoryEvent.EventType) { case HistoryEventType.TaskCompleted: var eventResult = GetEventResult(completedHistoryEvent); if (eventResult != null) { output(eventResult); } break; case HistoryEventType.TaskFailed: if (retryOptions == null) { onFailure(completedHistoryEvent.Reason); } else { // Reset IsProcessed, let RetryProcessor handle these events instead. scheduledHistoryEvent.IsProcessed = false; completedHistoryEvent.IsProcessed = false; var shouldContinueProcessing = RetryProcessor.Process( context.History, scheduledHistoryEvent, retryOptions.MaxNumberOfAttempts, onSuccess: result => { output(TypeExtensions.ConvertFromJson(result)); }, onFailure); if (shouldContinueProcessing) { InitiateAndWaitForStop(context); } } break; } } else { InitiateAndWaitForStop(context); } } }