diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 525dd4e..4b23a6b 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -50,7 +50,16 @@ public function getConfigTreeBuilder(): TreeBuilder 'bottom_center', 'bottom_right', ]) - ->scalarPrototype() + ->scalarPrototype()->end() + ->end() + ->arrayNode('assignment') + ->addDefaultsIfNotSet() + ->children() + ->integerNode('processing_delay') + ->info('The delay in seconds when processing a callout. This is to avoid processing the same callout multiple times within a short interval') + ->defaultValue(60) + ->min(0) + ; $this->addResourcesSection($rootNode); diff --git a/src/DependencyInjection/SetonoSyliusCalloutExtension.php b/src/DependencyInjection/SetonoSyliusCalloutExtension.php index 0a15136..b0c6e3e 100644 --- a/src/DependencyInjection/SetonoSyliusCalloutExtension.php +++ b/src/DependencyInjection/SetonoSyliusCalloutExtension.php @@ -21,6 +21,7 @@ public function load(array $configs, ContainerBuilder $container): void * @var array{ * elements: list, * positions: list, + * assignment: array{processing_delay: int}, * resources: array * } $config */ @@ -31,6 +32,7 @@ public function load(array $configs, ContainerBuilder $container): void $container->setParameter('setono_sylius_callout.elements', $config['elements']); $container->setParameter('setono_sylius_callout.positions', $config['positions']); + $container->setParameter('setono_sylius_callout.assignment.processing_delay', $config['assignment']['processing_delay']); $this->registerResources('setono_sylius_callout', SyliusResourceBundle::DRIVER_DOCTRINE_ORM, $config['resources'], $container); } diff --git a/src/EventSubscriber/HandleCalloutUpdateSubscriber.php b/src/EventSubscriber/HandleCalloutUpdateSubscriber.php index 065b1ae..abee099 100644 --- a/src/EventSubscriber/HandleCalloutUpdateSubscriber.php +++ b/src/EventSubscriber/HandleCalloutUpdateSubscriber.php @@ -11,6 +11,7 @@ use Setono\SyliusCalloutPlugin\Model\CalloutRuleInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Messenger\MessageBusInterface; +use Symfony\Component\Messenger\Stamp\DelayStamp; /** * This subscriber listens for changes to callouts and callout rules @@ -21,12 +22,14 @@ final class HandleCalloutUpdateSubscriber implements EventSubscriberInterface /** * The keys are the callout codes and the values are true * - * @var array + * @var array */ private array $calloutsToAssign = []; - public function __construct(private readonly MessageBusInterface $commandBus) - { + public function __construct( + private readonly MessageBusInterface $commandBus, + private readonly int $processingDelay, + ) { } public static function getSubscribedEvents(): array @@ -47,7 +50,7 @@ public function prePersist(PrePersistEventArgs $event): void return; } - $this->calloutsToAssign[(string) $callout->getCode()] = true; + $this->calloutsToAssign[(string) $callout->getCode()] = $callout; } /** @@ -91,7 +94,7 @@ private function preUpdateCallout(CalloutInterface $callout, PreUpdateEventArgs return; } - $this->calloutsToAssign[(string) $callout->getCode()] = true; + $this->calloutsToAssign[(string) $callout->getCode()] = $callout; } /** @@ -108,12 +111,12 @@ private function preUpdateCalloutRule(CalloutRuleInterface $calloutRule, PreUpda return; } - $this->calloutsToAssign[(string) $callout->getCode()] = true; + $this->calloutsToAssign[(string) $callout->getCode()] = $callout; } /** * This is called when a callout is created or updated by Sylius. - * In the lifecycle this is the last method called and therefore we can safely dispatch the message here if needed + * In the lifecycle this is the last method called, and therefore we can safely dispatch the message here if needed */ public function postUpdate(): void { @@ -121,6 +124,11 @@ public function postUpdate(): void return; } - $this->commandBus->dispatch(new AssignCallouts(array_keys($this->calloutsToAssign))); + $stamps = []; + if ($this->processingDelay > 0) { + $stamps[] = new DelayStamp($this->processingDelay * 1000); + } + + $this->commandBus->dispatch(new AssignCallouts(array_values($this->calloutsToAssign)), $stamps); } } diff --git a/src/Message/Command/AssignCallout.php b/src/Message/Command/AssignCallout.php deleted file mode 100644 index 1f32fb1..0000000 --- a/src/Message/Command/AssignCallout.php +++ /dev/null @@ -1,31 +0,0 @@ -version = $callout->getVersion(); - $callout = (string) $callout->getCode(); - } - - $this->callout = $callout; - } -} diff --git a/src/Message/Command/AssignCallouts.php b/src/Message/Command/AssignCallouts.php index 42e8cdb..07e7f16 100644 --- a/src/Message/Command/AssignCallouts.php +++ b/src/Message/Command/AssignCallouts.php @@ -11,7 +11,11 @@ */ final class AssignCallouts implements CommandInterface { - /** @var list */ + /** + * This is a list of arrays where the first element is the callout code and the second element is the version + * + * @var list + */ public array $callouts = []; /** @@ -20,7 +24,7 @@ final class AssignCallouts implements CommandInterface public function __construct(array $callouts = []) { foreach ($callouts as $callout) { - $this->callouts[] = $callout instanceof CalloutInterface ? (string) $callout->getCode() : $callout; + $this->callouts[] = $callout instanceof CalloutInterface ? [(string) $callout->getCode(), $callout->getVersion()] : [$callout, null]; } } } diff --git a/src/Message/Handler/AssignCalloutHandler.php b/src/Message/Handler/AssignCalloutHandler.php deleted file mode 100644 index 2228d13..0000000 --- a/src/Message/Handler/AssignCalloutHandler.php +++ /dev/null @@ -1,32 +0,0 @@ -calloutRepository->findOneByCode($message->callout); - if (null === $callout) { - throw new UnrecoverableMessageHandlingException(sprintf('Callout with code "%s" does not exist', $message->callout)); - } - - if (null !== $message->version && $message->version !== $callout->getVersion()) { - // this means the callout has been updated since the message was sent - throw new UnrecoverableMessageHandlingException(sprintf('Callout with id %s has version %s, but version %s was expected', $message->callout, (string) $callout->getVersion(), $message->version)); - } - - if (!$callout->isEnabled()) { - throw new UnrecoverableMessageHandlingException(sprintf('Callout with id %s is not enabled', $message->callout)); - } - - $callouts = [$callout]; - - $this->assign(callouts: $callouts); - } -} diff --git a/src/Message/Handler/AssignCalloutsHandler.php b/src/Message/Handler/AssignCalloutsHandler.php index c819eb5..0130a11 100644 --- a/src/Message/Handler/AssignCalloutsHandler.php +++ b/src/Message/Handler/AssignCalloutsHandler.php @@ -11,8 +11,28 @@ final class AssignCalloutsHandler extends AbstractAssignCalloutsHandler public function __invoke(AssignCallouts $message): void { $callouts = []; + if ([] !== $message->callouts) { - $callouts = $this->calloutRepository->findEnabled($message->callouts); + foreach ($message->callouts as $calloutShape) { + $callout = $this->calloutRepository->findOneByCode($calloutShape[0]); + if (null === $callout) { + continue; + } + + if (null !== $calloutShape[1] && $calloutShape[1] !== $callout->getVersion()) { + continue; + } + + if (!$callout->isEnabled()) { + continue; + } + + $callouts[] = $callout; + } + + if ([] === $callouts) { + return; + } } $this->assign(callouts: $callouts); diff --git a/src/Resources/config/services/event_subscriber.xml b/src/Resources/config/services/event_subscriber.xml index ad3f27c..9c71596 100644 --- a/src/Resources/config/services/event_subscriber.xml +++ b/src/Resources/config/services/event_subscriber.xml @@ -12,6 +12,7 @@ + %setono_sylius_callout.assignment.processing_delay% diff --git a/src/Resources/config/services/message.xml b/src/Resources/config/services/message.xml index 3af1892..bf6239e 100644 --- a/src/Resources/config/services/message.xml +++ b/src/Resources/config/services/message.xml @@ -13,12 +13,6 @@ %sylius.model.product.class% - - - -