11using Azure . Messaging . ServiceBus ;
22using AzureServiceBusFlow . Abstractions ;
33using AzureServiceBusFlow . Hosts ;
4+ using AzureServiceBusFlow . Middlewares ;
45using AzureServiceBusFlow . Models ;
56using Microsoft . Azure . ServiceBus . Management ;
67using Microsoft . Extensions . DependencyInjection ;
@@ -19,6 +20,19 @@ public class ServiceBusConsumerConfigurationBuilder(AzureServiceBusConfiguration
1920 private string ? _queueName ;
2021 private string ? _topicName ;
2122 private string ? _subscriptionName ;
23+ private readonly List < Type > _middlewares = [ ] ;
24+ private readonly string _consumerMiddlewareKey = Guid . NewGuid ( ) . ToString ( ) ;
25+
26+ public ServiceBusConsumerConfigurationBuilder UseMiddleware < TMiddleware > ( )
27+ where TMiddleware : IConsumerMiddleware
28+ {
29+ if ( ! _middlewares . Contains ( typeof ( TMiddleware ) ) )
30+ {
31+ _middlewares . Add ( typeof ( TMiddleware ) ) ;
32+ }
33+
34+ return this ;
35+ }
2236
2337 public ServiceBusConsumerConfigurationBuilder FromQueue ( string queueName )
2438 {
@@ -76,15 +90,28 @@ public void Build()
7690 throw new InvalidOperationException ( "Missing queue or topic configuration!" ) ;
7791 }
7892
93+ foreach ( var middlewareType in from middlewareType in _middlewares
94+ where ! _services . Any ( s =>
95+ s . ServiceType == typeof ( IConsumerMiddleware ) &&
96+ s . ImplementationType == middlewareType )
97+ select middlewareType )
98+ {
99+ _services . AddKeyedSingleton ( typeof ( IConsumerMiddleware ) , _consumerMiddlewareKey , middlewareType ) ;
100+ }
101+
79102 _services . AddSingleton < IHostedService > ( sp =>
80103 {
81104 var logger = sp . GetRequiredService < ILogger < ServiceBusConsumerHostedService > > ( ) ;
105+ var localConsumerMiddlewares = sp . GetKeyedServices < IConsumerMiddleware > ( _consumerMiddlewareKey ) ?? [ ] ;
106+ var globalConsumerMiddlewares = sp . GetServices < IConsumerMiddleware > ( ) ?? [ ] ;
107+
108+ var consumerMiddlewares = globalConsumerMiddlewares . Union ( localConsumerMiddlewares ) ;
82109
83110 if ( ! string . IsNullOrWhiteSpace ( _queueName ) )
84111 {
85112 return new ServiceBusConsumerHostedService (
86113 ( rawMessage , rootProvider , cancellationToken ) =>
87- MessageConsumingHandler ( rawMessage , rootProvider , logger , cancellationToken ) ,
114+ MessageConsumingHandler ( rawMessage , rootProvider , consumerMiddlewares , logger , cancellationToken ) ,
88115 sp ,
89116 logger ,
90117 _azureServiceBusConfiguration ,
@@ -93,7 +120,7 @@ public void Build()
93120
94121 return new ServiceBusConsumerHostedService (
95122 ( rawMessage , rootProvider , cancellationToken ) =>
96- MessageConsumingHandler ( rawMessage , rootProvider , logger , cancellationToken ) ,
123+ MessageConsumingHandler ( rawMessage , rootProvider , consumerMiddlewares , logger , cancellationToken ) ,
97124 sp ,
98125 logger ,
99126 _azureServiceBusConfiguration ,
@@ -102,7 +129,34 @@ public void Build()
102129 } ) ;
103130 }
104131
105- private async Task MessageConsumingHandler ( ServiceBusReceivedMessage rawMessage , IServiceProvider rootProvider , ILogger < ServiceBusConsumerHostedService > logger , CancellationToken cancellationToken )
132+ private async Task MessageConsumingHandler ( ServiceBusReceivedMessage rawMessage , IServiceProvider rootProvider , IEnumerable < IConsumerMiddleware > middlewares , ILogger < ServiceBusConsumerHostedService > logger , CancellationToken cancellationToken )
133+ {
134+ Func < Task > finalStep = async ( ) =>
135+ {
136+ await ProcessHandlersAsync ( rawMessage , rootProvider , logger , cancellationToken ) ;
137+ } ;
138+
139+ if ( middlewares != null && middlewares . Any ( ) )
140+ {
141+ Func < Task > next = finalStep ;
142+
143+ foreach ( var middleware in middlewares . Reverse ( ) )
144+ {
145+ var current = middleware ;
146+ var prevNext = next ;
147+
148+ next = ( ) => current . InvokeAsync ( rawMessage , prevNext , cancellationToken ) ;
149+ }
150+
151+ await next ( ) ;
152+ }
153+ else
154+ {
155+ await finalStep ( ) ;
156+ }
157+ }
158+
159+ private async Task ProcessHandlersAsync ( ServiceBusReceivedMessage rawMessage , IServiceProvider rootProvider , ILogger < ServiceBusConsumerHostedService > logger , CancellationToken cancellationToken )
106160 {
107161 if ( ! rawMessage . ApplicationProperties . TryGetValue ( "MessageType" , out var messageTypeNameObj ) )
108162 {
@@ -169,9 +223,9 @@ private async Task MessageConsumingHandler(ServiceBusReceivedMessage rawMessage,
169223 var elapsed = DateTime . UtcNow - startTime ;
170224
171225 logger . LogInformation (
172- "Message {MessageType} with RoutingKey {RoutingKey } consumed and handled by {HandlerName} at {StartTime} in {ElapsedMilliseconds} ms" ,
226+ "Message {MessageType} with CorrelationId {CorrelationId } consumed and handled by {HandlerName} at {StartTime} in {ElapsedMilliseconds} ms" ,
173227 messageTypeName ,
174- rawMessage . Subject ,
228+ rawMessage . CorrelationId ,
175229 handlerType . Name ,
176230 startTime . ToString ( "o" ) ,
177231 elapsed . TotalMilliseconds
0 commit comments