/// <summary> /// Adds an <see cref="ExactlyOnceMiddleware{T}"/> to the current pipeline. /// </summary> /// <param name="builder">The current <see cref="HandlerMiddlewareBuilder"/>.</param> /// <param name="lockKey">A unique key to identify this lock, e.g. the name of the handler.</param> /// <param name="lockDuration">The length of time to lock messages while handling them.</param> /// <typeparam name="TMessage">The type of the message that should be locked.</typeparam> /// <returns>The current <see cref="HandlerMiddlewareBuilder"/>.</returns> public static HandlerMiddlewareBuilder UseExactlyOnce <TMessage>( this HandlerMiddlewareBuilder builder, string lockKey, TimeSpan?lockDuration = null) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (string.IsNullOrEmpty(lockKey)) { throw new ArgumentException("Parameter cannot be null or empty.", nameof(lockKey)); } HandleMessageMiddleware CreateMiddleware() { var messageLock = builder.ServiceResolver.ResolveService <IMessageLockAsync>(); var logger = builder.ServiceResolver.ResolveService <ILogger <ExactlyOnceMiddleware <TMessage> > >(); return(new ExactlyOnceMiddleware <TMessage>(messageLock, lockDuration ?? TimeSpan.MaxValue, lockKey, logger)); } builder.Use(CreateMiddleware); return(builder); }
public static HandlerMiddlewareBuilder UseMessageContextAccessor(this HandlerMiddlewareBuilder builder) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } var contextAccessor = builder.ServiceResolver.ResolveService <IMessageContextAccessor>(); return(builder.Use(new MessageContextAccessorMiddleware(contextAccessor))); }
/// <summary> /// Adds an error handler to the pipeline that will call methods on the the <see cref="IMessageMonitor"/> /// registered in services. /// </summary> /// <param name="builder">The <see cref="HandlerMiddlewareBuilder"/> to add the middleware to.</param> /// <returns>The current <see cref="HandlerMiddlewareBuilder"/>.</returns> /// <exception cref="ArgumentNullException">When the <see cref="HandlerMiddlewareBuilder"/> is null.</exception> public static HandlerMiddlewareBuilder UseErrorHandler(this HandlerMiddlewareBuilder builder) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } IMessageMonitor monitor = builder.ServiceResolver.ResolveService <IMessageMonitor>(); return(builder.Use(new ErrorHandlerMiddleware(monitor))); }
/// <summary> /// Adds a <see cref="StopwatchMiddleware"/> to the current pipeline. /// </summary> /// <param name="builder">The current <see cref="HandlerMiddlewareBuilder"/>.</param> /// <param name="handlerType">The type of the handler that results should be reported against.</param> /// <returns>The current <see cref="HandlerMiddlewareBuilder"/>.</returns> /// <exception cref="ArgumentNullException"> /// <paramref name="builder"/> is <see langword="null"/>. /// </exception> public static HandlerMiddlewareBuilder UseStopwatch( this HandlerMiddlewareBuilder builder, Type handlerType) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } IMessageMonitor monitor = builder.ServiceResolver.ResolveService <IMessageMonitor>(); return(builder.Use(new StopwatchMiddleware(monitor, handlerType))); }
/// <summary> /// <para> /// Applies a set of default middlewares in order. Adding other middlewares before this will add them /// to the top of the stack, and are run first and last. /// Adding other middleware after this will add them to the bottom of the stack, just before the /// handler itself is invoked. /// </para> /// The middlewares this adds are, in order: /// <list type="bullet"> /// <item>MessageContextAccessorMiddleware</item> /// <item>BackoffMiddleware (only if an <see cref="IMessageBackoffStrategy"/> is available)</item> /// <item>ErrorHandlerMiddleware</item> /// <item>LoggingMiddleware</item> /// <item>StopwatchMiddleware</item> /// <item>SqsPostProcessorMiddleware</item> /// <item>HandlerInvocationMiddleware`1</item> /// </list> /// </summary> /// <param name="builder">The <see cref="HandlerMiddlewareBuilder"/> builder to add these defaults to.</param> /// <param name="handlerType">The type of the handler that will handle messages for this middleware pipeline. /// This is used when recording handler execution time with the StopwatchMiddleware.</param> /// <typeparam name="TMessage">The type of the message that this middleware pipeline handles.</typeparam> /// <returns>The current <see cref="HandlerMiddlewareBuilder"/>.</returns> public static HandlerMiddlewareBuilder UseDefaults <TMessage>( this HandlerMiddlewareBuilder builder, Type handlerType) where TMessage : Message { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (handlerType == null) { throw new ArgumentNullException(nameof(handlerType), "HandlerType is used here to"); } builder.UseMessageContextAccessor(); builder.UseErrorHandler(); builder.Use <LoggingMiddleware>(); builder.UseStopwatch(handlerType); builder.Use <SqsPostProcessorMiddleware>(); builder.UseHandler <TMessage>(); return(builder); }
/// <summary> /// Adds a <see cref="HandlerInvocationMiddleware{T}"/> to the current pipeline. /// </summary> /// <param name="builder">The current <see cref="HandlerMiddlewareBuilder"/>.</param> /// <param name="handler">A factory that creates <see cref="IHandlerAsync{T}"/> instances from /// a <see cref="HandlerResolutionContext"/>.</param> /// <typeparam name="TMessage">The type of the message that should be handled</typeparam> /// <returns>The current <see cref="HandlerMiddlewareBuilder"/>.</returns> /// <exception cref="ArgumentNullException"> /// <paramref name="builder"/> or <paramref name="handler"/> is <see langword="null"/>. /// </exception> public static HandlerMiddlewareBuilder UseHandler <TMessage>( this HandlerMiddlewareBuilder builder, Func <HandlerResolutionContext, IHandlerAsync <TMessage> > handler) where TMessage : Message { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (handler == null) { throw new ArgumentNullException(nameof(handler)); } return(builder.Use(new HandlerInvocationMiddleware <TMessage>(handler))); }
/// <summary> /// If an <see cref="IMessageBackoffStrategy"/> has been registered in services, then this will create /// a <see cref="BackoffMiddleware"/> and add it to the pipeline. /// </summary> /// <param name="builder">The <see cref="HandlerMiddlewareBuilder"/> to add the middleware to.</param> /// <param name="backoffStrategy">The <see cref="IMessageBackoffStrategy"/> to use to determine message visibility timeouts.</param> /// <returns>The current <see cref="HandlerMiddlewareBuilder"/>.</returns> /// <exception cref="ArgumentNullException">When the <see cref="HandlerMiddlewareBuilder"/> is null.</exception> public static HandlerMiddlewareBuilder UseBackoff(this HandlerMiddlewareBuilder builder, IMessageBackoffStrategy backoffStrategy) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (backoffStrategy == null) { throw new ArgumentNullException(nameof(backoffStrategy)); } var loggerFactory = builder.ServiceResolver.ResolveService <ILoggerFactory>(); var monitor = builder.ServiceResolver.ResolveService <IMessageMonitor>(); return(builder.Use(new BackoffMiddleware(backoffStrategy, loggerFactory, monitor))); }