Пример #1
0
 /// <summary>
 /// If a request cannot be completed by <see cref="HandleAsync"/>, implementing the <see cref="FallbackAsync"/> method provides an alternate code path that can be used
 /// This allows for graceful  degradation. Using the <see cref="FallbackPolicyAttribute"/> handler you can configure a policy to catch either all <see cref="Exception"/>'s or
 /// just <see cref="BrokenCircuitException"/> that occur later in the pipeline, and then call the <see cref="FallbackAsync"/> path.
 /// Note that the <see cref="FallbackPolicyAttribute"/> target handler might be 'beginning of chain' and need to pass through to actual handler that is end of chain.
 /// Because of this we need to call Fallback on the chain. Later step handlers don't know the context of failure so they cannot know if any operations they had,
 /// that could fail (such as DB access) were the cause of the failure chain being hit.
 /// Steps that don't know how to handle should pass through.
 /// Useful alternatives for Fallback are to try via the cache.
 /// Note that a Fallback handler implementation should not catch exceptions in the <see cref="FallbackAsync"/> chain to avoid an infinite loop.
 /// Call <see cref="Successor"/>.<see cref="HandleAsync"/> if having provided a Fallback you want the chain to return to the 'happy' path. Excerise caution here though
 /// as you do not know who generated the exception that caused the fallback chain.
 /// For this reason, the <see cref="FallbackPolicyHandler"/> puts the exception in the request context.
 /// When the <see cref="FallbackPolicyAttribute"/> is set on the <see cref="HandleAsync"/> method of a derived class
 /// The <see cref="FallbackPolicyHandler{TRequest}"/> will catch either all failures (backstop) or <see cref="BrokenCircuitException"/> depending on configuration
 /// and call the <see cref="RequestHandler{TRequest}"/>'s <see cref="FallbackAsync"/> method
 /// </summary>
 /// <param name="command">The command.</param>
 /// <param name="ct">A cancellation token (optional). Can be used to signal that the pipeline should end by the caller</param>
 /// <returns>Awaitable <see cref="Task{TRequest}"/>.</returns>
 public virtual async Task <TRequest> FallbackAsync(TRequest command, CancellationToken?ct = null)
 {
     if (_successor != null)
     {
         logger.DebugFormat("Falling back from {0} to {1}", Name, _successor.Name);
         return(await _successor.FallbackAsync(command, ct).ConfigureAwait(ContinueOnCapturedContext));
     }
     return(command);
 }
Пример #2
0
        /// <summary>
        /// If a request cannot be completed by <see cref="HandleAsync"/>, implementing the <see cref="FallbackAsync"/> method provides an alternate code path that can be used
        /// This allows for graceful  degradation. Using the <see cref="FallbackPolicyAttribute"/> handler you can configure a policy to catch either all <see cref="Exception"/>'s or
        /// just <see cref="BrokenCircuitException"/> that occur later in the pipeline, and then call the <see cref="FallbackAsync"/> path.
        /// Note that the <see cref="FallbackPolicyAttribute"/> target handler might be 'beginning of chain' and need to pass through to actual handler that is end of chain.
        /// Because of this we need to call Fallback on the chain. Later step handlers don't know the context of failure so they cannot know if any operations they had,
        /// that could fail (such as DB access) were the cause of the failure chain being hit.
        /// Steps that don't know how to handle should pass through.
        /// Useful alternatives for Fallback are to try via the cache.
        /// Note that a Fallback handler implementation should not catch exceptions in the <see cref="FallbackAsync"/> chain to avoid an infinite loop.
        /// Call <see cref="Successor"/>.<see cref="HandleAsync"/> if having provided a Fallback you want the chain to return to the 'happy' path. Excerise caution here though
        /// as you do not know who generated the exception that caused the fallback chain.
        /// For this reason, the <see cref="FallbackPolicyHandler"/> puts the exception in the request context.
        /// When the <see cref="FallbackPolicyAttribute"/> is set on the <see cref="HandleAsync"/> method of a derived class
        /// The <see cref="FallbackPolicyHandler{TRequest}"/> will catch either all failures (backstop) or <see cref="BrokenCircuitException"/> depending on configuration
        /// and call the <see cref="RequestHandler{TRequest}"/>'s <see cref="FallbackAsync"/> method
        /// </summary>
        /// <param name="command">The command.</param>
        /// <param name="cancellationToken">A cancellation token (optional). Can be used to signal that the pipeline should end by the caller</param>
        /// <returns>Awaitable <see cref="Task{TRequest}"/>.</returns>
        public virtual async Task <TRequest> FallbackAsync(TRequest command, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (_successor != null)
            {
                s_logger.LogDebug("Falling back from {HandlerName} to {NextHandler}", Name, _successor.Name);
                return(await _successor.FallbackAsync(command, cancellationToken).ConfigureAwait(ContinueOnCapturedContext));
            }

            return(command);
        }