diff --git a/packages/Ecotone/src/Modelling/Config/AggregrateModule.php b/packages/Ecotone/src/Modelling/Config/AggregrateModule.php index a576dea4b..1145009bc 100644 --- a/packages/Ecotone/src/Modelling/Config/AggregrateModule.php +++ b/packages/Ecotone/src/Modelling/Config/AggregrateModule.php @@ -196,14 +196,11 @@ private function initChannelsToBridge(): void // All channels on this route are factory or action channels, continue normal processing continue; } - if (count($staticChannels) > 1 || count($actionChannels) > 1) { - throw ConfigurationException::create("Message Handlers on Aggregate and Saga can be used either for single factory method and single action method together, or for multiple actions methods in {$staticRegistration->getClassName()}"); - } - // Exactly one factory and one action channel, register a bridge + // register a bridge if ($bridgeForThisFactoryMethod === null) { $bridgeForThisFactoryMethod = [ 'factoryChannel' => reset($staticChannels), - 'actionChannel' => reset($actionChannels), + 'actionChannels' => $actionChannels, 'routes' => [$routedKey], ]; } else { @@ -211,14 +208,14 @@ private function initChannelsToBridge(): void $bridgeForThisFactoryMethod['routes'][] = $routedKey; Assert::isTrue( reset($staticChannels) === $bridgeForThisFactoryMethod['factoryChannel'] - && reset($actionChannels) === $bridgeForThisFactoryMethod['actionChannel'], + && $actionChannels === $bridgeForThisFactoryMethod['actionChannels'], "Trying to register multiple factory methods for {$staticRegistration->getClassName()} under same route {$routedKey}" ); } } if ($bridgeForThisFactoryMethod !== null) { $this->channelsToBridge[$bridgeForThisFactoryMethod['factoryChannel']] = $channelToRegistrations[$bridgeForThisFactoryMethod['actionChannel']]; - $this->channelsToCancel[] = $bridgeForThisFactoryMethod['actionChannel']; + $this->channelsToCancel += $bridgeForThisFactoryMethod['actionChannels']; } } } diff --git a/packages/Ecotone/tests/Modelling/Fixture/MultipleMessageHandlers/InvoiceOrder.php b/packages/Ecotone/tests/Modelling/Fixture/MultipleMessageHandlers/InvoiceOrder.php new file mode 100644 index 000000000..4721e78a7 --- /dev/null +++ b/packages/Ecotone/tests/Modelling/Fixture/MultipleMessageHandlers/InvoiceOrder.php @@ -0,0 +1,61 @@ +products = []; + } + + public function products(): array + { + return $this->products; + } + + #[EventHandler(endpointId: 'createWhenProductBecameBillable', identifierMapping: ['debtorId' => 'payload.debtor'])] + public static function createWhenProductBecameBillable( + #[Payload] ProductBecameBillable $event + ): self { + $invoiceOrder = new self($event->debtor); + $invoiceOrder->products[] = $event->productId; + + return $invoiceOrder; + } + + #[EventHandler(endpointId: 'createWhenDebtorWasChanged', identifierMapping: ['debtorId' => 'payload.newDebtor'])] + public static function createWhenDebtorWasChanged( + #[Payload] ProductDebtorWasChanged $event + ): self { + $invoiceOrder = new self($event->newDebtor); + $invoiceOrder->products[] = $event->productId; + + return $invoiceOrder; + } + + #[EventHandler(endpointId: 'removeProductWhenDebtorWasChanged', identifierMapping: ['debtorId' => 'payload.oldDebtor'])] + public function removeProductWhenDebtorWasChanged( + #[Payload] ProductDebtorWasChanged $event + ): void { + unset($this->products[$event->productId]); + } + + #[EventHandler(endpointId: 'addProductWhenDebtorWasChanged', identifierMapping: ['debtorId' => 'payload.newDebtor'])] + public function addProductWhenDebtorWasChanged( + #[Payload] ProductDebtorWasChanged $event + ): void { + if (!in_array($event->productId, $this->products, true)) { + $this->products[] = $event->productId; + } + } +} diff --git a/packages/Ecotone/tests/Modelling/Fixture/MultipleMessageHandlers/ProductBecameBillable.php b/packages/Ecotone/tests/Modelling/Fixture/MultipleMessageHandlers/ProductBecameBillable.php new file mode 100644 index 000000000..0c35218fe --- /dev/null +++ b/packages/Ecotone/tests/Modelling/Fixture/MultipleMessageHandlers/ProductBecameBillable.php @@ -0,0 +1,12 @@ +withNamespaces(['Test\Ecotone\Modelling\Fixture\MultipleMessageHandlers']) + ->withExtensionObjects([ + SimpleMessageChannelBuilder::createQueueChannel('invoiceOrder') + ]) + , + ); + + $ecotone->publishEvent(new ProductBecameBillable(productId: 'product-1', debtor: 'debtor-1')); + + self::assertEquals(['product-1'], $ecotone->getAggregate(InvoiceOrder::class, 'debtor-1')->products()); + + $ecotone->publishEvent(new ProductDebtorWasChanged(productId: 'product-1', oldDebtor: 'debtor-1', newDebtor: 'debtor-2')); + + self::assertEquals([], $ecotone->getAggregate(InvoiceOrder::class, 'debtor-1')->products()); + self::assertEquals(['product-1'], $ecotone->getAggregate(InvoiceOrder::class, 'debtor-1')->products()); + } +}