/// <summary> /// Profile and time measure the specified <paramref name="action"/> delegate. /// </summary> /// <typeparam name="T1">The type of the first parameter of the <paramref name="action" /> delegate.</typeparam> /// <typeparam name="T2">The type of the second parameter of the <paramref name="action" /> delegate.</typeparam> /// <typeparam name="T3">The type of the third parameter of the <paramref name="action" /> delegate.</typeparam> /// <typeparam name="T4">The type of the fourth parameter of the <paramref name="action" /> delegate.</typeparam> /// <param name="action">The delegate to time measure.</param> /// <param name="arg1">The first parameter of the <paramref name="action" /> delegate.</param> /// <param name="arg2">The second parameter of the <paramref name="action" /> delegate.</param> /// <param name="arg3">The third parameter of the <paramref name="action" /> delegate.</param> /// <param name="arg4">The fourth parameter of the <paramref name="action" /> delegate.</param> /// <param name="setup">The <see cref="TimeMeasureOptions"/> which need to be configured.</param> /// <returns>A <see cref="TimeMeasureProfiler"/> with the result of the time measuring.</returns> public static Task <TimeMeasureProfiler> WithActionAsync <T1, T2, T3, T4>(Func <T1, T2, T3, T4, Task> action, T1 arg1, T2 arg2, T3 arg3, T4 arg4, Action <TimeMeasureOptions> setup = null) { Validator.ThrowIfNull(action, nameof(action)); var factory = TaskActionFactory.Create(action, arg1, arg2, arg3, arg4); return(WithActionAsyncCore(factory, setup)); }
/// <summary> /// Profile and time measure the specified <paramref name="action"/> delegate. /// </summary> /// <typeparam name="T">The type of the parameter of the <paramref name="action" /> delegate.</typeparam> /// <param name="action">The delegate to time measure.</param> /// <param name="arg">The parameter of the <paramref name="action" /> delegate.</param> /// <param name="setup">The <see cref="TimeMeasureOptions"/> which need to be configured.</param> /// <returns>A <see cref="TimeMeasureProfiler"/> with the result of the time measuring.</returns> public static Task <TimeMeasureProfiler> WithActionAsync <T>(Func <T, Task> action, T arg, Action <TimeMeasureOptions> setup = null) { Validator.ThrowIfNull(action, nameof(action)); var factory = TaskActionFactory.Create(action, arg); return(WithActionAsyncCore(factory, setup)); }
/// <summary> /// Profile and time measure the specified <paramref name="action"/> delegate. /// </summary> /// <typeparam name="T1">The type of the first parameter of the <paramref name="action" /> delegate.</typeparam> /// <typeparam name="T2">The type of the second parameter of the <paramref name="action" /> delegate.</typeparam> /// <typeparam name="T3">The type of the third parameter of the <paramref name="action" /> delegate.</typeparam> /// <typeparam name="T4">The type of the fourth parameter of the <paramref name="action" /> delegate.</typeparam> /// <typeparam name="T5">The type of the fifth parameter of the <paramref name="action" /> delegate.</typeparam> /// <typeparam name="T6">The type of the sixth parameter of the <paramref name="action" /> delegate.</typeparam> /// <typeparam name="T7">The type of the seventh parameter of the <paramref name="action" /> delegate.</typeparam> /// <typeparam name="T8">The type of the eighth parameter of the <paramref name="action" /> delegate.</typeparam> /// <typeparam name="T9">The type of the ninth parameter of the <paramref name="action" /> delegate.</typeparam> /// <typeparam name="T10">The type of the tenth parameter of the <paramref name="action" /> delegate.</typeparam> /// <param name="action">The delegate to time measure.</param> /// <param name="arg1">The first parameter of the <paramref name="action" /> delegate.</param> /// <param name="arg2">The second parameter of the <paramref name="action" /> delegate.</param> /// <param name="arg3">The third parameter of the <paramref name="action" /> delegate.</param> /// <param name="arg4">The fourth parameter of the <paramref name="action" /> delegate.</param> /// <param name="arg5">The fifth parameter of the <paramref name="action" /> delegate.</param> /// <param name="arg6">The sixth parameter of the <paramref name="action" /> delegate.</param> /// <param name="arg7">The seventh parameter of the <paramref name="action" /> delegate.</param> /// <param name="arg8">The eighth parameter of the <paramref name="action" /> delegate.</param> /// <param name="arg9">The ninth parameter of the <paramref name="action" /> delegate .</param> /// <param name="arg10">The tenth parameter of the <paramref name="action" /> delegate.</param> /// <param name="setup">The <see cref="TimeMeasureOptions"/> which need to be configured.</param> /// <returns>A <see cref="TimeMeasureProfiler"/> with the result of the time measuring.</returns> public static Task <TimeMeasureProfiler> WithActionAsync <T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(Func <T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, Task> action, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, Action <TimeMeasureOptions> setup = null) { Validator.ThrowIfNull(action, nameof(action)); var factory = TaskActionFactory.Create(action, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); return(WithActionAsyncCore(factory, setup)); }
public Task(string taskName, Action <ITask> taskPreExecutor, TaskActionFactory taskActionFactory) { Name = taskName; Dependencies = new string[] { }; _taskActionFactory = taskActionFactory; if (taskPreExecutor != null) { _actions.Add(() => taskPreExecutor(this)); } }
private static async Task <TimeMeasureProfiler> WithActionAsyncCore <TTuple>(TaskActionFactory <TTuple> factory, Action <TimeMeasureOptions> setup) where TTuple : Template { var options = setup.ConfigureOptions(); var descriptor = options.MethodDescriptor?.Invoke() ?? new MethodDescriptor(factory.DelegateInfo); var profiler = new TimeMeasureProfiler() { Member = descriptor.ToString(), Data = descriptor.MergeParameters(options.RuntimeParameters ?? factory.GenericArguments.ToArray()) }; await PerformTimeMeasuringAsync(profiler, options, async p => await factory.ExecuteMethodAsync().ContinueWithSuppressedContext()).ContinueWithSuppressedContext(); return(profiler); }
private static async Task WithActionAsyncCore <TTuple>(TaskActionFactory <TTuple> factory, Action <TransientOperationOptions> setup = null) where TTuple : Template { var options = setup.ConfigureOptions(); if (!options.EnableRecovery) { await factory.ExecuteMethodAsync().ContinueWithSuppressedContext(); return; } DateTime timestamp = DateTime.UtcNow; TimeSpan latency = TimeSpan.Zero; TimeSpan totalWaitTime = TimeSpan.Zero; TimeSpan lastWaitTime = TimeSpan.Zero; bool isTransientFault = false; bool throwExceptions; List <Exception> aggregatedExceptions = new List <Exception>(); for (int attempts = 0; ;) { TimeSpan waitTime = options.RetryStrategy(attempts); try { if (latency > options.MaximumAllowedLatency) { throw new LatencyException(string.Format(CultureInfo.InvariantCulture, "The latency of the operation exceeded the allowed maximum value of {0} seconds. Actual latency was: {1} seconds.", options.MaximumAllowedLatency.TotalSeconds, latency.TotalSeconds)); } await factory.ExecuteMethodAsync().ContinueWithSuppressedContext(); return; } catch (Exception ex) { try { lock (aggregatedExceptions) { aggregatedExceptions.Insert(0, ex); } isTransientFault = options.DetectionStrategy(ex); if (attempts >= options.RetryAttempts) { throw; } if (!isTransientFault) { throw; } lastWaitTime = waitTime; totalWaitTime = totalWaitTime.Add(waitTime); attempts++; await Task.Delay(waitTime).ContinueWithSuppressedContext(); latency = DateTime.UtcNow.Subtract(timestamp).Subtract(totalWaitTime); } catch (Exception) { throwExceptions = true; if (isTransientFault) { var evidence = new TransientFaultEvidence(attempts, lastWaitTime, totalWaitTime, latency, new MethodDescriptor(factory.DelegateInfo).ToString()); aggregatedExceptions.InsertTransientFaultException(evidence); FaultCallback?.Invoke(evidence); } break; } } } if (throwExceptions) { throw new AggregateException(aggregatedExceptions); } }
/// <summary> /// Repetitively executes the specified <paramref name="faultSensitiveMethod"/> until the operation is successful, the amount of retry attempts has been reached, or a failed operation is not considered related to transient fault condition. /// </summary> /// <typeparam name="T1">The type of the first parameter of the delegate <paramref name="faultSensitiveMethod"/>.</typeparam> /// <typeparam name="T2">The type of the second parameter of the delegate <paramref name="faultSensitiveMethod"/>.</typeparam> /// <typeparam name="T3">The type of the third parameter of the delegate <paramref name="faultSensitiveMethod"/>.</typeparam> /// <typeparam name="T4">The type of the fourth parameter of the delegate <paramref name="faultSensitiveMethod"/>.</typeparam> /// <typeparam name="T5">The type of the fifth parameter of the delegate <paramref name="faultSensitiveMethod"/>.</typeparam> /// <param name="faultSensitiveMethod">The fault sensitive <see cref="Task"/> based function delegate that is invoked until an operation is successful, the amount of retry attempts has been reached, or a failed operation is not considered related to transient fault condition.</param> /// <param name="arg1">The first parameter of the delegate <paramref name="faultSensitiveMethod"/>.</param> /// <param name="arg2">The second parameter of the delegate <paramref name="faultSensitiveMethod"/>.</param> /// <param name="arg3">The third parameter of the delegate <paramref name="faultSensitiveMethod"/>.</param> /// <param name="arg4">The fourth parameter of the delegate <paramref name="faultSensitiveMethod"/>.</param> /// <param name="arg5">The fifth parameter of the delegate <paramref name="faultSensitiveMethod"/>.</param> /// <param name="setup">The <see cref="TransientOperationOptions"/> which need to be configured.</param> public static Task WithActionAsync <T1, T2, T3, T4, T5>(Func <T1, T2, T3, T4, T5, Task> faultSensitiveMethod, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, Action <TransientOperationOptions> setup = null) { var factory = TaskActionFactory.Create(faultSensitiveMethod, arg1, arg2, arg3, arg4, arg5); return(WithActionAsyncCore(factory, setup)); }
/// <summary> /// Repetitively executes the specified <paramref name="faultSensitiveMethod"/> until the operation is successful, the amount of retry attempts has been reached, or a failed operation is not considered related to transient fault condition. /// </summary> /// <typeparam name="T">The type of the parameter of the delegate <paramref name="faultSensitiveMethod"/>.</typeparam> /// <param name="faultSensitiveMethod">The fault sensitive <see cref="Task"/> based function delegate that is invoked until an operation is successful, the amount of retry attempts has been reached, or a failed operation is not considered related to transient fault condition.</param> /// <param name="arg">The parameter of the delegate <paramref name="faultSensitiveMethod"/>.</param> /// <param name="setup">The <see cref="TransientOperationOptions"/> which need to be configured.</param> public static Task WithActionAsync <T>(Func <T, Task> faultSensitiveMethod, T arg, Action <TransientOperationOptions> setup = null) { var factory = TaskActionFactory.Create(faultSensitiveMethod, arg); return(WithActionAsyncCore(factory, setup)); }