Particular / NServiceBus

Build, version, and monitor better microservices with the most powerful service platform for .NET
https://particular.net/nservicebus/
Other
2.08k stars 648 forks source link

Message specific recoverability configuration #6344

Open timbussmann opened 2 years ago

timbussmann commented 2 years ago

Recoverability settings and error notifications can only be configured on an endpoint level. Sometimes, specific messages should be retried different amounts of time, or users would like to be notified only when a specific message fails processing and is moved to the error queue. With the current APIs available, this is not impossible but fairly laborious to set up & filter.

In addition, any message specific configuration using the current extensibility and notification APIs is strictly separated from the the business logic (the message handler implementation).

rbecker-brainlab commented 2 years ago

The issue I have is that I want to notify an external system and mark a record as failed, only once the final failure has occurred. This is not something I would like to configure globally, because the implementation is specific to the handler.

I am hoping that something similar to IHandleMessages like IHandleFinalFailure will be implemented.

Separately, it would be nice to be able to configure to not do immediate retries for delayed retries.

sdecoodt commented 1 year ago

@rbecker-brainlab one year later, and I find myself having an identical requirement. This still is not available to my knowledge, what approach did you decide on to get your case handled?

rbecker-brainlab commented 1 year ago

@rbecker-brainlab one year later, and I find myself having an identical requirement. This still is not available to my knowledge, what approach did you decide on to get your case handled?

Retries: As Particular indicated to me, in a distributed scenario, it is not deterministic as to which node handles a message. However, you can check the number of retries in the message header (the retries header is not quite consistent in a distributed scenario, but accurate enough for my purposes):

        string numDelayedRetriesText;
        if (context.MessageHeaders.TryGetValue(NServiceBus.Headers.DelayedRetries, out numDelayedRetriesText))

Final failed: Then, if max retries is reached, then I throw an exception for which a retry will not be performed afterwards. Before throwing this exception, I do what needs to be done to finish off the workflow logic / saga.

The kind of unrecoverable exceptions are configured on the endpoint: (RecoverabilitySettings recoverability) { // Add exceptions, where retries will not be performed. ... recoverability.AddUnrecoverableException(unrecoverableEx);

        recoverability.Immediate(
            settings => 
            {
                settings.NumberOfRetries(App.Configuration.NumberOfImmediateRetries);
            }
        );

        recoverability.Delayed(
            settings =>
            {
                settings.NumberOfRetries(App.Configuration.NumberOfDelayedRetries);
                settings.TimeIncrease(TimeSpan.FromMinutes(App.Configuration.DelayedRetryTimeIncreaseMinutes));                    
            }