public static async Task TryExecuteAsync()

in src/Microsoft.Azure.WebJobs.Host/Executors/FunctionExecutorExtensions.cs [20:104]


        public static async Task<IDelayedException> TryExecuteAsync(this IFunctionExecutor executor, Func<IFunctionInstance> instanceFactory, ILoggerFactory loggerFactory, CancellationToken cancellationToken)
        {
            var attempt = 0;
            IDelayedException functionResult = null;
            ILogger logger = null;
            RetryContext retryContext = null;
            bool isRetryPendingSet = false;
            IRetryNotifier retryNotifier = executor as IRetryNotifier;

            try
            {
                while (true)
                {
                    IFunctionInstance functionInstance = instanceFactory.Invoke();
                    if (logger == null)
                    {
                        logger = loggerFactory.CreateLogger(LogCategories.CreateFunctionCategory(functionInstance.FunctionDescriptor.LogName));
                    }

                    if (retryContext == null && functionInstance.FunctionDescriptor.RetryStrategy != null)
                    {
                        retryContext = new RetryContext();
                        retryContext.MaxRetryCount = functionInstance.FunctionDescriptor.RetryStrategy.MaxRetryCount;
                    }

                    if (retryContext != null && functionInstance is FunctionInstance instance)
                    {
                        retryContext.Instance = instance;
                        instance.RetryContext = retryContext;
                    }
                    functionResult = await executor.TryExecuteAsync(functionInstance, cancellationToken);

                    if (functionResult == null)
                    {
                        // function invocation succeeded
                        break;
                    }
                    if (functionInstance.FunctionDescriptor.RetryStrategy == null)
                    {
                        // retry is not configured
                        break;
                    }

                    IRetryStrategy retryStrategy = functionInstance.FunctionDescriptor.RetryStrategy;
                    if (retryStrategy.MaxRetryCount != -1 && attempt == retryStrategy.MaxRetryCount)
                    {
                        // retry count exceeded
                        logger.LogFunctionRetriesFailed(attempt, functionResult);
                        break;
                    }

                    retryContext.RetryCount = ++attempt;
                    retryContext.Exception = functionResult?.Exception;

                    TimeSpan nextDelay = retryStrategy.GetNextDelay(retryContext);
                    logger.LogFunctionRetryAttempt(nextDelay, attempt, retryStrategy.MaxRetryCount);

                    if (retryNotifier != null && !isRetryPendingSet)
                    {
                        isRetryPendingSet = true;
                        retryNotifier.RetryPending();
                    }

                    try
                    {
                        // If the invocation is cancelled retries must stop.
                        await Task.Delay(nextDelay, cancellationToken);
                    }
                    catch (TaskCanceledException)
                    {
                        logger.LogExitFromRetryLoop();
                        break;
                    }
                }
            }
            finally
            {
                if (retryNotifier != null && isRetryPendingSet)
                {
                    retryNotifier.RetryComplete();
                }
            }

            return functionResult;
        }