-
-
Notifications
You must be signed in to change notification settings - Fork 21
Multiple message handlers #573
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Multiple message handlers #573
Conversation
| } | ||
|
|
||
| #[EventHandler(endpointId: 'createWhenDebtorWasChanged', identifierMapping: ['debtorId' => 'payload.newDebtor'])] | ||
| public static function createWhenDebtorWasChanged( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we would go this path, then there should be still guard that there is only one factory:action for given identifier mapping (either payload or headers).
Otherwise it become confusing whatever they do relate to each other or not, and then it's not obvious if we should create instance or redirect to action.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dgafka yes, right now Ecotone guards factory:action combination and does not take identifier mapping into consideration. I think adding this into account does not introduce BC as it won't affect cases where there is already one factory:action.
|
|
||
| self::assertEquals(['product-1'], $ecotone->getAggregate(InvoiceOrder::class, 'debtor-1')->products()); | ||
|
|
||
| $ecotone->publishEvent(new ProductDebtorWasChanged(productId: 'product-1', oldDebtor: 'debtor-1', newDebtor: 'debtor-2')); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It feels like the design here is that, Product is stating that Debtor was changed, but Debtor itself also hold the list and need to be synchronized (even so it's not source of truth for it, because Product is?)
I wonder if this could be modelled differently?
For example Debtor (debtor-1) would record an event ProductDebtorWasChanged (which would unassign the product), and then there would be single Event Handler on the Debtor, that would be called based on newDebtor id. This way Product itself is not really holding Debtor information and that info is not in need to be synced there.
Do you have other scenarios where we would like to trigger same Aggregate but more than one instance, based on single Event?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dgafka Example here is simplified.
In real example, Products Debtor is "calculated" based on changes in Product itself so it is changed for the Product, not for the Debtor. Later we need to assign Product in correct Invoice. That logic is not 100% applicable for Product nor Debtor so we want to introduce InvoiceOrder as something in the middle that would keep that coupling away from both Product and Debtor.
This is a typical problem for us whenever we have to "move" something. When identifier of an "orchestrator" is hard to define we'd introduce technical ACL which would do all the complex logic but this is not that efficient and hard to track.
Why is this change proposed?
Consider following scenario.
ProductBecameBillable), it should be added toInvoiceOrderidentified byDebtorof billable product.InvoiceOrdercan be created when this occurs.Debtorof a product can change overtime (ProductDebtorWasChanged). When it happens, following outcome should take place:InvoiceOrdeidentified by oldDebtorInvoiceOrderidentified by newDebtor.InvoiceOrderof newDebtormay not yet exists, therefore it can be created when this occurs.Above scenario require aggregate to have multiple factory methods and action channels:
ProductBecameBillable- factory method ofInvoiceOrderProductDebtorWasChanged- factory method + two action channels, one to remove and second to add product toInvoiceOrderProper identifier mapping is defined in
EventHandlerdefinition as shown inpackages/Ecotone/tests/Modelling/Fixture/MultipleMessageHandlers/InvoiceOrder.phpHowever, current implementation require that Message Handlers on Aggregate and Saga can be used either for single factory method and single action method together, or for multiple actions methods and forbid that implementation.
Description of Changes
tbd
Pull Request Contribution Terms