// 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);
            }
        }
Example #2
0
        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);
                }
            }
        }