You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Adding custom middleware which can throw an exception causes unexpected behaviour, namely, handler starvation.
It seems the default pipeline has the following setup - source
publicstaticHandlerMiddlewareBuilderUseDefaults<TMessage>(thisHandlerMiddlewareBuilderbuilder,TypehandlerType)whereTMessage:Message{if(builder==null)thrownewArgumentNullException(nameof(builder));if(handlerType==null)thrownewArgumentNullException(nameof(handlerType),"HandlerType is used here to");builder.UseMessageContextAccessor();builder.Use<LoggingMiddleware>();builder.UseStopwatch(handlerType);builder.Use<SqsPostProcessorMiddleware>();builder.UseErrorHandler();builder.UseHandler<TMessage>();returnbuilder;}
Specifically, the UseErrorHandler middleware added here, converts exceptions into a false result from the handler - source
x.WithSubscriptionGroup("error_messages", cfg =>cfg.WithConcurrencyLimit(1));x.ForTopic<ErrorMessage>(
cfg =>{cfg.WithMiddlewareConfiguration(
m =>{m.Use<BadMiddlewareTest>();m.UseDefaults<ErrorMessage>(typeof(ErrorMessageHandler));});cfg.WithReadConfiguration(
r =>{r.SubscriptionGroupName="error_messages";r.RetryCountBeforeSendingToErrorQueue=1;});});
Even if we wait forever, we only ever see a count of 1, however, if we remove the BadMiddlewareTest, we receive the correct count of 10.
In addition, we can also move this middleware deeper in the chain, and the exception being caught will solve this behaviour:
x.ForTopic<ErrorMessage>(
cfg =>{cfg.WithMiddlewareConfiguration(
m =>{m.UseMessageContextAccessor();m.Use<LoggingMiddleware>();m.UseStopwatch(handlerType);m.Use<SqsPostProcessorMiddleware>();m.UseErrorHandler();m.Use<BadMiddlewareTest>();m.UseHandler<TMessage>();});cfg.WithReadConfiguration(
r =>{r.SubscriptionGroupName="error_messages";r.RetryCountBeforeSendingToErrorQueue=1;});});
It has taken us a fair while to work out why we kept suffering from handlers stopping from processing their work and freezing up, and it turns out our UoW middleware we added could throw if it failed to write to the database.
I'm not sure if this is expected behaviour, but if it is, it must be documented clearly when writing middleware. It must not throw an exception under any circumstance unless its added after UseErrorHandler which will handle the issue for you.
The text was updated successfully, but these errors were encountered:
Adding custom middleware which can throw an exception causes unexpected behaviour, namely, handler starvation.
It seems the default pipeline has the following setup - source
Specifically, the
UseErrorHandler
middleware added here, converts exceptions into a false result from the handler - sourceNow, consider a user decides to add some middleware to the outside of the pipeline:
Now I configure this as such:
Now a simple handler:
We can make a simple test, publish 10 messages, I expect the count to be 10, its actually 1:
Even if we wait forever, we only ever see a count of 1, however, if we remove the
BadMiddlewareTest
, we receive the correct count of 10.In addition, we can also move this middleware deeper in the chain, and the exception being caught will solve this behaviour:
It has taken us a fair while to work out why we kept suffering from handlers stopping from processing their work and freezing up, and it turns out our UoW middleware we added could throw if it failed to write to the database.
I'm not sure if this is expected behaviour, but if it is, it must be documented clearly when writing middleware. It must not throw an exception under any circumstance unless its added after
UseErrorHandler
which will handle the issue for you.The text was updated successfully, but these errors were encountered: