private async Task InvokeUserCodeAndHandleResults()

in src/WebJobs.Extensions.DurableTask/Listener/TaskOrchestrationShim.cs [137:209]


        private async Task InvokeUserCodeAndHandleResults(
            RegisteredFunctionInfo orchestratorInfo,
            OrchestrationContext innerContext)
        {
            try
            {
                Task invokeTask = this.FunctionInvocationCallback();
                if (invokeTask is Task<object> resultTask)
                {
                    // Orchestrator threads cannot perform async I/O, so block on such out-of-proc threads.
                    // Possible performance implications; may need revisiting.
                    object returnValue = orchestratorInfo.IsOutOfProc ? resultTask.Result : await resultTask;

                    // If an "illegal await" (awaiting a non DF API) is detected, we throw an exception.
                    // This exception will not transition the orchestrator to a Failed state.
                    // TODO: look to fail orchestrator in illegal awaits. This may require DTFx support.
                    this.context.ThrowIfInvalidAccess();

                    if (returnValue != null)
                    {
                        if (orchestratorInfo.IsOutOfProc)
                        {
                            await this.TraceAndReplay(returnValue);
                        }
                        else
                        {
                            this.context.SetOutput(returnValue);
                        }
                    }
                }
                else
                {
                    throw new InvalidOperationException("The WebJobs runtime returned a invocation task that does not support return values!");
                }
            }
            catch (Exception e)
            {
                if (orchestratorInfo != null
                    && orchestratorInfo.IsOutOfProc
                    && OutOfProcExceptionHelpers.TryExtractOutOfProcStateJson(e.InnerException, out string returnValue)
                    && !string.IsNullOrEmpty(returnValue))
                {
                    try
                    {
                        await this.TraceAndReplay(returnValue, e);
                    }
                    catch (OrchestrationFailureException ex)
                    {
                        this.TraceAndSendExceptionNotification(ex);
                        this.context.OrchestrationException = ExceptionDispatchInfo.Capture(ex);
                        throw;
                    }
                }
                else
                {
                    this.TraceAndSendExceptionNotification(e);
                    var orchestrationException = new OrchestrationFailureException(
                        $"Orchestrator function '{this.context.Name}' failed: {e.Message}",
                        Utils.SerializeCause(e, innerContext.ErrorDataConverter));

                    this.context.OrchestrationException =
                        ExceptionDispatchInfo.Capture(orchestrationException);

                    DurableTaskExtension.TagActivityWithOrchestrationStatus(OrchestrationRuntimeStatus.Failed, this.context.InstanceId);

                    throw orchestrationException;
                }
            }
            finally
            {
                this.context.IsCompleted = true;
            }
        }