Example #1
0
        internal static TResult Implementation <TResult>(
            Func <CancellationToken, TResult> action,
            Context context,
            Action <Context> onBulkheadRejected,
            SemaphoreSlim maxParallelizationSemaphore,
            SemaphoreSlim maxQueuedActionsSemaphore,
            CancellationToken cancellationToken)
        {
            if (!maxQueuedActionsSemaphore.Wait(TimeSpan.Zero, cancellationToken))
            {
                onBulkheadRejected(context);
                throw new BulkheadRejectedException();
            }

            try
            {
                maxParallelizationSemaphore.Wait(cancellationToken);
                try
                {
                    return(action(cancellationToken));
                }
                finally
                {
                    maxParallelizationSemaphore.Release();
                }
            }
            finally
            {
                maxQueuedActionsSemaphore.Release();
            }
        }
Example #2
0
        internal static async Task <TResult> ImplementationAsync <TResult>(
            Func <CancellationToken, Task <TResult> > action,
            Context context,
            Func <Context, Task> onBulkheadRejectedAsync,
            SemaphoreSlim maxParallelizationSemaphore,
            SemaphoreSlim maxQueuedActionsSemaphore,
            CancellationToken cancellationToken,
            bool continueOnCapturedContext)
        {
            if (!await maxQueuedActionsSemaphore.WaitAsync(TimeSpan.Zero, cancellationToken).ConfigureAwait(continueOnCapturedContext))
            {
                await onBulkheadRejectedAsync(context).ConfigureAwait(continueOnCapturedContext);

                throw new BulkheadRejectedException();
            }
            try
            {
                await maxParallelizationSemaphore.WaitAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext);

                try
                {
                    return(await action(cancellationToken).ConfigureAwait(continueOnCapturedContext));
                }
                finally
                {
                    maxParallelizationSemaphore.Release();
                }
            }
            finally
            {
                maxQueuedActionsSemaphore.Release();
            }
        }
Example #3
0
 internal BulkheadPolicy(Func <Func <Context, CancellationToken, Task>, Context, CancellationToken, bool, Task> asyncExceptionPolicy,
                         int maxParallelization,
                         int maxQueueingActions,
                         SemaphoreSlim maxParallelizationSemaphore,
                         SemaphoreSlim maxQueuedActionsSemaphore)
     : base(asyncExceptionPolicy, PredicateHelper.EmptyExceptionPredicates)
 {
     _maxParallelization          = maxParallelization;
     _maxQueueingActions          = maxQueueingActions;
     _maxParallelizationSemaphore = maxParallelizationSemaphore;
     _maxQueuedActionsSemaphore   = maxQueuedActionsSemaphore;
 }
Example #4
0
 internal BulkheadPolicy(Func<Func<CancellationToken, Task>, Context, CancellationToken, bool, Task> asyncExceptionPolicy,
     int maxParallelization,
     int maxQueueingActions,
     SemaphoreSlim maxParallelizationSemaphore,
     SemaphoreSlim maxQueuedActionsSemaphore)
    : base(asyncExceptionPolicy, PredicateHelper.EmptyExceptionPredicates)
 {
     _maxParallelization = maxParallelization;
     _maxQueueingActions = maxQueueingActions;
     _maxParallelizationSemaphore = maxParallelizationSemaphore;
     _maxQueuedActionsSemaphore = maxQueuedActionsSemaphore;
 }
Example #5
0
 internal BulkheadPolicy(
     Action <Action <CancellationToken>, Context, CancellationToken> exceptionPolicy,
     int maxParallelization,
     int maxQueueingActions,
     SemaphoreSlim maxParallelizationSemaphore,
     SemaphoreSlim maxQueuedActionsSemaphore
     ) : base(exceptionPolicy, PredicateHelper.EmptyExceptionPredicates)
 {
     _maxParallelization          = maxParallelization;
     _maxQueueingActions          = maxQueueingActions;
     _maxParallelizationSemaphore = maxParallelizationSemaphore;
     _maxQueuedActionsSemaphore   = maxQueuedActionsSemaphore;
 }
Example #6
0
 internal BulkheadPolicy(
     Action<Action<CancellationToken>, Context, CancellationToken> exceptionPolicy, 
     int maxParallelization,
     int maxQueueingActions,
     SemaphoreSlim maxParallelizationSemaphore, 
     SemaphoreSlim maxQueuedActionsSemaphore
     ) : base(exceptionPolicy, PredicateHelper.EmptyExceptionPredicates)
 {
     _maxParallelization = maxParallelization;
     _maxQueueingActions = maxQueueingActions;
     _maxParallelizationSemaphore = maxParallelizationSemaphore;
     _maxQueuedActionsSemaphore = maxQueuedActionsSemaphore;
 }
Example #7
0
        /// <summary>
        /// Builds a bulkhead isolation <see cref="Policy" />, which limits the maximum concurrency of actions executed through the policy.  Imposing a maximum concurrency limits the potential of governed actions, when faulting, to bring down the system.
        /// <para>When an execution would cause the number of actions executing concurrently through the policy to exceed <paramref name="maxParallelization" />, the policy allows a further <paramref name="maxQueuingActions" /> executions to queue, waiting for a concurrent execution slot.  When an execution would cause the number of queuing actions to exceed <paramref name="maxQueuingActions" />, a <see cref="BulkheadRejectedException" /> is thrown.</para>
        /// </summary>
        /// <param name="maxParallelization">The maximum number of concurrent actions that may be executing through the policy.</param>
        /// <param name="maxQueuingActions">The maximum number of actions that may be queuing, waiting for an execution slot.</param>
        /// <param name="onBulkheadRejectedAsync">An action to call asynchronously, if the bulkhead rejects execution due to oversubscription.</param>
        /// <returns>The policy instance.</returns>
        /// <exception cref="System.ArgumentOutOfRangeException">maxParallelization;Value must be greater than zero.</exception>
        /// <exception cref="System.ArgumentOutOfRangeException">maxQueuingActions;Value must be greater than or equal to zero.</exception>
        /// <exception cref="System.ArgumentNullException">onBulkheadRejectedAsync</exception>
        public static BulkheadPolicy BulkheadAsync(int maxParallelization, int maxQueuingActions, Func <Context, Task> onBulkheadRejectedAsync)
        {
            if (maxParallelization <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(maxParallelization), "Value must be greater than zero.");
            }
            if (maxQueuingActions < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(maxQueuingActions), "Value must be greater than or equal to zero.");
            }
            if (onBulkheadRejectedAsync == null)
            {
                throw new ArgumentNullException(nameof(onBulkheadRejectedAsync));
            }

            SemaphoreSlim maxParallelizationSemaphore = SemaphoreSlimFactory.CreateSemaphoreSlim(maxParallelization);

            var maxQueuingCompounded = maxQueuingActions <= int.MaxValue - maxParallelization
                ? maxQueuingActions + maxParallelization
                : int.MaxValue;
            SemaphoreSlim maxQueuedActionsSemaphore = SemaphoreSlimFactory.CreateSemaphoreSlim(maxQueuingCompounded);

            return(new BulkheadPolicy((action, context, cancellationToken, continueOnCapturedContext) =>
                                      BulkheadEngine.ImplementationAsync(
                                          async(ctx, ct) => { await action(ctx, ct).ConfigureAwait(continueOnCapturedContext); return EmptyStruct.Instance; },
                                          context,
                                          onBulkheadRejectedAsync,
                                          maxParallelizationSemaphore,
                                          maxQueuedActionsSemaphore,
                                          cancellationToken,
                                          continueOnCapturedContext),
                                      maxParallelization,
                                      maxQueuingActions,
                                      maxParallelizationSemaphore,
                                      maxQueuedActionsSemaphore
                                      ));
        }
Example #8
0
        /// <summary>
        /// Builds a bulkhead isolation <see cref="Policy" />, which limits the maximum concurrency of actions executed through the policy.  Imposing a maximum concurrency limits the potential of governed actions, when faulting, to bring down the system.
        /// <para>When an execution would cause the number of actions executing concurrently through the policy to exceed <paramref name="maxParallelization" />, the policy allows a further <paramref name="maxQueuingActions" /> executions to queue, waiting for a concurrent execution slot.  When an execution would cause the number of queuing actions to exceed <paramref name="maxQueuingActions" />, a <see cref="BulkheadRejectedException" /> is thrown.</para>
        /// </summary>
        /// <param name="maxParallelization">The maximum number of concurrent actions that may be executing through the policy.</param>
        /// <param name="maxQueuingActions">The maxmimum number of actions that may be queuing, waiting for an execution slot.</param>
        /// <param name="onBulkheadRejected">An action to call, if the bulkhead rejects execution due to oversubscription.</param>
        /// <returns>The policy instance.</returns>
        /// <exception cref="System.ArgumentOutOfRangeException">maxParallelization;Value must be greater than zero.</exception>
        /// <exception cref="System.ArgumentOutOfRangeException">maxParallelization;Value must be greater than zero.</exception>
        /// <exception cref="System.ArgumentNullException">onBulkheadRejected</exception>
        public static BulkheadPolicy Bulkhead(int maxParallelization, int maxQueuingActions, Action <Context> onBulkheadRejected)
        {
            if (maxParallelization <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(maxParallelization), "Value must be greater than zero.");
            }
            if (maxQueuingActions < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(maxQueuingActions), "Value must be greater than or equal to zero.");
            }
            if (onBulkheadRejected == null)
            {
                throw new ArgumentNullException(nameof(onBulkheadRejected));
            }

            SemaphoreSlim maxParallelizationSemaphore = SemaphoreSlimFactory.CreateSemaphoreSlim(maxParallelization);

            var maxQueuingCompounded = maxQueuingActions <= int.MaxValue - maxParallelization
                ? maxQueuingActions + maxParallelization
                : int.MaxValue;
            SemaphoreSlim maxQueuedActionsSemaphore = SemaphoreSlimFactory.CreateSemaphoreSlim(maxQueuingCompounded);

            return(new BulkheadPolicy(
                       (action, context, cancellationToken) => BulkheadEngine.Implementation(
                           ct => { action(ct); return EmptyStruct.Instance; },
                           context,
                           onBulkheadRejected,
                           maxParallelizationSemaphore,
                           maxQueuedActionsSemaphore,
                           cancellationToken
                           ),
                       maxParallelization,
                       maxQueuingActions,
                       maxParallelizationSemaphore,
                       maxQueuedActionsSemaphore
                       ));
        }