Пример #1
0
        private async Task ProcessAsyncActions(AsyncAction[][] actions)
        {
            if (actions == null)
            {
                throw new ArgumentNullException("Out-of-proc orchestrator schema must have a non-null actions property.");
            }

            // Each actionSet represents a particular execution of the orchestration.
            foreach (AsyncAction[] actionSet in actions)
            {
                var tasks = new List <Task>(actions.Length);
                DurableOrchestrationContext ctx = this.context as DurableOrchestrationContext;

                // An actionSet represents all actions that were scheduled within that execution.
                foreach (AsyncAction action in actionSet)
                {
                    switch (action.ActionType)
                    {
                    case AsyncActionType.CallActivity:
                        tasks.Add(this.context.CallActivityAsync(action.FunctionName, action.Input));
                        break;

                    case AsyncActionType.CreateTimer:
                        using (var cts = new CancellationTokenSource())
                        {
                            if (ctx != null)
                            {
                                ctx.ThrowIfInvalidTimerLengthForStorageProvider(action.FireAt);
                            }

                            tasks.Add(this.context.CreateTimer(action.FireAt, cts.Token));

                            if (action.IsCanceled)
                            {
                                cts.Cancel();
                            }
                        }

                        break;

                    case AsyncActionType.CallActivityWithRetry:
                        tasks.Add(this.context.CallActivityWithRetryAsync(action.FunctionName, action.RetryOptions, action.Input));
                        break;

                    case AsyncActionType.CallSubOrchestrator:
                        tasks.Add(this.context.CallSubOrchestratorAsync(action.FunctionName, action.InstanceId, action.Input));
                        break;

                    case AsyncActionType.CallSubOrchestratorWithRetry:
                        tasks.Add(this.context.CallSubOrchestratorWithRetryAsync(action.FunctionName, action.RetryOptions, action.InstanceId, action.Input));
                        break;

                    case AsyncActionType.CallEntity:
                    {
                        var entityId = EntityId.GetEntityIdFromSchedulerId(action.InstanceId);
                        tasks.Add(this.context.CallEntityAsync(entityId, action.EntityOperation, action.Input));
                        break;
                    }

                    case AsyncActionType.SignalEntity:
                    {
                        // We do not add a task because this is 'fire and forget'
                        var entityId = EntityId.GetEntityIdFromSchedulerId(action.InstanceId);
                        this.context.SignalEntity(entityId, action.EntityOperation, action.Input);
                        break;
                    }

                    case AsyncActionType.ScheduledSignalEntity:
                    {
                        // We do not add a task because this is 'fire and forget'
                        var entityId = EntityId.GetEntityIdFromSchedulerId(action.InstanceId);
                        this.context.SignalEntity(entityId, action.FireAt, action.EntityOperation, action.Input);
                        break;
                    }

                    case AsyncActionType.ContinueAsNew:
                        this.context.ContinueAsNew(action.Input);
                        break;

                    case AsyncActionType.WaitForExternalEvent:
                        tasks.Add(this.context.WaitForExternalEvent <object>(action.ExternalEventName));
                        break;

                    case AsyncActionType.CallHttp:
                        tasks.Add(this.context.CallHttpAsync(action.HttpRequest));
                        break;

                    default:
                        break;
                    }
                }

                if (tasks.Count > 0)
                {
                    await Task.WhenAny(tasks);
                }
            }
        }
        /// <summary>
        /// Invokes a DF API based on the input action object.
        /// </summary>
        /// <param name="action">An OOProc action object representing a DF task.</param>
        /// <returns>If the API returns a task, the DF task corresponding to the input action. Else, null.</returns>
        private Task InvokeAPIFromAction(AsyncAction action)
        {
            Task fireAndForgetTask = Task.CompletedTask;
            Task task = null;

            switch (action.ActionType)
            {
            case AsyncActionType.CallActivity:
                task = this.context.CallActivityAsync(action.FunctionName, action.Input);
                break;

            case AsyncActionType.CreateTimer:
                DurableOrchestrationContext ctx = this.context as DurableOrchestrationContext;
                using (var cts = new CancellationTokenSource())
                {
                    if (ctx != null)
                    {
                        ctx.ThrowIfInvalidTimerLengthForStorageProvider(action.FireAt);
                    }

                    task = this.context.CreateTimer(action.FireAt, cts.Token);

                    if (action.IsCanceled)
                    {
                        cts.Cancel();
                    }
                }

                break;

            case AsyncActionType.CallActivityWithRetry:
                task = this.context.CallActivityWithRetryAsync(action.FunctionName, action.RetryOptions, action.Input);
                break;

            case AsyncActionType.CallSubOrchestrator:
                task = this.context.CallSubOrchestratorAsync(action.FunctionName, action.InstanceId, action.Input);
                break;

            case AsyncActionType.CallSubOrchestratorWithRetry:
                task = this.context.CallSubOrchestratorWithRetryAsync(action.FunctionName, action.RetryOptions, action.InstanceId, action.Input);
                break;

            case AsyncActionType.CallEntity:
            {
                var entityId = EntityId.GetEntityIdFromSchedulerId(action.InstanceId);
                task = this.context.CallEntityAsync(entityId, action.EntityOperation, action.Input);
                break;
            }

            case AsyncActionType.SignalEntity:
            {
                // We do not add a task because this is 'fire and forget'
                var entityId = EntityId.GetEntityIdFromSchedulerId(action.InstanceId);
                this.context.SignalEntity(entityId, action.EntityOperation, action.Input);
                task = fireAndForgetTask;
                break;
            }

            case AsyncActionType.ScheduledSignalEntity:
            {
                // We do not add a task because this is 'fire and forget'
                var entityId = EntityId.GetEntityIdFromSchedulerId(action.InstanceId);
                this.context.SignalEntity(entityId, action.FireAt, action.EntityOperation, action.Input);
                task = fireAndForgetTask;
                break;
            }

            case AsyncActionType.ContinueAsNew:
                this.context.ContinueAsNew(action.Input);
                task = fireAndForgetTask;
                break;

            case AsyncActionType.WaitForExternalEvent:
                task = this.context.WaitForExternalEvent <object>(action.ExternalEventName);
                break;

            case AsyncActionType.CallHttp:
                task = this.context.CallHttpAsync(action.HttpRequest);
                break;

            case AsyncActionType.WhenAll:
                task = Task.WhenAll(action.CompoundActions.Select(x => this.InvokeAPIFromAction(x)));
                break;

            case AsyncActionType.WhenAny:
                task = Task.WhenAny(action.CompoundActions.Select(x => this.InvokeAPIFromAction(x)));
                break;

            default:
                throw new Exception($"Received an unexpected action type from the out-of-proc function: '${action.ActionType}'.");
            }

            return(task);
        }