/// <summary>
        /// Initializes a new instance of the <see cref="CompilationUnitExceptionHandlingProxy"/> class.
        /// </summary>
        /// <param name="successor">
        /// The successor.
        /// </param>
        /// <param name="exceptionHandler">
        /// The exception Handler.
        /// </param>
        public CompilationUnitExceptionHandlingProxy(IExecutionStrategy successor, Action<Exception> exceptionHandler)
        {
            this.successor = successor;
            this.exceptionHandler = exceptionHandler;

            this.successor.MustNotBeNull();
            this.exceptionHandler.MustNotBeNull("The exception handler must not be null.");
        }
Example #2
0
 public TaskContext(
     IExecutionStrategy executionStrategy, 
     ILogRenderer logRenderer, 
     IDirectory workDirectory, 
     IEnvironment environment, 
     ITaskInterceptor interceptor)
     : this(ResultsStorage.Empty, executionStrategy, null, logRenderer, workDirectory, environment, interceptor, Identities.Empty)
 {
 }
Example #3
0
 private TaskContext(
     IResultsStorage results, 
     IExecutionStrategy executionStrategy, 
     Identity identity, 
     ILogRenderer logRenderer, 
     IDirectory workDirectory, 
     IEnvironment environment, 
     ITaskInterceptor interceptor, 
     Identities identitiesTail)
 {
     _identity = identity;
     _results = results;
     _executionStrategy = executionStrategy;
     _logRenderer = logRenderer;
     _workDirectory = workDirectory;
     _environment = environment;
     _interceptor = interceptor;
     _identitiesTail = identitiesTail;
     _log = new LogHelper(message => logRenderer.Render(message, GetFullIdentitiesPath()));
 }
        /// <summary>
        /// Initializes a new instance of the <see cref="InitTestAssemblyCompilationUnitProxy"/> class. 
        /// </summary>
        /// <param name="successor">
        /// The successor.
        /// </param>
        public InitTestAssemblyCompilationUnitProxy(IExecutionStrategy successor)
        {
            this.successor = successor;

            this.successor.MustNotBeNull();
        }
 public ScopedExecutionStrategy(IDependencyInjector injector, IExecutionStrategy innerStrategy)
 {
     _injector      = injector;
     _innerStrategy = innerStrategy;
 }
 /// <summary>
 ///     Executes the specified asynchronous operation in a transaction. Allows to check whether
 ///     the transaction has been rolled back if an error occurs during commit.
 /// </summary>
 /// <remarks>
 ///     See <see href="https://aka.ms/efcore-docs-connection-resiliency">Connection resiliency and database retries</see>
 ///     for more information and examples.
 /// </remarks>
 /// <param name="strategy">The strategy that will be used for the execution.</param>
 /// <param name="isolationLevel">The isolation level to use for the transaction.</param>
 /// <param name="operation">
 ///     A function that returns a started task.
 /// </param>
 /// <param name="verifySucceeded">
 ///     A delegate that tests whether the operation succeeded even though an exception was thrown when the
 ///     transaction was being committed.
 /// </param>
 /// <returns>
 ///     A task that will run to completion if the original task completes successfully (either the
 ///     first time or after retrying transient failures). If the task fails with a non-transient error or
 ///     the retry limit is reached, the returned task will become faulted and the exception must be observed.
 /// </returns>
 /// <exception cref="RetryLimitExceededException">
 ///     The operation has not succeeded after the configured number of retries.
 /// </exception>
 public static Task ExecuteInTransactionAsync(
     this IExecutionStrategy strategy,
     Func <Task> operation,
     Func <Task <bool> > verifySucceeded,
     IsolationLevel isolationLevel)
 => strategy.ExecuteInTransactionAsync <object?>(null, (_, _) => operation(), (_, _) => verifySucceeded(), isolationLevel);
Example #7
0
        /// <summary>
        /// Runs the specified target.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="strategy">The execution strategy.</param>
        /// <param name="settings">The execution settings.</param>
        /// <exception cref="Exception"></exception>
        /// <returns>The resulting report.</returns>
        public async Task <CakeReport> RunTargetAsync(ICakeContext context, IExecutionStrategy strategy, ExecutionSettings settings)
        {
            if (settings == null)
            {
                throw new ArgumentNullException(nameof(settings));
            }
            if (string.IsNullOrWhiteSpace(settings.Target))
            {
                throw new ArgumentException("No target specified.", nameof(settings));
            }

            if (strategy == null)
            {
                throw new ArgumentNullException(nameof(strategy));
            }

            // Ensure that registered actions are valid.
            _actions.Validate();

            // Create a graph out of the tasks.
            var graph = CakeGraphBuilder.Build(_tasks);

            // Make sure target exist.
            var target = settings.Target;

            if (!graph.Exist(target))
            {
                const string format = "The target '{0}' was not found.";
                throw new CakeException(string.Format(CultureInfo.InvariantCulture, format, target));
            }

            // This isn't pretty, but we need to keep track of exceptions thrown
            // while running a setup action, or a task. We do this since we don't
            // want to throw teardown exceptions if an exception was thrown previously.
            var       exceptionWasThrown = false;
            Exception thrownException    = null;

            var stopWatch = new Stopwatch();
            var report    = new CakeReport();

            try
            {
                // Get all nodes to traverse in the correct order.
                var orderedTasks = graph.Traverse(target)
                                   .Select(y => _tasks.FirstOrDefault(x =>
                                                                      x.Name.Equals(y, StringComparison.OrdinalIgnoreCase))).ToArray();

                // Get target node
                var targetNode = orderedTasks
                                 .FirstOrDefault(node => node.Name.Equals(target, StringComparison.OrdinalIgnoreCase));

                PerformSetup(strategy, context, targetNode, orderedTasks, stopWatch, report);

                if (settings.Exclusive)
                {
                    // Execute only the target task.
                    var task = _tasks.FirstOrDefault(x => x.Name.Equals(settings.Target, StringComparison.OrdinalIgnoreCase));
                    await RunTask(context, strategy, task, target, stopWatch, report);

                    return(report);
                }

                // Ignore tasks until the continue from target
                orderedTasks = RemoveTasksToSkip(settings.ContinueFromTaskName, orderedTasks);

                // Execute all scheduled tasks.
                foreach (var task in orderedTasks)
                {
                    await RunTask(context, strategy, task, target, stopWatch, report);
                }

                return(report);
            }
            catch (Exception ex)
            {
                exceptionWasThrown = true;
                thrownException    = ex;
                throw;
            }
            finally
            {
                PerformTeardown(strategy, context, stopWatch, report, exceptionWasThrown, thrownException);
            }
        }
Example #8
0
        /// <summary>
        /// Runs the specified target.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="strategy">The execution strategy.</param>
        /// <param name="target">The target to run.</param>
        /// <returns>The resulting report.</returns>
        public async Task <CakeReport> RunTargetAsync(ICakeContext context, IExecutionStrategy strategy, string target)
        {
            if (target == null)
            {
                throw new ArgumentNullException(nameof(target));
            }
            if (strategy == null)
            {
                throw new ArgumentNullException(nameof(strategy));
            }

            var graph = CakeGraphBuilder.Build(_tasks);

            // Make sure target exist.
            if (!graph.Exist(target))
            {
                const string format = "The target '{0}' was not found.";
                throw new CakeException(string.Format(CultureInfo.InvariantCulture, format, target));
            }

            // This isn't pretty, but we need to keep track of exceptions thrown
            // while running a setup action, or a task. We do this since we don't
            // want to throw teardown exceptions if an exception was thrown previously.
            var       exceptionWasThrown = false;
            Exception thrownException    = null;

            var stopWatch = new Stopwatch();
            var report    = new CakeReport();

            try
            {
                PerformSetup(strategy, context, stopWatch, report);

                foreach (var taskNode in graph.Traverse(target))
                {
                    // Get the task.
                    var task = _tasks.FirstOrDefault(x => x.Name.Equals(taskNode, StringComparison.OrdinalIgnoreCase));
                    Debug.Assert(task != null, "Node should not be null.");

                    // Is this the current target?
                    var isTarget = task.Name.Equals(target, StringComparison.OrdinalIgnoreCase);

                    // Should we execute the task?
                    if (ShouldTaskExecute(context, task, isTarget))
                    {
                        await ExecuteTaskAsync(context, strategy, stopWatch, task, report).ConfigureAwait(false);
                    }
                    else
                    {
                        SkipTask(context, strategy, task, report);
                    }
                }

                return(report);
            }
            catch (Exception ex)
            {
                exceptionWasThrown = true;
                thrownException    = ex;
                throw;
            }
            finally
            {
                PerformTeardown(strategy, context, stopWatch, report, exceptionWasThrown, thrownException);
            }
        }
 /// <summary>
 ///     Executes the specified operation in a transaction and returns the result. Allows to check whether
 ///     the transaction has been rolled back if an error occurs during commit.
 /// </summary>
 /// <param name="strategy"> The strategy that will be used for the execution. </param>
 /// <param name="operation">
 ///     A delegate representing an executable operation that returns the result of type <typeparamref name="TResult" />.
 /// </param>
 /// <param name="verifySucceeded">
 ///     A delegate that tests whether the operation succeeded even though an exception was thrown when the
 ///     transaction was being committed.
 /// </param>
 /// <typeparam name="TResult"> The return type of <paramref name="operation" />. </typeparam>
 /// <returns> The result from the operation. </returns>
 /// <exception cref="RetryLimitExceededException">
 ///     The operation has not succeeded after the configured number of retries.
 /// </exception>
 public static TResult ExecuteInTransaction <TResult>(
     [NotNull] this IExecutionStrategy strategy,
     [NotNull] Func <TResult> operation,
     [NotNull] Func <bool> verifySucceeded)
 => strategy.ExecuteInTransaction <object, TResult>(null, s => operation(), s => verifySucceeded());
 /// <summary>
 ///     Executes the specified operation in a transaction and returns the result. Allows to check whether
 ///     the transaction has been rolled back if an error occurs during commit.
 /// </summary>
 /// <remarks>
 ///     See <see href="https://aka.ms/efcore-docs-connection-resiliency">Connection resiliency and database retries</see>
 ///     for more information and examples.
 /// </remarks>
 /// <param name="strategy">The strategy that will be used for the execution.</param>
 /// <param name="operation">
 ///     A delegate representing an executable operation that returns the result of type <typeparamref name="TResult" />.
 /// </param>
 /// <param name="verifySucceeded">
 ///     A delegate that tests whether the operation succeeded even though an exception was thrown when the
 ///     transaction was being committed.
 /// </param>
 /// <typeparam name="TResult">The return type of <paramref name="operation" />.</typeparam>
 /// <returns>The result from the operation.</returns>
 /// <exception cref="RetryLimitExceededException">
 ///     The operation has not succeeded after the configured number of retries.
 /// </exception>
 public static TResult ExecuteInTransaction <TResult>(
     this IExecutionStrategy strategy,
     Func <TResult> operation,
     Func <bool> verifySucceeded)
 => strategy.ExecuteInTransaction <object?, TResult>(null, _ => operation(), _ => verifySucceeded());
Example #11
0
 private void SkipTask(ICakeContext context, IExecutionStrategy strategy, CakeTask task)
 {
     PerformTaskSetup(context, strategy, task, true);
     strategy.Skip(task);
     PerformTaskTeardown(context, strategy, task, TimeSpan.Zero, true, false);
 }
 public virtual void OnActionExecuting(IExecutionStrategy filterContext)
 {
 }
Example #13
0
        private async Task ExecuteTaskAsync(ICakeContext context, IExecutionStrategy strategy, Stopwatch stopWatch,
                                            CakeTask task, CakeReport report)
        {
            stopWatch.Restart();

            PerformTaskSetup(context, strategy, task, false);

            Exception taskException = null;

            try
            {
                // Execute the task.
                await strategy.ExecuteAsync(task, context).ConfigureAwait(false);
            }
            catch (Exception exception)
            {
                _log.Error("An error occurred when executing task '{0}'.", task.Name);

                taskException = exception;

                // Got an error reporter?
                if (task.ErrorReporter != null)
                {
                    await ReportErrorsAsync(strategy, task.ErrorReporter, exception);
                }

                // Got an error handler?
                if (task.ErrorHandler != null)
                {
                    await HandleErrorsAsync(strategy, task.ErrorHandler, exception, context);
                }
                else
                {
                    // No error handler defined for this task.
                    // Rethrow the exception and let it propagate.
                    throw;
                }
            }
            finally
            {
                if (task.FinallyHandler != null)
                {
                    await strategy.InvokeFinallyAsync(task.FinallyHandler);
                }

                PerformTaskTeardown(context, strategy, task, stopWatch.Elapsed, false, taskException);
            }

            // Add the task results to the report
            if (IsDelegatedTask(task))
            {
                report.AddDelegated(task.Name, stopWatch.Elapsed);
            }
            else if (taskException is null)
            {
                report.Add(task.Name, CakeReportEntryCategory.Task, stopWatch.Elapsed);
            }
            else
            {
                report.AddFailed(task.Name, stopWatch.Elapsed);
            }
        }
Example #14
0
        /// <summary>
        /// Initializes a new instance of the <see cref="CompilationUnit"/> class.
        /// </summary>
        /// <param name="successor">
        /// The successor.
        /// </param>
        public CompilationUnit(IExecutionStrategy successor)
        {
            this.successor = successor;

            this.successor.MustNotBeNull();
        }
Example #15
0
 public MockDIDocumentExecuter(IExecutionStrategy executionStrategy) : base(executionStrategy)
 {
 }
Example #16
0
 /// <summary>
 ///     Executes the specified operation in a transaction. Allows to check whether
 ///     the transaction has been rolled back if an error occurs during commit.
 /// </summary>
 /// <param name="strategy"> The strategy that will be used for the execution. </param>
 /// <param name="isolationLevel"> The isolation level to use for the transaction. </param>
 /// <param name="operation">
 ///     A delegate representing an executable operation.
 /// </param>
 /// <param name="verifySucceeded">
 ///     A delegate that tests whether the operation succeeded even though an exception was thrown when the
 ///     transaction was being committed.
 /// </param>
 /// <exception cref="RetryLimitExceededException">
 ///     The operation has not succeeded after the configured number of retries.
 /// </exception>
 public static void ExecuteInTransaction(
     [NotNull] this IExecutionStrategy strategy,
     [NotNull] Action operation,
     [NotNull] Func <bool> verifySucceeded,
     IsolationLevel isolationLevel)
 => strategy.ExecuteInTransaction <object>(null, s => operation(), s => verifySucceeded(), isolationLevel);
Example #17
0
        internal static void SeedData(StoreContext context)
        {
            try
            {
                var cust = new Customer()
                {
                    Id           = 1,
                    EmailAddress = "*****@*****.**",
                    Password     = "******",
                    FullName     = "Super Spy",
                };
                if (!context.Customers.Any())
                {
                    IExecutionStrategy strategy = context.Database.CreateExecutionStrategy();
                    strategy.Execute(() =>
                    {
                        using (var transaction = context.Database.BeginTransaction())
                        {
                            try
                            {
                                context.Database.ExecuteSqlRaw("DBCC CHECKIDENT ('Store.Customers', RESEED, 0);");
                                context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Store.Customers" + " ON");
                                context.Customers.Add(cust);
                                context.SaveChanges();
                                context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Store.Customers" + " OFF");
                                transaction.Commit();
                            }
                            catch (Exception e)
                            {
                                transaction.Rollback();
                            }
                        }
                    });
                }

                if (!context.Categories.Any())
                {
                    context.Database.ExecuteSqlRaw("DBCC CHECKIDENT ('Store.Categories', RESEED, 0);");
                    IExecutionStrategy strategy = context.Database.CreateExecutionStrategy();
                    strategy.Execute(() =>
                    {
                        using (var transaction = context.Database.BeginTransaction())
                        {
                            context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Store.Categories" + " ON");
                            context.Categories.AddRange(SampleData.GetCategories());
                            context.SaveChanges();
                            context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Store.Categories" + " OFF");
                            transaction.Commit();
                        }
                    });
                }

                if (!context.Products.Any())
                {
                    context.Database.ExecuteSqlRaw("DBCC CHECKIDENT ('Store.Products', RESEED, 0);");
                    IExecutionStrategy strategy = context.Database.CreateExecutionStrategy();
                    strategy.Execute(() =>
                    {
                        using (var transaction = context.Database.BeginTransaction())
                        {
                            context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Store.Products" + " ON");
                            context.Products.AddRange(SampleData.GetProducts());
                            context.SaveChanges();
                            context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Store.Products" + " OFF");
                            transaction.Commit();
                        }
                    });
                }

                if (!context.Orders.Any())
                {
                    context.Database.ExecuteSqlRaw("DBCC CHECKIDENT ('Store.Orders', RESEED, 0);");
                    IExecutionStrategy strategy = context.Database.CreateExecutionStrategy();
                    strategy.Execute(() =>
                    {
                        using (var transaction = context.Database.BeginTransaction())
                        {
                            context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Store.Orders" + " ON");
                            context.Orders.AddRange(SampleData.GetOrders());
                            context.SaveChanges();
                            context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Store.Orders" + " OFF");
                            transaction.Commit();
                        }
                    });
                }

                if (!context.OrderDetails.Any())
                {
                    var products = new List <Product>
                    {
                        context.Categories
                        .Include(c => c.Products).FirstOrDefault()?
                        .Products.Skip(3).FirstOrDefault(),
                        context.Categories.Skip(2)
                        .Include(c => c.Products).FirstOrDefault()?
                        .Products.Skip(2).FirstOrDefault(),
                        context.Categories.Skip(5)
                        .Include(c => c.Products).FirstOrDefault()?
                        .Products.Skip(1).FirstOrDefault(),
                    };
                    context.Database.ExecuteSqlRaw("DBCC CHECKIDENT ('Store.OrderDetails', RESEED, 0);");
                    IExecutionStrategy strategy = context.Database.CreateExecutionStrategy();
                    strategy.Execute(() =>
                    {
                        using (var transaction = context.Database.BeginTransaction())
                        {
                            context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Store.OrderDetails" + " ON");
                            context.OrderDetails.AddRange(SampleData.GetOrderDetails(products));
                            context.SaveChanges();
                            context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Store.OrderDetails" + " OFF");
                            transaction.Commit();
                        }
                    });
                }

                if (!context.ShoppingCartRecords.Any())
                {
                    var products = new List <Product>
                    {
                        context.Categories.Skip(2)
                        .Include(c => c.Products).FirstOrDefault()?
                        .Products.Skip(1).FirstOrDefault()
                    };
                    context.Database.ExecuteSqlRaw("DBCC CHECKIDENT ('Store.ShoppingCartRecords', RESEED, 0);");
                    IExecutionStrategy strategy = context.Database.CreateExecutionStrategy();
                    strategy.Execute(() =>
                    {
                        using (var transaction = context.Database.BeginTransaction())
                        {
                            context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Store.ShoppingCartRecords" + " ON");
                            context.ShoppingCartRecords.AddRange(SampleData.GetCart(products));
                            context.SaveChanges();
                            context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Store.ShoppingCartRecords" + " OFF");
                            transaction.Commit();
                        }
                    });
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                throw;
            }
        }
 /// <summary>
 ///     Executes the specified asynchronous operation and returns the result.
 /// </summary>
 /// <param name="strategy">The strategy that will be used for the execution.</param>
 /// <param name="state">The state that will be passed to the operation.</param>
 /// <param name="operation">
 ///     A function that returns a started task of type <typeparamref name="TResult" />.
 /// </param>
 /// <param name="cancellationToken">
 ///     A cancellation token used to cancel the retry operation, but not operations that are already in flight
 ///     or that already completed successfully.
 /// </param>
 /// <typeparam name="TState">The type of the state.</typeparam>
 /// <typeparam name="TResult">
 ///     The result type of the <see cref="Task{T}" /> returned by <paramref name="operation" />.
 /// </typeparam>
 /// <returns>
 ///     A task that will run to completion if the original task completes successfully (either the
 ///     first time or after retrying transient failures). If the task fails with a non-transient error or
 ///     the retry limit is reached, the returned task will become faulted and the exception must be observed.
 /// </returns>
 public static Task <TResult> ExecuteAsync <TState, TResult>(
     [NotNull] this IExecutionStrategy strategy,
     [CanBeNull] TState state,
     [NotNull] Func <TState, CancellationToken, Task <TResult> > operation,
     CancellationToken cancellationToken)
 => strategy.ExecuteAsync(state, operation, verifySucceeded: null, cancellationToken: cancellationToken);
Example #19
0
        /// <summary>
        /// Initializes a new instance of the <see cref="InitCompilerCompilationUnitProxy"/> class.
        /// </summary>
        /// <param name="successor">
        /// The successor.
        /// </param>
        public InitCompilerCompilationUnitProxy(IExecutionStrategy successor)
        {
            this.successor = successor;

            this.successor.MustNotBeNull();
        }
 /// <summary>
 /// Initializes a new instance with the specified execution strategy for child nodes.
 /// </summary>
 public SubscriptionExecutionStrategy(IExecutionStrategy baseExecutionStrategy)
 {
     _baseExecutionStrategy = baseExecutionStrategy ?? throw new ArgumentNullException(nameof(baseExecutionStrategy));
 }
Example #21
0
 /// <summary>
 ///     Executes the specified operation and returns the result.
 /// </summary>
 /// <param name="strategy">The strategy that will be used for the execution.</param>
 /// <param name="state">The state that will be passed to the operation.</param>
 /// <param name="operation">
 ///     A delegate representing an executable operation that returns the result of type <typeparamref name="TResult" />.
 /// </param>
 /// <typeparam name="TState">The type of the state.</typeparam>
 /// <typeparam name="TResult">The return type of <paramref name="operation" />.</typeparam>
 /// <returns>The result from the operation.</returns>
 public static TResult Execute <TState, TResult>(
     this IExecutionStrategy strategy,
     TState state,
     Func <TState, TResult> operation)
 => strategy.Execute(state, operation, verifySucceeded: null);
Example #22
0
 /// <summary>
 /// Runs the specified target using the specified <see cref="T:Cake.Core.IExecutionStrategy" />.
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="strategy">The execution strategy.</param>
 /// <param name="settings">The execution settings.</param>
 /// <returns>
 /// The resulting report.
 /// </returns>
 public Task <CakeReport> RunTargetAsync(ICakeContext context, IExecutionStrategy strategy, ExecutionSettings settings)
 {
     return(_engine.RunTargetAsync(context, strategy, settings));
 }
Example #23
0
 /// <summary>
 ///     Executes the specified operation in a transaction. Allows to check whether
 ///     the transaction has been rolled back if an error occurs during commit.
 /// </summary>
 /// <param name="strategy"> The strategy that will be used for the execution. </param>
 /// <param name="operation">
 ///     A delegate representing an executable operation.
 /// </param>
 /// <param name="verifySucceeded">
 ///     A delegate that tests whether the operation succeeded even though an exception was thrown when the
 ///     transaction was being committed.
 /// </param>
 /// <exception cref="RetryLimitExceededException">
 ///     The operation has not succeeded after the configured number of retries.
 /// </exception>
 public static void ExecuteInTransaction(
     this IExecutionStrategy strategy,
     Action operation,
     Func <bool> verifySucceeded)
 => strategy.ExecuteInTransaction <object?>(null, s => operation(), s => verifySucceeded());
 /// <summary>
 ///     Executes the specified operation in a transaction. Allows to check whether
 ///     the transaction has been rolled back if an error occurs during commit.
 /// </summary>
 /// <remarks>
 ///     See <see href="https://aka.ms/efcore-docs-connection-resiliency">Connection resiliency and database retries</see>
 ///     for more information and examples.
 /// </remarks>
 /// <param name="strategy">The strategy that will be used for the execution.</param>
 /// <param name="isolationLevel">The isolation level to use for the transaction.</param>
 /// <param name="operation">
 ///     A delegate representing an executable operation.
 /// </param>
 /// <param name="verifySucceeded">
 ///     A delegate that tests whether the operation succeeded even though an exception was thrown when the
 ///     transaction was being committed.
 /// </param>
 /// <exception cref="RetryLimitExceededException">
 ///     The operation has not succeeded after the configured number of retries.
 /// </exception>
 public static void ExecuteInTransaction(
     this IExecutionStrategy strategy,
     Action operation,
     Func <bool> verifySucceeded,
     IsolationLevel isolationLevel)
 => strategy.ExecuteInTransaction <object?>(null, _ => operation(), _ => verifySucceeded(), isolationLevel);
Example #25
0
 /// <summary>
 ///     Executes the specified asynchronous operation in a transaction. Allows to check whether
 ///     the transaction has been rolled back if an error occurs during commit.
 /// </summary>
 /// <param name="strategy"> The strategy that will be used for the execution. </param>
 /// <param name="operation">
 ///     A function that returns a started task.
 /// </param>
 /// <param name="verifySucceeded">
 ///     A delegate that tests whether the operation succeeded even though an exception was thrown when the
 ///     transaction was being committed.
 /// </param>
 /// <returns>
 ///     A task that will run to completion if the original task completes successfully (either the
 ///     first time or after retrying transient failures). If the task fails with a non-transient error or
 ///     the retry limit is reached, the returned task will become faulted and the exception must be observed.
 /// </returns>
 /// <exception cref="RetryLimitExceededException">
 ///     The operation has not succeeded after the configured number of retries.
 /// </exception>
 public static Task ExecuteInTransactionAsync(
     this IExecutionStrategy strategy,
     Func <Task> operation,
     Func <Task <bool> > verifySucceeded)
 => strategy.ExecuteInTransactionAsync <object?>(null, (s, ct) => operation(), (s, ct) => verifySucceeded());
Example #26
0
        /// <summary>
        /// Run samples for Order By queries.
        /// </summary>
        /// <returns>a Task object.</returns>
        private async Task <RunSummary> ExecuteAsync(BenchmarkConfig config)
        {
            using (CosmosClient cosmosClient = config.CreateCosmosClient(config.Key))
            {
                Microsoft.Azure.Cosmos.Database database = cosmosClient.GetDatabase(config.Database);
                if (config.CleanupOnStart)
                {
                    await database.DeleteStreamAsync();
                }

                ContainerResponse containerResponse = await Program.CreatePartitionedContainerAsync(config, cosmosClient);

                Container container = containerResponse;

                int?currentContainerThroughput = await container.ReadThroughputAsync();

                if (!currentContainerThroughput.HasValue)
                {
                    // Container throughput is not configured. It is shared database throughput
                    ThroughputResponse throughputResponse = await database.ReadThroughputAsync(requestOptions : null);

                    throw new InvalidOperationException($"Using database {config.Database} with {throughputResponse.Resource.Throughput} RU/s. " +
                                                        $"Container {config.Container} must have a configured throughput.");
                }

                Console.WriteLine($"Using container {config.Container} with {currentContainerThroughput} RU/s");
                int taskCount = config.GetTaskCount(currentContainerThroughput.Value);

                Console.WriteLine("Starting Inserts with {0} tasks", taskCount);
                Console.WriteLine();

                string partitionKeyPath = containerResponse.Resource.PartitionKeyPath;
                int    opsPerTask       = config.ItemCount / taskCount;

                // TBD: 2 clients SxS some overhead
                RunSummary runSummary;
                using (DocumentClient documentClient = config.CreateDocumentClient(config.Key))
                {
                    Func <IBenchmarkOperation> benchmarkOperationFactory = this.GetBenchmarkFactory(
                        config,
                        partitionKeyPath,
                        cosmosClient,
                        documentClient);

                    if (config.DisableCoreSdkLogging)
                    {
                        // Do it after client initialization (HACK)
                        Program.ClearCoreSdkListeners();
                    }

                    IExecutionStrategy execution = IExecutionStrategy.StartNew(config, benchmarkOperationFactory);
                    runSummary = await execution.ExecuteAsync(taskCount, opsPerTask, config.TraceFailures, 0.01);
                }

                if (config.CleanupOnFinish)
                {
                    Console.WriteLine($"Deleting Database {config.Database}");
                    await database.DeleteStreamAsync();
                }

                runSummary.WorkloadType = config.WorkloadType;
                runSummary.id           = $"{DateTime.UtcNow:yyyy-MM-dd:HH-mm}-{config.CommitId}";
                runSummary.Commit       = config.CommitId;
                runSummary.CommitDate   = config.CommitDate;
                runSummary.CommitTime   = config.CommitTime;

                runSummary.Date        = DateTime.UtcNow.ToString("yyyy-MM-dd");
                runSummary.Time        = DateTime.UtcNow.ToString("HH-mm");
                runSummary.BranchName  = config.BranchName;
                runSummary.TotalOps    = config.ItemCount;
                runSummary.Concurrency = taskCount;
                runSummary.Database    = config.Database;
                runSummary.Container   = config.Container;
                runSummary.AccountName = config.EndPoint;
                runSummary.pk          = config.ResultsPartitionKeyValue;

                string consistencyLevel = config.ConsistencyLevel;
                if (string.IsNullOrWhiteSpace(consistencyLevel))
                {
                    AccountProperties accountProperties = await cosmosClient.ReadAccountAsync();

                    consistencyLevel = accountProperties.Consistency.DefaultConsistencyLevel.ToString();
                }
                runSummary.ConsistencyLevel = consistencyLevel;


                if (config.PublishResults)
                {
                    runSummary.Diagnostics = CosmosDiagnosticsLogger.GetDiagnostics();
                    await this.PublishResults(
                        config,
                        runSummary,
                        cosmosClient);
                }

                return(runSummary);
            }
        }
Example #27
0
 /// <summary>
 /// Initializes a new instance of the <see cref="DefaultExecutionStrategy"/> class.
 /// </summary>
 /// <param name="log">The log.</param>
 /// <param name="exclusiveTaskName">The optional exclusive task name to execute.</param>
 public CodeCakeExecutionStrategy(ICakeLog log, string exclusiveTaskName = null)
 {
     _exclusiveTaskName = exclusiveTaskName;
     _default           = new DefaultExecutionStrategy(log);
 }
Example #28
0
        /// <summary>
        /// Runs the specified target.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="strategy">The execution strategy.</param>
        /// <param name="target">The target to run.</param>
        /// <returns>The resulting report.</returns>
        public async Task <CakeReport> RunTargetAsync(ICakeContext context, IExecutionStrategy strategy, string target)
        {
            if (target == null)
            {
                throw new ArgumentNullException(nameof(target));
            }

            if (strategy == null)
            {
                throw new ArgumentNullException(nameof(strategy));
            }

            // Ensure that registered actions are valid.
            _actions.Validate();

            // Create a graph out of the tasks.
            var graph = CakeGraphBuilder.Build(_tasks);

            // Make sure target exist.
            if (!graph.Exist(target))
            {
                const string format = "The target '{0}' was not found.";
                throw new CakeException(string.Format(CultureInfo.InvariantCulture, format, target));
            }

            // This isn't pretty, but we need to keep track of exceptions thrown
            // while running a setup action, or a task. We do this since we don't
            // want to throw teardown exceptions if an exception was thrown previously.
            var       exceptionWasThrown = false;
            Exception thrownException    = null;

            var stopWatch = new Stopwatch();
            var report    = new CakeReport();

            try
            {
                // Get all nodes to traverse in the correct order.
                var orderedTasks = graph.Traverse(target)
                                   .Select(y => _tasks.FirstOrDefault(x =>
                                                                      x.Name.Equals(y, StringComparison.OrdinalIgnoreCase))).ToArray();

                // Get target node
                var targetNode = orderedTasks
                                 .FirstOrDefault(node => node.Name.Equals(target, StringComparison.OrdinalIgnoreCase));

                PerformSetup(strategy, context, targetNode, orderedTasks, stopWatch, report);

                foreach (var task in orderedTasks)
                {
                    // Is this the current target?
                    var isTarget = task.Name.Equals(target, StringComparison.OrdinalIgnoreCase);

                    // Should we execute the task?
                    var skipped = false;
                    foreach (var criteria in task.Criterias)
                    {
                        if (!ShouldTaskExecute(context, task, criteria, isTarget))
                        {
                            SkipTask(context, strategy, task, report, criteria);
                            skipped = true;
                            break;
                        }
                    }

                    if (!skipped)
                    {
                        await ExecuteTaskAsync(context, strategy, stopWatch, task, report).ConfigureAwait(false);
                    }
                }

                return(report);
            }
            catch (Exception ex)
            {
                exceptionWasThrown = true;
                thrownException    = ex;
                throw;
            }
            finally
            {
                PerformTeardown(strategy, context, stopWatch, report, exceptionWasThrown, thrownException);
            }
        }
Example #29
0
 /// <summary>
 ///     Executes the specified asynchronous operation in a transaction and returns the result. Allows to check whether
 ///     the transaction has been rolled back if an error occurs during commit.
 /// </summary>
 /// <param name="strategy"> The strategy that will be used for the execution. </param>
 /// <param name="operation">
 ///     A function that returns a started task of type <typeparamref name="TResult" />.
 /// </param>
 /// <param name="verifySucceeded">
 ///     A delegate that tests whether the operation succeeded even though an exception was thrown when the
 ///     transaction was being committed.
 /// </param>
 /// <param name="cancellationToken">
 ///     A cancellation token used to cancel the retry operation, but not operations that are already in flight
 ///     or that already completed successfully.
 /// </param>
 /// <typeparam name="TResult"> The result type of the <see cref="Task{T}" /> returned by <paramref name="operation" />. </typeparam>
 /// <returns>
 ///     A task that will run to completion if the original task completes successfully (either the
 ///     first time or after retrying transient failures). If the task fails with a non-transient error or
 ///     the retry limit is reached, the returned task will become faulted and the exception must be observed.
 /// </returns>
 /// <exception cref="RetryLimitExceededException">
 ///     The operation has not succeeded after the configured number of retries.
 /// </exception>
 public static Task <TResult> ExecuteInTransactionAsync <TResult>(
     [NotNull] this IExecutionStrategy strategy,
     [NotNull] Func <CancellationToken, Task <TResult> > operation,
     [NotNull] Func <CancellationToken, Task <bool> > verifySucceeded,
     CancellationToken cancellationToken = default)
 => strategy.ExecuteInTransactionAsync <object, TResult>(null, (s, ct) => operation(ct), (s, ct) => verifySucceeded(ct), cancellationToken);
 /// <summary>
 ///     Executes the specified operation in a transaction and returns the result. Allows to check whether
 ///     the transaction has been rolled back if an error occurs during commit.
 /// </summary>
 /// <remarks>
 ///     See <see href="https://aka.ms/efcore-docs-connection-resiliency">Connection resiliency and database retries</see>
 ///     for more information and examples.
 /// </remarks>
 /// <param name="strategy">The strategy that will be used for the execution.</param>
 /// <param name="isolationLevel">The isolation level to use for the transaction.</param>
 /// <param name="operation">
 ///     A delegate representing an executable operation that returns the result of type <typeparamref name="TResult" />.
 /// </param>
 /// <param name="verifySucceeded">
 ///     A delegate that tests whether the operation succeeded even though an exception was thrown when the
 ///     transaction was being committed.
 /// </param>
 /// <typeparam name="TResult">The return type of <paramref name="operation" />.</typeparam>
 /// <returns>The result from the operation.</returns>
 /// <exception cref="RetryLimitExceededException">
 ///     The operation has not succeeded after the configured number of retries.
 /// </exception>
 public static TResult ExecuteInTransaction <TResult>(
     this IExecutionStrategy strategy,
     Func <TResult> operation,
     Func <bool> verifySucceeded,
     IsolationLevel isolationLevel)
 => strategy.ExecuteInTransaction <object?, TResult>(null, s => operation(), s => verifySucceeded(), isolationLevel);
        public async Task <ExecutionResult> ExecuteAsync(ExecutionOptions options)
        {
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }
            if (options.Schema == null)
            {
                throw new InvalidOperationException("Cannot execute request if no schema is specified");
            }
            if (options.Query == null)
            {
                throw new InvalidOperationException("Cannot execute request if no query is specified");
            }
            if (options.FieldMiddleware == null)
            {
                throw new InvalidOperationException("Cannot execute request if no middleware builder specified");
            }

            var metrics = new Metrics(options.EnableMetrics).Start(options.OperationName);

            options.Schema.NameConverter = options.NameConverter;
            options.Schema.Filter        = options.SchemaFilter;

            ExecutionResult  result  = null;
            ExecutionContext context = null;

            try
            {
                if (!options.Schema.Initialized)
                {
                    using (metrics.Subject("schema", "Initializing schema"))
                    {
                        options.FieldMiddleware.ApplyTo(options.Schema);
                        options.Schema.Initialize();
                    }
                }

                var document = options.Document;
                using (metrics.Subject("document", "Building document"))
                {
                    if (document == null)
                    {
                        document = _documentBuilder.Build(options.Query);
                    }
                }

                if (document.Operations.Count == 0)
                {
                    throw new NoOperationError();
                }

                var operation = GetOperation(options.OperationName, document);
                metrics.SetOperationName(operation?.Name);

                if (operation == null)
                {
                    throw new InvalidOperationException($"Query does not contain operation '{options.OperationName}'.");
                }

                IValidationResult validationResult;
                using (metrics.Subject("document", "Validating document"))
                {
                    validationResult = await _documentValidator.ValidateAsync(
                        options.Query,
                        options.Schema,
                        document,
                        options.ValidationRules,
                        options.UserContext,
                        options.Inputs);
                }

                if (options.ComplexityConfiguration != null && validationResult.IsValid)
                {
                    using (metrics.Subject("document", "Analyzing complexity"))
                        _complexityAnalyzer.Validate(document, options.ComplexityConfiguration);
                }

                try
                {
                    context = BuildExecutionContext(
                        options.Schema,
                        options.Root,
                        document,
                        operation,
                        options.Inputs ?? Inputs.Empty,
                        options.UserContext,
                        options.CancellationToken,
                        metrics,
                        options.Listeners,
                        options.ThrowOnUnhandledException,
                        options.UnhandledExceptionDelegate,
                        options.MaxParallelExecutionCount,
                        options.RequestServices);
                }
                catch (InvalidVariableError)
                {
                    // error parsing variables
                    // attempt to run AfterValidationAsync with null for the 'ExecutionContext.Variables' property

                    context = BuildExecutionContext(
                        options.Schema,
                        options.Root,
                        document,
                        operation,
                        null,
                        options.UserContext,
                        options.CancellationToken,
                        metrics,
                        options.Listeners,
                        options.ThrowOnUnhandledException,
                        options.UnhandledExceptionDelegate,
                        options.MaxParallelExecutionCount,
                        options.RequestServices);

                    try
                    {
                        foreach (var listener in options.Listeners)
                        {
                            await listener.AfterValidationAsync(context, validationResult)
                            .ConfigureAwait(false);
                        }

                        // if there was a validation error, return that, and ignore the variable parsing error
                        if (!validationResult.IsValid)
                        {
                            return(new ExecutionResult
                            {
                                Errors = validationResult.Errors,
                                Perf = metrics.Finish()
                            });
                        }
                    }
                    catch
                    {
                        // if there was an error within AfterValidationAsync (such as a NullReferenceException
                        // due to ExecutionContext.Variables being null), skip this step and throw the variable parsing error
                    }

                    // if there was no validation errors returned, throw the variable parsing error
                    throw;
                }

                foreach (var listener in options.Listeners)
                {
                    await listener.AfterValidationAsync(context, validationResult)
                    .ConfigureAwait(false);
                }

                if (!validationResult.IsValid)
                {
                    return(new ExecutionResult
                    {
                        Errors = validationResult.Errors,
                        Perf = metrics.Finish()
                    });
                }

                if (context.Errors.Count > 0)
                {
                    return(new ExecutionResult
                    {
                        Errors = context.Errors,
                        Perf = metrics.Finish()
                    });
                }

                using (metrics.Subject("execution", "Executing operation"))
                {
                    if (context.Listeners != null)
                    {
                        foreach (var listener in context.Listeners)
                        {
                            await listener.BeforeExecutionAsync(context)
                            .ConfigureAwait(false);
                        }
                    }

                    IExecutionStrategy executionStrategy = SelectExecutionStrategy(context);

                    if (executionStrategy == null)
                    {
                        throw new InvalidOperationException("Invalid ExecutionStrategy!");
                    }

                    var task = executionStrategy.ExecuteAsync(context)
                               .ConfigureAwait(false);

                    if (context.Listeners != null)
                    {
                        foreach (var listener in context.Listeners)
                        {
                            await listener.BeforeExecutionAwaitedAsync(context)
                            .ConfigureAwait(false);
                        }
                    }

                    result = await task;

                    if (context.Listeners != null)
                    {
                        foreach (var listener in context.Listeners)
                        {
                            await listener.AfterExecutionAsync(context)
                            .ConfigureAwait(false);
                        }
                    }
                }

                if (context.Errors.Count > 0)
                {
                    result.Errors = context.Errors;
                }
            }
            catch (OperationCanceledException) when(options.CancellationToken.IsCancellationRequested)
            {
                throw;
            }
            catch (ExecutionError ex)
            {
                result = new ExecutionResult
                {
                    Errors = new ExecutionErrors
                    {
                        ex
                    }
                };
            }
            catch (Exception ex)
            {
                if (options.ThrowOnUnhandledException)
                {
                    throw;
                }

                UnhandledExceptionContext exceptionContext = null;
                if (options.UnhandledExceptionDelegate != null)
                {
                    exceptionContext = new UnhandledExceptionContext(context, null, ex);
                    options.UnhandledExceptionDelegate(exceptionContext);
                    ex = exceptionContext.Exception;
                }

                result = new ExecutionResult
                {
                    Errors = new ExecutionErrors
                    {
                        ex is ExecutionError executionError ? executionError : new UnhandledError(exceptionContext?.ErrorMessage ?? "Error executing document.", ex)
                    }
                };
            }
            finally
            {
                result ??= new ExecutionResult();
                result.Perf = metrics.Finish();
            }

            return(result);
        }
Example #32
0
 public MockDIDocumentExecuter(IServiceProvider serviceProvider, IExecutionStrategy executionStrategy) : base(serviceProvider, executionStrategy)
 {
 }
        public async Task <ExecutionResult> ExecuteAsync(ExecutionOptions options)
        {
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }
            if (options.Schema == null)
            {
                throw new InvalidOperationException("Cannot execute request if no schema is specified");
            }

            var metrics = new Metrics(options.EnableMetrics, options.MetricThreshold).Start(options.OperationName);

            options.Schema.NameConverter = options.NameConverter;
            options.Schema.Filter        = options.SchemaFilter;

            ExecutionResult  result  = null;
            ExecutionContext context = null;

            try
            {
                ValidateOptions(options);

                if (!options.Schema.Initialized)
                {
                    using (metrics.Subject("schema", "Initializing schema"))
                    {
                        options.FieldMiddleware.ApplyTo(options.Schema);
                        options.Schema.Initialize();
                    }
                }

                var document = options.Document;
                using (metrics.Subject("document", "Building document"))
                {
                    if (document == null)
                    {
                        document = _documentBuilder.Build(options.Query);
                    }
                }

                var operation = GetOperation(options.OperationName, document);
                metrics.SetOperationName(operation?.Name);

                if (operation == null)
                {
                    throw new ExecutionError("Unable to determine operation from query.");
                }

                IValidationResult validationResult;
                using (metrics.Subject("document", "Validating document"))
                {
                    validationResult = await _documentValidator.ValidateAsync(
                        options.Query,
                        options.Schema,
                        document,
                        options.ValidationRules,
                        options.UserContext,
                        options.Inputs);
                }

                if (options.ComplexityConfiguration != null && validationResult.IsValid)
                {
                    using (metrics.Subject("document", "Analyzing complexity"))
                        _complexityAnalyzer.Validate(document, options.ComplexityConfiguration);
                }

                context = BuildExecutionContext(
                    options.Schema,
                    options.Root,
                    document,
                    operation,
                    options.Inputs,
                    options.UserContext,
                    options.CancellationToken,
                    metrics,
                    options.Listeners,
                    options.ThrowOnUnhandledException,
                    options.UnhandledExceptionDelegate,
                    options.MaxParallelExecutionCount);

                foreach (var listener in options.Listeners)
                {
                    await listener.AfterValidationAsync(context, validationResult)
                    .ConfigureAwait(false);
                }

                if (!validationResult.IsValid)
                {
                    return(new ExecutionResult
                    {
                        Errors = validationResult.Errors,
                        ExposeExceptions = options.ExposeExceptions,
                        Perf = metrics.Finish()
                    });
                }

                if (context.Errors.Count > 0)
                {
                    return(new ExecutionResult
                    {
                        Errors = context.Errors,
                        ExposeExceptions = options.ExposeExceptions,
                        Perf = metrics.Finish()
                    });
                }

                using (metrics.Subject("execution", "Executing operation"))
                {
                    if (context.Listeners != null)
                    {
                        foreach (var listener in context.Listeners)
                        {
                            await listener.BeforeExecutionAsync(context)
                            .ConfigureAwait(false);
                        }
                    }

                    IExecutionStrategy executionStrategy = SelectExecutionStrategy(context);

                    if (executionStrategy == null)
                    {
                        throw new InvalidOperationException("Invalid ExecutionStrategy!");
                    }

                    var task = executionStrategy.ExecuteAsync(context)
                               .ConfigureAwait(false);

                    if (context.Listeners != null)
                    {
                        foreach (var listener in context.Listeners)
                        {
                            await listener.BeforeExecutionAwaitedAsync(context)
                            .ConfigureAwait(false);
                        }
                    }

                    result = await task;

                    if (context.Listeners != null)
                    {
                        foreach (var listener in context.Listeners)
                        {
                            await listener.AfterExecutionAsync(context)
                            .ConfigureAwait(false);
                        }
                    }
                }

                if (context.Errors.Count > 0)
                {
                    result.Errors = context.Errors;
                }
            }
            catch (Exception ex)
            {
                if (options.ThrowOnUnhandledException)
                {
                    throw;
                }

                if (options.UnhandledExceptionDelegate != null)
                {
                    var exceptionContext = new UnhandledExceptionContext(context, null, ex);
                    options.UnhandledExceptionDelegate(exceptionContext);
                    ex = exceptionContext.Exception;
                }

                result = new ExecutionResult
                {
                    Errors = new ExecutionErrors
                    {
                        new ExecutionError(ex.Message, ex)
                    }
                };
            }
            finally
            {
                result ??= new ExecutionResult();
                result.ExposeExceptions = options.ExposeExceptions;
                result.Perf             = metrics.Finish();
            }

            return(result);
        }
Example #34
0
 /// <summary>
 ///     Executes the specified asynchronous operation in a transaction. Allows to check whether
 ///     the transaction has been rolled back if an error occurs during commit.
 /// </summary>
 /// <param name="strategy"> The strategy that will be used for the execution. </param>
 /// <param name="isolationLevel"> The isolation level to use for the transaction. </param>
 /// <param name="operation">
 ///     A function that returns a started task.
 /// </param>
 /// <param name="verifySucceeded">
 ///     A delegate that tests whether the operation succeeded even though an exception was thrown when the
 ///     transaction was being committed.
 /// </param>
 /// <returns>
 ///     A task that will run to completion if the original task completes successfully (either the
 ///     first time or after retrying transient failures). If the task fails with a non-transient error or
 ///     the retry limit is reached, the returned task will become faulted and the exception must be observed.
 /// </returns>
 /// <exception cref="RetryLimitExceededException">
 ///     The operation has not succeeded after the configured number of retries.
 /// </exception>
 public static Task ExecuteInTransactionAsync(
     [NotNull] this IExecutionStrategy strategy,
     [NotNull] Func <Task> operation,
     [NotNull] Func <Task <bool> > verifySucceeded,
     IsolationLevel isolationLevel)
 => strategy.ExecuteInTransactionAsync <object>(null, (s, ct) => operation(), (s, ct) => verifySucceeded(), isolationLevel);
 /// <summary>
 ///     Executes the specified operation and returns the result.
 /// </summary>
 /// <param name="strategy">The strategy that will be used for the execution.</param>
 /// <param name="state">The state that will be passed to the operation.</param>
 /// <param name="operation">
 ///     A delegate representing an executable operation that returns the result of type <typeparamref name="TResult" />.
 /// </param>
 /// <typeparam name="TState">The type of the state.</typeparam>
 /// <typeparam name="TResult">The return type of <paramref name="operation" />.</typeparam>
 /// <returns>The result from the operation.</returns>
 public static TResult Execute <TState, TResult>(
     [NotNull] this IExecutionStrategy strategy,
     [CanBeNull] TState state,
     [NotNull] Func <TState, TResult> operation)
 => strategy.Execute(state, operation, verifySucceeded: null);