We need another case for a Decorator using MediatR and the CommandHandlers with .NET Core.
Just having a LogDecorator doesn't justify the use of Decorators in a generic way based with MediatR.
A good candidate for this would be a TRANSACTION decorator, using the following underneath:
EF Core transactions can be explicitly controlled with context.Database.BeginTransaction()
EF Core also supports cross-context transaction (relational databases only), so you can also share a transaction across multiple context instances. This functionality is only available when using a relational database provider because it requires the use of聽DbTransaction聽and聽DbConnection, which are specific to relational databases. To share a transaction, the contexts must share both a聽DbConnection聽and a聽DbTransaction.
See: https://docs.microsoft.com/en-us/ef/core/saving/transactions
Any other good candidate for additional Decorators other than this?
Please, answer this thread in GitHub when possible.
I would avoid Transactions via decorators.
We tried this in our early days of running on Brighter, but it leads to the anti-pattern that the whole of the handler is contained within the transaction. Now, if a developer decides to do something long-running here, such as calling an HTTP endpoint, or posting a message onto RMQ, you are going to hold the transaction open for the whole time period. That is obviously a no-no.
For that reason we dropped Transactional decorators and forced developers to explicitly manage the transaction lifetime within the handler.
Our main use case for decorators is resiliency. Brighter wraps Polly and you can then run your pipeline within a Polly policy declaritively. We do this by using a Russian Doll approach to composition. EPoll is a Python library that one of the team wrote that uses a similar decorator wrapper to support resiliency model.
We also use decorators to handle fallback scenarios. Darker, our query side project for example will use it to acces a cache on fallback.
Agreed. This issue is actually kind of old and we were thinking about something different instead of a transaction decorator.
The next decorator we were thinking about was a Validator decorator, maybe using FluentValidation https://github.com/JeremySkinner/FluentValidation or similar.
Resiliency might also be a good case for a decorator, although using Polly for resiliency would also be needed from the client apps. We're planning to use Polly for resiliency in the upcoming weeks, as shown in our roadmap.
It would be great to see a fork of this sample app with your implementation using Brighter, so we and the community learn from your experiences. And it would be referenced from our guidance, too. :)
Will do, we have 15% time coming up next week, we'll endeavour to get a Brighter fork up and running so you can see how it would work. I can probably get a few co-conspirators to help me :-)
(PS It does also mean we can do some heavy lifting if you need some bodies. Just ask. We have thought about doing something similar to your project, but working with you guys makes more sense, so not a big ask)
Sure! If you guys see code that could be improved by itself (not really related to the Brighter implementation), please do pull requests! :)
Most helpful comment
I would avoid Transactions via decorators.
We tried this in our early days of running on Brighter, but it leads to the anti-pattern that the whole of the handler is contained within the transaction. Now, if a developer decides to do something long-running here, such as calling an HTTP endpoint, or posting a message onto RMQ, you are going to hold the transaction open for the whole time period. That is obviously a no-no.
For that reason we dropped Transactional decorators and forced developers to explicitly manage the transaction lifetime within the handler.
Our main use case for decorators is resiliency. Brighter wraps Polly and you can then run your pipeline within a Polly policy declaritively. We do this by using a Russian Doll approach to composition. EPoll is a Python library that one of the team wrote that uses a similar decorator wrapper to support resiliency model.
We also use decorators to handle fallback scenarios. Darker, our query side project for example will use it to acces a cache on fallback.