private async Task OrchestrationMiddleware(DispatchMiddlewareContext dispatchContext, Func <Task> next)
        {
            TaskOrchestrationShim       shim    = (TaskOrchestrationShim)dispatchContext.GetProperty <TaskOrchestration>();
            DurableOrchestrationContext context = shim.Context;

            OrchestrationRuntimeState orchestrationRuntimeState = dispatchContext.GetProperty <OrchestrationRuntimeState>();

            if (orchestrationRuntimeState.ParentInstance != null)
            {
                context.ParentInstanceId = orchestrationRuntimeState.ParentInstance.OrchestrationInstance.InstanceId;
            }

            context.History = orchestrationRuntimeState.Events;
            context.SetInput(orchestrationRuntimeState.Input);

            FunctionName orchestratorFunction = new FunctionName(context.Name);

            OrchestratorInfo info;

            if (!this.registeredOrchestrators.TryGetValue(orchestratorFunction, out info))
            {
                string message = this.GetInvalidOrchestratorFunctionMessage(orchestratorFunction.Name);
                this.TraceHelper.ExtensionWarningEvent(
                    this.Options.HubName,
                    orchestratorFunction.Name,
                    orchestrationRuntimeState.OrchestrationInstance.InstanceId,
                    message);
                throw new InvalidOperationException(message);
            }

            // 1. Start the functions invocation pipeline (billing, logging, bindings, and timeout tracking).
            FunctionResult result = await info.Executor.TryExecuteAsync(
                new TriggeredFunctionData
            {
                TriggerValue = context,

#pragma warning disable CS0618 // Approved for use by this extension
                InvokeHandler = userCodeInvoker =>
                {
                    // 2. Configure the shim with the inner invoker to execute the user code.
                    shim.SetFunctionInvocationCallback(userCodeInvoker);

                    // 3. Move to the next stage of the DTFx pipeline to trigger the orchestrator shim.
                    return(next());
                },
#pragma warning restore CS0618
            },
                CancellationToken.None);

            if (!context.IsCompleted)
            {
                this.TraceHelper.FunctionAwaited(
                    context.HubName,
                    context.Name,
                    context.InstanceId,
                    context.IsReplaying);
            }

            await context.RunDeferredTasks();
        }
Exemple #2
0
        private async Task OrchestrationMiddleware(DispatchMiddlewareContext dispatchContext, Func <Task> next)
        {
            TaskOrchestrationShim       shim    = (TaskOrchestrationShim)dispatchContext.GetProperty <TaskOrchestration>();
            DurableOrchestrationContext context = shim.Context;

            OrchestrationRuntimeState orchestrationRuntimeState = dispatchContext.GetProperty <OrchestrationRuntimeState>();

            if (orchestrationRuntimeState.ParentInstance != null)
            {
                context.ParentInstanceId = orchestrationRuntimeState.ParentInstance.OrchestrationInstance.InstanceId;
            }

            context.InstanceId  = orchestrationRuntimeState.OrchestrationInstance.InstanceId;
            context.IsReplaying = orchestrationRuntimeState.ExecutionStartedEvent.IsPlayed;
            context.History     = orchestrationRuntimeState.Events;
            context.SetInput(orchestrationRuntimeState.Input);

            FunctionName orchestratorFunction = new FunctionName(context.Name);

            RegisteredFunctionInfo info;

            if (!this.knownOrchestrators.TryGetValue(orchestratorFunction, out info))
            {
                string message = this.GetInvalidOrchestratorFunctionMessage(orchestratorFunction.Name);
                this.TraceHelper.ExtensionWarningEvent(
                    this.Options.HubName,
                    orchestratorFunction.Name,
                    orchestrationRuntimeState.OrchestrationInstance.InstanceId,
                    message);
                throw new InvalidOperationException(message);
            }

            // 1. Start the functions invocation pipeline (billing, logging, bindings, and timeout tracking).
            FunctionResult result = await info.Executor.TryExecuteAsync(
                new TriggeredFunctionData
            {
                TriggerValue = context,

#pragma warning disable CS0618 // Approved for use by this extension
                InvokeHandler = async userCodeInvoker =>
                {
                    // 2. Configure the shim with the inner invoker to execute the user code.
                    shim.SetFunctionInvocationCallback(userCodeInvoker);

                    // 3. Move to the next stage of the DTFx pipeline to trigger the orchestrator shim.
                    await next();

                    // 4. If an activity failed, indicate to the functions Host that this execution failed via an exception
                    if (context.IsCompleted && context.OrchestrationException != null)
                    {
                        context.OrchestrationException.Throw();
                    }
                },
#pragma warning restore CS0618
            },
                CancellationToken.None);

            if (!context.IsCompleted)
            {
                this.TraceHelper.FunctionAwaited(
                    context.HubName,
                    context.Name,
                    context.InstanceId,
                    context.IsReplaying);
            }

            if (context.IsCompleted &&
                context.ContinuedAsNew &&
                context.PreserveUnprocessedEvents)
            {
                // Reschedule any unprocessed external events so that they can be picked up
                // in the next iteration.
                context.RescheduleBufferedExternalEvents();
            }

            await context.RunDeferredTasks();
        }