2
2
using System . Collections . Generic ;
3
3
using System . Collections . ObjectModel ;
4
4
using System . Linq ;
5
+ using System . Text ;
5
6
using System . Text . Json ;
6
7
using System . Text . Json . Serialization ;
7
8
using System . Threading ;
@@ -107,34 +108,27 @@ protected async Task<MessageProcessingResult> RouteMessageThroughRegisteredHandl
107
108
return NoHandlersRegistered ( messageContext . MessageId ) ;
108
109
}
109
110
110
- try
111
+ int skippedHandlers = 0 ;
112
+ bool hasGoneThroughMessageHandler = false ;
113
+
114
+ foreach ( var handler in handlers )
111
115
{
112
- int skippedHandlers = 0 ;
113
- bool hasGoneThroughMessageHandler = false ;
116
+ MessageProcessingResult result = await ProcessMessageHandlerAsync ( handler , messageBody , messageContext , correlationInfo , cancellation ) ;
117
+ hasGoneThroughMessageHandler = result . IsSuccessful || result . Error is MessageProcessingError . ProcessingInterrupted ;
114
118
115
- foreach ( var handler in handlers )
119
+ if ( result . IsSuccessful )
116
120
{
117
- MessageProcessingResult result = await ProcessMessageHandlerAsync ( handler , messageBody , messageContext , correlationInfo , cancellation ) ;
118
- hasGoneThroughMessageHandler = result . IsSuccessful || result . Error is MessageProcessingError . ProcessingInterrupted ;
119
-
120
- if ( result . IsSuccessful )
121
- {
122
- Logger . LogMessageProcessedSummary ( messageContext . MessageId , handler . MessageHandlerType , skippedHandlers ) ;
123
- return result ;
124
- }
125
-
126
- skippedHandlers ++ ;
121
+ Logger . LogMessageProcessedSummary ( messageContext . MessageId , handler . MessageHandlerType , skippedHandlers ) ;
122
+ return result ;
127
123
}
128
124
129
- return hasGoneThroughMessageHandler
130
- ? MatchedHandlerFailed ( messageContext . MessageId )
131
- : NoMatchedHandler ( messageContext . MessageId ) ;
132
- }
133
- catch ( Exception exception )
134
- {
135
- return ExceptionDuringRouting ( exception , messageContext . MessageId ) ;
125
+ skippedHandlers ++ ;
136
126
}
137
127
128
+ return hasGoneThroughMessageHandler
129
+ ? MatchedHandlerFailed ( messageContext . MessageId )
130
+ : NoMatchedHandler ( messageContext . MessageId ) ;
131
+
138
132
MessageProcessingResult NoHandlersRegistered ( string messageId )
139
133
{
140
134
Logger . LogNoHandlersRegistered ( messageId ) ;
@@ -152,12 +146,6 @@ MessageProcessingResult MatchedHandlerFailed(string messageId)
152
146
Logger . LogMatchedHandlerFailedToProcessMessage ( messageId ) ;
153
147
return MessageProcessingResult . Failure ( messageId , MessageProcessingError . MatchedHandlerFailed , MatchedHandlerFailedMessage ) ;
154
148
}
155
-
156
- MessageProcessingResult ExceptionDuringRouting ( Exception exception , string messageId )
157
- {
158
- Logger . LogExceptionDuringRouting ( exception , messageId ) ;
159
- return MessageProcessingResult . Failure ( messageId , MessageProcessingError . ProcessingInterrupted , ExceptionDuringRoutingMessage , exception ) ;
160
- }
161
149
}
162
150
163
151
private async Task < MessageProcessingResult > ProcessMessageHandlerAsync < TMessageContext > (
@@ -206,7 +194,7 @@ MessageProcessingResult MatchedHandlerSkipped()
206
194
207
195
MessageProcessingResult MatchedHandlerFailed ( Exception exception , string errorMessage )
208
196
{
209
- summary . AddFailed ( exception , "message processing failed" , errorMessage ) ;
197
+ summary . AddFailed ( exception , "message processing failed" , check => check . AddReason ( errorMessage ) ) ;
210
198
211
199
Logger . LogMessageFailedInHandler ( messageType , context . MessageId , handler . MessageHandlerType , summary ) ;
212
200
return MessageProcessingResult . Failure ( context . MessageId , MessageProcessingError . ProcessingInterrupted , "n/a" ) ;
@@ -278,11 +266,11 @@ private async Task<MessageResult> DeserializeMessageAsync(MessageHandler handler
278
266
object deserializedByType = JsonSerializer . Deserialize ( messageBody , handlerMessageType , _jsonOptions ) ;
279
267
if ( deserializedByType != null )
280
268
{
281
- summary . AddPassed ( "default JSON body parsing passed" , ( "additional members" , Options . Deserialization . AdditionalMembers ) ) ;
269
+ summary . AddPassed ( "default JSON body parsing passed" , check => check . AddMember ( "additional members" , Options . Deserialization . AdditionalMembers . ToString ( ) ) ) ;
282
270
return MessageResult . Success ( deserializedByType ) ;
283
271
}
284
272
285
- summary . AddFailed ( "default JSON body parsing failed" , reason : "returns 'null'" ) ;
273
+ summary . AddFailed ( "default JSON body parsing failed" , check => check . AddReason ( "returns 'null'" ) ) ;
286
274
return MessageResult . Failure ( "n/a" ) ;
287
275
}
288
276
catch ( JsonException exception )
@@ -349,9 +337,6 @@ internal static partial class MessageRouterLoggerExtensions
349
337
[ LoggerMessage ( LogLevel . Error , "Message '{MessageId}' [Failed in] message pump => ✗ " + MatchedHandlerFailedMessage ) ]
350
338
internal static partial void LogMatchedHandlerFailedToProcessMessage ( this ILogger logger , string messageId ) ;
351
339
352
- [ LoggerMessage ( LogLevel . Critical , "Message '{MessageId}' [Failed in] message pump => ✗ " + ExceptionDuringRoutingMessage ) ]
353
- internal static partial void LogExceptionDuringRouting ( this ILogger logger , Exception exception , string messageId ) ;
354
-
355
340
internal static void LogMessageSkippedByHandler ( this ILogger logger , string messageId , Type messageHandlerType , MessageHandlerSummary summary )
356
341
{
357
342
LogMessageSkippedByHandler ( logger , summary . OccurredException , messageId , messageHandlerType . Name , summary ) ;
@@ -411,78 +396,107 @@ internal class MessageHandlerSummary
411
396
_ => new AggregateException ( _exceptions )
412
397
} ;
413
398
414
- /// <summary>
415
- /// Adds a passed check to the summary.
416
- /// </summary>
417
- /// <param name="description">The message that describes in a short manner the check that was passed.</param>
418
- /// <param name="members">The additional key-value pair members that were involved in the check.</param>
419
- internal void AddPassed ( string description , params ( string , object ) [ ] members )
399
+ internal class MessageHandlerCheckBuilder
420
400
{
421
- ArgumentNullException . ThrowIfNull ( description ) ;
401
+ private readonly Collection < ( string memberName , string memberValue ) > _members = [ ] ;
402
+ private string _reason ;
403
+ private readonly StringBuilder _result = new ( ) ;
422
404
423
- string membersDescription = members . Length > 0
424
- ? $ " ({ string . Join ( ", " , members . Select ( m => m . Item1 + "=" + m . Item2 ) ) } )"
425
- : string . Empty ;
405
+ private MessageHandlerCheckBuilder ( string description )
406
+ {
407
+ ArgumentException . ThrowIfNullOrWhiteSpace ( description ) ;
408
+ _result . Append ( description ) ;
409
+ }
426
410
427
- _lines . Add ( "✓ " + description + membersDescription ) ;
428
- }
411
+ internal static MessageHandlerCheckBuilder Passed ( string description ) => new ( "✓ " + description ) ;
412
+ internal static MessageHandlerCheckBuilder Failed ( string description ) => new ( "✗ " + description ) ;
429
413
430
- /// <summary>
431
- /// Adds a failed check to the summary.
432
- /// </summary>
433
- /// <param name="exception">The optional exception that occured during the check.</param>
434
- /// <param name="description">The message that describes in a short manner the check that was failed.</param>
435
- /// <param name="reason">The message that explains the reason why the check failed.</param>
436
- internal void AddFailed ( Exception exception , string description , string reason = "exception thrown" )
437
- {
438
- if ( exception is not null )
414
+ /// <summary>
415
+ /// Adds a key-value pair member to the pre-check message - acts as additional context (i.e. 'using type=MyType').
416
+ /// </summary>
417
+ internal MessageHandlerCheckBuilder AddMember ( string memberName , string memberValue )
439
418
{
440
- _exceptions . Add ( exception ) ;
419
+ _members . Add ( ( memberName , memberValue ) ) ;
420
+ return this ;
441
421
}
442
422
443
- AddFailed ( description , reason ) ;
423
+ /// <summary>
424
+ /// Adds a final reason why the pre-check acted like it did.
425
+ /// </summary>
426
+ internal MessageHandlerCheckBuilder AddReason ( string reason )
427
+ {
428
+ _reason = reason ;
429
+ return this ;
430
+ }
431
+
432
+ /// <summary>
433
+ /// Returns a string that represents the current object.
434
+ /// </summary>
435
+ /// <returns>A string that represents the current object.</returns>
436
+ public override string ToString ( )
437
+ {
438
+ if ( _members . Count > 0 )
439
+ {
440
+ _result . Append ( " (" ) ;
441
+ _result . AppendJoin ( ", " , _members . Select ( m => $ "{ m . memberName } ={ m . memberValue } ") ) ;
442
+ _result . Append ( ')' ) ;
443
+ }
444
+
445
+ if ( _reason != null )
446
+ {
447
+ _result . Append ( ": " ) ;
448
+ _result . Append ( _reason ) ;
449
+ }
450
+
451
+ return _result . ToString ( ) ;
452
+ }
444
453
}
445
454
446
455
/// <summary>
447
- /// Adds a failed check to the summary.
456
+ /// Adds a passed pre- check line to the summary.
448
457
/// </summary>
449
- /// <param name="description">The message that describes in a short manner the check that was failed .</param>
450
- /// <param name="reason ">The message that explains the reason why the check failed .</param>
451
- internal void AddFailed ( string description , string reason )
458
+ /// <param name="description">The short description of the pre- check.</param>
459
+ /// <param name="configureCheck ">The additional information around the pre-check, formatted on the same line .</param>
460
+ internal void AddPassed ( string description , Action < MessageHandlerCheckBuilder > configureCheck = null )
452
461
{
453
- ArgumentNullException . ThrowIfNull ( description ) ;
454
- ArgumentNullException . ThrowIfNull ( reason ) ;
462
+ var builder = MessageHandlerCheckBuilder . Passed ( description ) ;
463
+ configureCheck ? . Invoke ( builder ) ;
455
464
456
- AddFailed ( description + " (" + reason + ")" ) ;
465
+ _lines . Add ( builder . ToString ( ) ) ;
457
466
}
458
467
459
468
/// <summary>
460
- /// Adds a failed check to the summary.
469
+ /// Adds a failed pre- check line to the summary.
461
470
/// </summary>
462
- /// <param name="description">The message that describes in a short manner the check that was failed.</param>
463
- /// <param name="members">The additional members that were involved in the check (both single values as tuples are supported).</param>
464
- internal void AddFailed ( string description , params object [ ] members )
471
+ /// <param name="exception">
472
+ /// The occurred exception that caused the pre-check to fail
473
+ /// - only here to track exceptions (<see cref="OccurredException"/>), not to expose information in the logged line.
474
+ /// </param>
475
+ /// <param name="description">The short description of the pre-check.</param>
476
+ /// <param name="configureCheck">The additional information around the pre-check, formatted on the same line.</param>
477
+ internal void AddFailed ( Exception exception , string description , Action < MessageHandlerCheckBuilder > configureCheck = null )
465
478
{
466
- ArgumentNullException . ThrowIfNull ( description ) ;
467
- ArgumentNullException . ThrowIfNull ( members ) ;
479
+ ArgumentNullException . ThrowIfNull ( exception ) ;
480
+ _exceptions . Add ( exception ) ;
468
481
469
- string membersDescription = members . Length > 1
470
- ? $ " ({ string . Join ( ", " , members . Select ( m =>
471
- {
472
- return m switch
473
- {
474
- ( string name , string value ) => $ "{ name } ={ value } ",
475
- _ => m . ToString ( )
476
- } ;
477
- } ) ) } "
478
- : string . Empty ;
479
-
480
- AddFailed ( description + membersDescription ) ;
482
+ AddFailed ( description , check =>
483
+ {
484
+ check . AddReason ( "exception thrown" ) ;
485
+ configureCheck ? . Invoke ( check ) ;
486
+ } ) ;
481
487
}
482
488
483
- private void AddFailed ( string description )
489
+ /// <summary>
490
+ /// Adds a failed pre-check line to the summary.
491
+ /// </summary>
492
+ /// <param name="description">The short description of the pre-check.</param>
493
+ /// <param name="configureCheck">The additional information around the pre-check, formatted on the same line.</param>
494
+ internal void AddFailed ( string description , Action < MessageHandlerCheckBuilder > configureCheck = null )
484
495
{
485
- _lines . Add ( "✗ " + description ) ;
496
+ var builder = MessageHandlerCheckBuilder . Failed ( description ) ;
497
+ configureCheck ? . Invoke ( builder ) ;
498
+
499
+ _lines . Add ( builder . ToString ( ) ) ;
486
500
}
487
501
488
502
/// <summary>
0 commit comments