Comments (1)
Hey, sorry about the reply, thanks for your patience 😄
I couldn't read the whole article since it's on Medium and it want's be to login but... I think I get the gist from the image and first part of the text.
I think it is technically possible, but not sure if it's a good solution in practice. If transaction lifecycle is part of the pipeline, it might be a little unclear what should happen when commands trigger subsequent commands. Is it always the case that transactions should cover the whole graph of commands that are dispatched? That is a little unclear to me, and that would make me nervous. In the applications I've worked on the transaction boundaries are important, and I want the developers to care about them and understand them when interacting with the database, so I'd say my preference would be to not keep transaction lifecycle in the pipeline, but be closer to the specifics of the feature (i.e. in the message handlers)
However, I think if I were to experiment with this kind of abstraction I would go in this general direction:
public interface ITransactionalCommand<TResponse> : ICommand<TResponse> { }
public sealed class TransactionalBoundary<TCommand, TResponse> : IPipelineBehavior<TCommand, TResponse>
where TCommand : ITransactionalCommand<TResponse>
{
internal static readonly AsyncLocal<(DbConnection Connection, DbTransaction Transaction)> _currentTransaction = new();
public async ValueTask<TResponse> Handle(
TCommand command,
MessageHandlerDelegate<TCommand, TResponse> next,
CancellationToken cancellationToken
)
{
var ownsTransaction = false;
if (_currentTransaction.Value.Connection is null)
{
_currentTransaction.Value = (new DbTransaction, new DbConnection());
ownsTransaction = true;
}
try {
return await next(command, cancellationToken);
} finally {
// Handle transaction commit/rollback using catch/finally blocks
if (ownsTransaction)
{
// ...
}
}
}
}
public abstract class TransactionCommandHandler<TCommand, TResponse> : ICommandHandler<TCommand, TResponse>
where TCommand : ITransactionalCommand<TResponse>
{
public (DbConnection Connection, DbTransaction Transaction) Db => TransactionalBoundary<TCommand, TResponse>._currentTransaction.Value;
public abstract ValueTask<TResponse> Handle(TCommand command, CancellationToken cancellationToken);
}
// Now define commands that implement ITransactionalCommand, and handlers that inherit from TransactionCommandHandler
This is completely untested. It uses AsyncLocal
which can be kind of dangerous and has some pitfalls. It's unclear what happens if handlers dispatch commands that are not ITransactionalCommand
etc.. So I'm not sure if this kind of abstraction is worth it. I'm sure it depends on project requirements, team discipline and skill-level etc 😄
from mediator.
Related Issues (20)
- AddMediator(config => ..) not working HOT 4
- Run NotificationHandlers in parallel HOT 17
- Usage without dependency injection HOT 2
- Support for internal objects that implement IRequest. HOT 2
- Is it possible to get a Courier design similar to another library in Mediatr HOT 2
- Suggestion: Consider moving the analyzing to a dedicated analyzer HOT 2
- Multilayered app problem HOT 6
- Generator 'IncrementalMediatorGenerator' failed to initialize under .net 8 (8.0.0.100) and Sonoma 14.1 HOT 1
- DefaultServiceLifetime.Transient registers Mediator as transient too as opposed to ReadMe HOT 7
- Proposal: Mediator 3.0 design to support multiple configuration and fast switching. HOT 1
- Empty Handler needed in order to work with behavoiur pipeline HOT 2
- Sample projects don't work in isolation HOT 3
- different Request/Command/Query HOT 2
- Native AOT HOT 2
- Mediator.MissingMessageHandlerException Help
- Incorrect switch case order in polymorphic notifications HOT 3
- Issue on Project with Mediator and MassTransit HOT 1
- Support generic handlers HOT 3
- Move Interfaces to Mediatr Contracts Package.
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from mediator.