DomainEventPublisher consistency
up vote
0
down vote
favorite
Having just read Vaughn Vernon's effective aggregate design, I'm wondering about failures related to event publishing.
In the given example at page 9 (page 3 of the PDF), we call DomainEventPublisher.publish()
. The event being published allows other aggregates to execute their behaviours.
What I'm wondering is: What happens if DomainEventPublisher.publish()
fails ? What happens if DomainEventPublisher.publish()
succeeds, but the transaction fails ?
How implementations handle these two cases ?
domain-driven-design aggregateroot
|
show 11 more comments
up vote
0
down vote
favorite
Having just read Vaughn Vernon's effective aggregate design, I'm wondering about failures related to event publishing.
In the given example at page 9 (page 3 of the PDF), we call DomainEventPublisher.publish()
. The event being published allows other aggregates to execute their behaviours.
What I'm wondering is: What happens if DomainEventPublisher.publish()
fails ? What happens if DomainEventPublisher.publish()
succeeds, but the transaction fails ?
How implementations handle these two cases ?
domain-driven-design aggregateroot
1
that example is not very resilient/usable in the real world. The most reliable patterns are those from the Event sourcing, when the events are not published at all but are pulled from the Event store and the event consumer (the readmodel or saga) keeps track if the processed events.
– Constantin Galbenu
yesterday
1
it uses transactions; it makes the Aggregate dependent of the infrastructure (which can be mitigated by returning the events instead)
– Constantin Galbenu
yesterday
1
@ConstantinGalbenu Whether you return them or use a static thread-bound synchronousDomainEventPublisher
you pretty much get the same exact result with the same testability. The pattern does use database transactions, but the domain is not aware of these in any way. I don't really see your point.
– plalx
yesterday
1
@plalx the Aggregate makes anIO
call and I don't like that. I keep my Aggregates pure, with no side effects, with no dependency to Infrastructure or any other Components in fact.
– Constantin Galbenu
yesterday
1
@ConstantinGalbenu Well, they don't make an IO call if there's no registered handler that does IO, which means everything can be unit tested without any IO going on. The ARs themselves have no dependencies on infrastructure components or any other packages.
– plalx
yesterday
|
show 11 more comments
up vote
0
down vote
favorite
up vote
0
down vote
favorite
Having just read Vaughn Vernon's effective aggregate design, I'm wondering about failures related to event publishing.
In the given example at page 9 (page 3 of the PDF), we call DomainEventPublisher.publish()
. The event being published allows other aggregates to execute their behaviours.
What I'm wondering is: What happens if DomainEventPublisher.publish()
fails ? What happens if DomainEventPublisher.publish()
succeeds, but the transaction fails ?
How implementations handle these two cases ?
domain-driven-design aggregateroot
Having just read Vaughn Vernon's effective aggregate design, I'm wondering about failures related to event publishing.
In the given example at page 9 (page 3 of the PDF), we call DomainEventPublisher.publish()
. The event being published allows other aggregates to execute their behaviours.
What I'm wondering is: What happens if DomainEventPublisher.publish()
fails ? What happens if DomainEventPublisher.publish()
succeeds, but the transaction fails ?
How implementations handle these two cases ?
domain-driven-design aggregateroot
domain-driven-design aggregateroot
asked yesterday
arnaud576875
68.9k16169171
68.9k16169171
1
that example is not very resilient/usable in the real world. The most reliable patterns are those from the Event sourcing, when the events are not published at all but are pulled from the Event store and the event consumer (the readmodel or saga) keeps track if the processed events.
– Constantin Galbenu
yesterday
1
it uses transactions; it makes the Aggregate dependent of the infrastructure (which can be mitigated by returning the events instead)
– Constantin Galbenu
yesterday
1
@ConstantinGalbenu Whether you return them or use a static thread-bound synchronousDomainEventPublisher
you pretty much get the same exact result with the same testability. The pattern does use database transactions, but the domain is not aware of these in any way. I don't really see your point.
– plalx
yesterday
1
@plalx the Aggregate makes anIO
call and I don't like that. I keep my Aggregates pure, with no side effects, with no dependency to Infrastructure or any other Components in fact.
– Constantin Galbenu
yesterday
1
@ConstantinGalbenu Well, they don't make an IO call if there's no registered handler that does IO, which means everything can be unit tested without any IO going on. The ARs themselves have no dependencies on infrastructure components or any other packages.
– plalx
yesterday
|
show 11 more comments
1
that example is not very resilient/usable in the real world. The most reliable patterns are those from the Event sourcing, when the events are not published at all but are pulled from the Event store and the event consumer (the readmodel or saga) keeps track if the processed events.
– Constantin Galbenu
yesterday
1
it uses transactions; it makes the Aggregate dependent of the infrastructure (which can be mitigated by returning the events instead)
– Constantin Galbenu
yesterday
1
@ConstantinGalbenu Whether you return them or use a static thread-bound synchronousDomainEventPublisher
you pretty much get the same exact result with the same testability. The pattern does use database transactions, but the domain is not aware of these in any way. I don't really see your point.
– plalx
yesterday
1
@plalx the Aggregate makes anIO
call and I don't like that. I keep my Aggregates pure, with no side effects, with no dependency to Infrastructure or any other Components in fact.
– Constantin Galbenu
yesterday
1
@ConstantinGalbenu Well, they don't make an IO call if there's no registered handler that does IO, which means everything can be unit tested without any IO going on. The ARs themselves have no dependencies on infrastructure components or any other packages.
– plalx
yesterday
1
1
that example is not very resilient/usable in the real world. The most reliable patterns are those from the Event sourcing, when the events are not published at all but are pulled from the Event store and the event consumer (the readmodel or saga) keeps track if the processed events.
– Constantin Galbenu
yesterday
that example is not very resilient/usable in the real world. The most reliable patterns are those from the Event sourcing, when the events are not published at all but are pulled from the Event store and the event consumer (the readmodel or saga) keeps track if the processed events.
– Constantin Galbenu
yesterday
1
1
it uses transactions; it makes the Aggregate dependent of the infrastructure (which can be mitigated by returning the events instead)
– Constantin Galbenu
yesterday
it uses transactions; it makes the Aggregate dependent of the infrastructure (which can be mitigated by returning the events instead)
– Constantin Galbenu
yesterday
1
1
@ConstantinGalbenu Whether you return them or use a static thread-bound synchronous
DomainEventPublisher
you pretty much get the same exact result with the same testability. The pattern does use database transactions, but the domain is not aware of these in any way. I don't really see your point.– plalx
yesterday
@ConstantinGalbenu Whether you return them or use a static thread-bound synchronous
DomainEventPublisher
you pretty much get the same exact result with the same testability. The pattern does use database transactions, but the domain is not aware of these in any way. I don't really see your point.– plalx
yesterday
1
1
@plalx the Aggregate makes an
IO
call and I don't like that. I keep my Aggregates pure, with no side effects, with no dependency to Infrastructure or any other Components in fact.– Constantin Galbenu
yesterday
@plalx the Aggregate makes an
IO
call and I don't like that. I keep my Aggregates pure, with no side effects, with no dependency to Infrastructure or any other Components in fact.– Constantin Galbenu
yesterday
1
1
@ConstantinGalbenu Well, they don't make an IO call if there's no registered handler that does IO, which means everything can be unit tested without any IO going on. The ARs themselves have no dependencies on infrastructure components or any other packages.
– plalx
yesterday
@ConstantinGalbenu Well, they don't make an IO call if there's no registered handler that does IO, which means everything can be unit tested without any IO going on. The ARs themselves have no dependencies on infrastructure components or any other packages.
– plalx
yesterday
|
show 11 more comments
2 Answers
2
active
oldest
votes
up vote
1
down vote
accepted
DomainEventPublisher.publish()
is synchronous. You'd setup a generic handler (handles all events) which stores the events in the same database transaction as the business process, which means your event storage must have the ability to be transactionnal with whatever other storage mechanism you rely on to store the state of your aggregates.
Once events have been written on disk transactionnaly, you can then put them on a message queue for asynchronous delivery.
Are there other known ways to do it?
Well, rather than using a static DomainEventPublisher
you could record events in a collection on the AR, just like in event sourcing and then implement a centralised mechanism to store them (e.g. transaction hooks, using aspects, etc.).
Thanks. I like this solution. Are there other known ways to do it ?
– arnaud576875
yesterday
add a comment |
up vote
0
down vote
What happens if DomainEventPublisher.publish() succeeds, but the
transaction fails?
In this case I am against Vernon aproach. I prefer to return the events to the application service. This way I can persist the changes performed by the aggregate using a transacion (if needed) and, if everything is Ok, I will publish the event. This also helps to keep the business layer entirely clean and pure.
In a few words; if the transaction fails then no event is raised.
What happens if DomainEventPublisher.publish() fails?
A domain event never fails, by business ruels, because it's a notification of things that happened. If an aggregate said Yes to the operation and return a event expresing the bussines changes; then nothing in the world should say that this operation can not be done or has to be undone.
If the event fails by infrastructure then you need to have the tools to re-raise it (automatically or manualy) when the outage is fixed and eventualy archive the consistency in your system. Take a look at NServiceBus. It provides retries, error queues, logs and so on to never loose the events.
If the message system is down you have at least event logs that you can use to re-reise them into the message system.
Thanks. I think that my question was not clear enough about the things that can fail: The first thing is that we can fail to pulish an event (e.g. the messaging system is down temporarily). The second thing is that after publishing an event, the ongoing transaction can fail to commit; as a result, we have published an event, but the thing didn't really happen since the transaction failed.
– arnaud576875
yesterday
But I am answering that 2 things. What do you do not understand in my answer that drives you to think that I misunderstood your question?
– jlvaquero
yesterday
I'm speaking about publishing events, not about handling them :)
– arnaud576875
yesterday
And my answer is that changing Vernon strategy allows you to publish the events when the transaction commits or not publish them when transaction fails.
– jlvaquero
yesterday
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
accepted
DomainEventPublisher.publish()
is synchronous. You'd setup a generic handler (handles all events) which stores the events in the same database transaction as the business process, which means your event storage must have the ability to be transactionnal with whatever other storage mechanism you rely on to store the state of your aggregates.
Once events have been written on disk transactionnaly, you can then put them on a message queue for asynchronous delivery.
Are there other known ways to do it?
Well, rather than using a static DomainEventPublisher
you could record events in a collection on the AR, just like in event sourcing and then implement a centralised mechanism to store them (e.g. transaction hooks, using aspects, etc.).
Thanks. I like this solution. Are there other known ways to do it ?
– arnaud576875
yesterday
add a comment |
up vote
1
down vote
accepted
DomainEventPublisher.publish()
is synchronous. You'd setup a generic handler (handles all events) which stores the events in the same database transaction as the business process, which means your event storage must have the ability to be transactionnal with whatever other storage mechanism you rely on to store the state of your aggregates.
Once events have been written on disk transactionnaly, you can then put them on a message queue for asynchronous delivery.
Are there other known ways to do it?
Well, rather than using a static DomainEventPublisher
you could record events in a collection on the AR, just like in event sourcing and then implement a centralised mechanism to store them (e.g. transaction hooks, using aspects, etc.).
Thanks. I like this solution. Are there other known ways to do it ?
– arnaud576875
yesterday
add a comment |
up vote
1
down vote
accepted
up vote
1
down vote
accepted
DomainEventPublisher.publish()
is synchronous. You'd setup a generic handler (handles all events) which stores the events in the same database transaction as the business process, which means your event storage must have the ability to be transactionnal with whatever other storage mechanism you rely on to store the state of your aggregates.
Once events have been written on disk transactionnaly, you can then put them on a message queue for asynchronous delivery.
Are there other known ways to do it?
Well, rather than using a static DomainEventPublisher
you could record events in a collection on the AR, just like in event sourcing and then implement a centralised mechanism to store them (e.g. transaction hooks, using aspects, etc.).
DomainEventPublisher.publish()
is synchronous. You'd setup a generic handler (handles all events) which stores the events in the same database transaction as the business process, which means your event storage must have the ability to be transactionnal with whatever other storage mechanism you rely on to store the state of your aggregates.
Once events have been written on disk transactionnaly, you can then put them on a message queue for asynchronous delivery.
Are there other known ways to do it?
Well, rather than using a static DomainEventPublisher
you could record events in a collection on the AR, just like in event sourcing and then implement a centralised mechanism to store them (e.g. transaction hooks, using aspects, etc.).
edited yesterday
answered yesterday
plalx
32k44770
32k44770
Thanks. I like this solution. Are there other known ways to do it ?
– arnaud576875
yesterday
add a comment |
Thanks. I like this solution. Are there other known ways to do it ?
– arnaud576875
yesterday
Thanks. I like this solution. Are there other known ways to do it ?
– arnaud576875
yesterday
Thanks. I like this solution. Are there other known ways to do it ?
– arnaud576875
yesterday
add a comment |
up vote
0
down vote
What happens if DomainEventPublisher.publish() succeeds, but the
transaction fails?
In this case I am against Vernon aproach. I prefer to return the events to the application service. This way I can persist the changes performed by the aggregate using a transacion (if needed) and, if everything is Ok, I will publish the event. This also helps to keep the business layer entirely clean and pure.
In a few words; if the transaction fails then no event is raised.
What happens if DomainEventPublisher.publish() fails?
A domain event never fails, by business ruels, because it's a notification of things that happened. If an aggregate said Yes to the operation and return a event expresing the bussines changes; then nothing in the world should say that this operation can not be done or has to be undone.
If the event fails by infrastructure then you need to have the tools to re-raise it (automatically or manualy) when the outage is fixed and eventualy archive the consistency in your system. Take a look at NServiceBus. It provides retries, error queues, logs and so on to never loose the events.
If the message system is down you have at least event logs that you can use to re-reise them into the message system.
Thanks. I think that my question was not clear enough about the things that can fail: The first thing is that we can fail to pulish an event (e.g. the messaging system is down temporarily). The second thing is that after publishing an event, the ongoing transaction can fail to commit; as a result, we have published an event, but the thing didn't really happen since the transaction failed.
– arnaud576875
yesterday
But I am answering that 2 things. What do you do not understand in my answer that drives you to think that I misunderstood your question?
– jlvaquero
yesterday
I'm speaking about publishing events, not about handling them :)
– arnaud576875
yesterday
And my answer is that changing Vernon strategy allows you to publish the events when the transaction commits or not publish them when transaction fails.
– jlvaquero
yesterday
add a comment |
up vote
0
down vote
What happens if DomainEventPublisher.publish() succeeds, but the
transaction fails?
In this case I am against Vernon aproach. I prefer to return the events to the application service. This way I can persist the changes performed by the aggregate using a transacion (if needed) and, if everything is Ok, I will publish the event. This also helps to keep the business layer entirely clean and pure.
In a few words; if the transaction fails then no event is raised.
What happens if DomainEventPublisher.publish() fails?
A domain event never fails, by business ruels, because it's a notification of things that happened. If an aggregate said Yes to the operation and return a event expresing the bussines changes; then nothing in the world should say that this operation can not be done or has to be undone.
If the event fails by infrastructure then you need to have the tools to re-raise it (automatically or manualy) when the outage is fixed and eventualy archive the consistency in your system. Take a look at NServiceBus. It provides retries, error queues, logs and so on to never loose the events.
If the message system is down you have at least event logs that you can use to re-reise them into the message system.
Thanks. I think that my question was not clear enough about the things that can fail: The first thing is that we can fail to pulish an event (e.g. the messaging system is down temporarily). The second thing is that after publishing an event, the ongoing transaction can fail to commit; as a result, we have published an event, but the thing didn't really happen since the transaction failed.
– arnaud576875
yesterday
But I am answering that 2 things. What do you do not understand in my answer that drives you to think that I misunderstood your question?
– jlvaquero
yesterday
I'm speaking about publishing events, not about handling them :)
– arnaud576875
yesterday
And my answer is that changing Vernon strategy allows you to publish the events when the transaction commits or not publish them when transaction fails.
– jlvaquero
yesterday
add a comment |
up vote
0
down vote
up vote
0
down vote
What happens if DomainEventPublisher.publish() succeeds, but the
transaction fails?
In this case I am against Vernon aproach. I prefer to return the events to the application service. This way I can persist the changes performed by the aggregate using a transacion (if needed) and, if everything is Ok, I will publish the event. This also helps to keep the business layer entirely clean and pure.
In a few words; if the transaction fails then no event is raised.
What happens if DomainEventPublisher.publish() fails?
A domain event never fails, by business ruels, because it's a notification of things that happened. If an aggregate said Yes to the operation and return a event expresing the bussines changes; then nothing in the world should say that this operation can not be done or has to be undone.
If the event fails by infrastructure then you need to have the tools to re-raise it (automatically or manualy) when the outage is fixed and eventualy archive the consistency in your system. Take a look at NServiceBus. It provides retries, error queues, logs and so on to never loose the events.
If the message system is down you have at least event logs that you can use to re-reise them into the message system.
What happens if DomainEventPublisher.publish() succeeds, but the
transaction fails?
In this case I am against Vernon aproach. I prefer to return the events to the application service. This way I can persist the changes performed by the aggregate using a transacion (if needed) and, if everything is Ok, I will publish the event. This also helps to keep the business layer entirely clean and pure.
In a few words; if the transaction fails then no event is raised.
What happens if DomainEventPublisher.publish() fails?
A domain event never fails, by business ruels, because it's a notification of things that happened. If an aggregate said Yes to the operation and return a event expresing the bussines changes; then nothing in the world should say that this operation can not be done or has to be undone.
If the event fails by infrastructure then you need to have the tools to re-raise it (automatically or manualy) when the outage is fixed and eventualy archive the consistency in your system. Take a look at NServiceBus. It provides retries, error queues, logs and so on to never loose the events.
If the message system is down you have at least event logs that you can use to re-reise them into the message system.
edited yesterday
answered yesterday
jlvaquero
6,50211836
6,50211836
Thanks. I think that my question was not clear enough about the things that can fail: The first thing is that we can fail to pulish an event (e.g. the messaging system is down temporarily). The second thing is that after publishing an event, the ongoing transaction can fail to commit; as a result, we have published an event, but the thing didn't really happen since the transaction failed.
– arnaud576875
yesterday
But I am answering that 2 things. What do you do not understand in my answer that drives you to think that I misunderstood your question?
– jlvaquero
yesterday
I'm speaking about publishing events, not about handling them :)
– arnaud576875
yesterday
And my answer is that changing Vernon strategy allows you to publish the events when the transaction commits or not publish them when transaction fails.
– jlvaquero
yesterday
add a comment |
Thanks. I think that my question was not clear enough about the things that can fail: The first thing is that we can fail to pulish an event (e.g. the messaging system is down temporarily). The second thing is that after publishing an event, the ongoing transaction can fail to commit; as a result, we have published an event, but the thing didn't really happen since the transaction failed.
– arnaud576875
yesterday
But I am answering that 2 things. What do you do not understand in my answer that drives you to think that I misunderstood your question?
– jlvaquero
yesterday
I'm speaking about publishing events, not about handling them :)
– arnaud576875
yesterday
And my answer is that changing Vernon strategy allows you to publish the events when the transaction commits or not publish them when transaction fails.
– jlvaquero
yesterday
Thanks. I think that my question was not clear enough about the things that can fail: The first thing is that we can fail to pulish an event (e.g. the messaging system is down temporarily). The second thing is that after publishing an event, the ongoing transaction can fail to commit; as a result, we have published an event, but the thing didn't really happen since the transaction failed.
– arnaud576875
yesterday
Thanks. I think that my question was not clear enough about the things that can fail: The first thing is that we can fail to pulish an event (e.g. the messaging system is down temporarily). The second thing is that after publishing an event, the ongoing transaction can fail to commit; as a result, we have published an event, but the thing didn't really happen since the transaction failed.
– arnaud576875
yesterday
But I am answering that 2 things. What do you do not understand in my answer that drives you to think that I misunderstood your question?
– jlvaquero
yesterday
But I am answering that 2 things. What do you do not understand in my answer that drives you to think that I misunderstood your question?
– jlvaquero
yesterday
I'm speaking about publishing events, not about handling them :)
– arnaud576875
yesterday
I'm speaking about publishing events, not about handling them :)
– arnaud576875
yesterday
And my answer is that changing Vernon strategy allows you to publish the events when the transaction commits or not publish them when transaction fails.
– jlvaquero
yesterday
And my answer is that changing Vernon strategy allows you to publish the events when the transaction commits or not publish them when transaction fails.
– jlvaquero
yesterday
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53409319%2fdomaineventpublisher-consistency%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
that example is not very resilient/usable in the real world. The most reliable patterns are those from the Event sourcing, when the events are not published at all but are pulled from the Event store and the event consumer (the readmodel or saga) keeps track if the processed events.
– Constantin Galbenu
yesterday
1
it uses transactions; it makes the Aggregate dependent of the infrastructure (which can be mitigated by returning the events instead)
– Constantin Galbenu
yesterday
1
@ConstantinGalbenu Whether you return them or use a static thread-bound synchronous
DomainEventPublisher
you pretty much get the same exact result with the same testability. The pattern does use database transactions, but the domain is not aware of these in any way. I don't really see your point.– plalx
yesterday
1
@plalx the Aggregate makes an
IO
call and I don't like that. I keep my Aggregates pure, with no side effects, with no dependency to Infrastructure or any other Components in fact.– Constantin Galbenu
yesterday
1
@ConstantinGalbenu Well, they don't make an IO call if there's no registered handler that does IO, which means everything can be unit tested without any IO going on. The ARs themselves have no dependencies on infrastructure components or any other packages.
– plalx
yesterday