private async Task <TResult> CallDurableTaskFunctionAsync <TResult>(
            string functionName,
            FunctionType functionType,
            string instanceId,
            RetryOptions retryOptions,
            object input)
        {
            this.ThrowIfInvalidAccess();

            // TODO: Support for versioning
            string version = DefaultVersion;

            this.config.ThrowIfFunctionDoesNotExist(functionName, functionType);

            Task <TResult> callTask;

            switch (functionType)
            {
            case FunctionType.Activity:
                System.Diagnostics.Debug.Assert(instanceId == null, "The instanceId parameter should not be used for activity functions.");
                if (retryOptions == null)
                {
                    callTask = this.innerContext.ScheduleTask <TResult>(functionName, version, input);
                }
                else
                {
                    callTask = this.innerContext.ScheduleWithRetry <TResult>(
                        functionName,
                        version,
                        retryOptions.GetRetryOptions(),
                        input);
                }

                break;

            case FunctionType.Orchestrator:
                if (retryOptions == null)
                {
                    callTask = this.innerContext.CreateSubOrchestrationInstance <TResult>(
                        functionName,
                        version,
                        instanceId,
                        input);
                }
                else
                {
                    callTask = this.innerContext.CreateSubOrchestrationInstanceWithRetry <TResult>(
                        functionName,
                        version,
                        instanceId,
                        retryOptions.GetRetryOptions(),
                        input);
                }

                break;

            default:
                throw new InvalidOperationException($"Unexpected function type '{functionType}'.");
            }

            string sourceFunctionId = this.orchestrationName;

            this.config.TraceHelper.FunctionScheduled(
                this.config.Options.HubName,
                functionName,
                this.InstanceId,
                reason: sourceFunctionId,
                functionType: functionType,
                isReplay: this.innerContext.IsReplaying);

            TResult   output;
            Exception exception = null;

            try
            {
                output = await callTask;
            }
            catch (TaskFailedException e)
            {
                exception = e;
                string message = string.Format(
                    "The {0} function '{1}' failed: \"{2}\". See the function execution logs for additional details.",
                    functionType.ToString().ToLowerInvariant(),
                    functionName,
                    e.InnerException?.Message);
                throw new FunctionFailedException(message, e.InnerException);
            }
            catch (SubOrchestrationFailedException e)
            {
                exception = e;
                string message = string.Format(
                    "The {0} function '{1}' failed: \"{2}\". See the function execution logs for additional details.",
                    functionType.ToString().ToLowerInvariant(),
                    functionName,
                    e.InnerException?.Message);
                throw new FunctionFailedException(message, e.InnerException);
            }
            catch (Exception e)
            {
                exception = e;
                throw;
            }
            finally
            {
                if (exception != null && this.innerContext.IsReplaying)
                {
                    // If this were not a replay, then the activity function trigger would have already
                    // emitted a FunctionFailed trace with the full exception details.
                    this.config.TraceHelper.FunctionFailed(
                        this.config.Options.HubName,
                        functionName,
                        this.InstanceId,
                        reason: $"(replayed {exception.GetType().Name})",
                        functionType: functionType,
                        isReplay: true);
                }
            }

            if (this.innerContext.IsReplaying)
            {
                // If this were not a replay, then the activity function trigger would have already
                // emitted a FunctionCompleted trace with the actual output details.
                this.config.TraceHelper.FunctionCompleted(
                    this.config.Options.HubName,
                    functionName,
                    this.InstanceId,
                    output: "(replayed)",
                    continuedAsNew: false,
                    functionType: functionType,
                    isReplay: true);
            }

            return(output);
        }
Esempio n. 2
0
        private async Task <TResult> CallDurableTaskFunctionAsync <TResult>(string functionName,
                                                                            FunctionType functionType,
                                                                            RetryOptions retryOptions,
                                                                            object[] parameters)
        {
            this.ThrowIfInvalidAccess();

            // TODO: Support for versioning
            string version = DefaultVersion;

            this.config.ThrowIfInvalidFunctionType(functionName, functionType, version);

            Task <TResult> callTask;

            switch (functionType)
            {
            case FunctionType.Activity:
                if (retryOptions == null)
                {
                    callTask = this.innerContext.ScheduleTask <TResult>(functionName, version, parameters);
                }
                else
                {
                    callTask = this.innerContext.ScheduleWithRetry <TResult>(functionName, version,
                                                                             retryOptions.GetRetryOptions(), parameters);
                }
                break;

            case FunctionType.Orchestrator:
                if (retryOptions == null)
                {
                    callTask = this.innerContext.CreateSubOrchestrationInstance <TResult>(functionName, version,
                                                                                          JsonConvert.SerializeObject(parameters));
                }
                else
                {
                    callTask = this.innerContext.CreateSubOrchestrationInstanceWithRetry <TResult>(functionName, version,
                                                                                                   retryOptions.GetRetryOptions(), JsonConvert.SerializeObject(parameters));
                }
                break;

            default:
                throw new InvalidOperationException(
                          string.Format("Unexpected function type '{0}'.",
                                        functionType));
            }

            string sourceFunctionId = string.IsNullOrEmpty(this.orchestrationVersion)
                ? this.orchestrationName
                : this.orchestrationName + "/" + this.orchestrationVersion;

            this.config.TraceHelper.FunctionScheduled(
                this.config.HubName,
                functionName,
                version,
                this.InstanceId,
                reason: sourceFunctionId,
                functionType: functionType,
                isReplay: this.innerContext.IsReplaying);

            TResult output;

            try
            {
                output = await callTask;
            }
            catch (Exception e)
            {
                if (this.innerContext.IsReplaying)
                {
                    // If this were not a replay, then the activity function trigger would have already
                    // emitted a FunctionFailed trace with the full exception details.
                    this.config.TraceHelper.FunctionFailed(
                        this.config.HubName,
                        functionName,
                        version,
                        this.InstanceId,
                        reason: $"(replayed {e.GetType().Name})",
                        functionType: FunctionType.Activity,
                        isReplay: true);
                }
                throw;
            }

            if (this.innerContext.IsReplaying)
            {
                // If this were not a replay, then the activity function trigger would have already
                // emitted a FunctionCompleted trace with the actual output details.
                this.config.TraceHelper.FunctionCompleted(
                    this.config.HubName,
                    functionName,
                    version,
                    this.InstanceId,
                    output: "(replayed)",
                    continuedAsNew: false,
                    functionType: FunctionType.Activity,
                    isReplay: true);
            }

            return(output);
        }