mirror of
https://github.com/Sylius/Sylius.git
synced 2026-07-14 09:02:12 +00:00
[API] Decorate base write state processor to catch messenger exceptions
This commit is contained in:
parent
b9d2bac821
commit
517affc078
7 changed files with 92 additions and 129 deletions
|
|
@ -575,31 +575,6 @@ parameters:
|
|||
count: 1
|
||||
path: src/Sylius/Bundle/ApiBundle/DataPersister/CountryDataPersister.php
|
||||
|
||||
-
|
||||
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\MessengerDataPersister\\:\\:persist\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
|
||||
count: 1
|
||||
path: src/Sylius/Bundle/ApiBundle/DataPersister/MessengerDataPersister.php
|
||||
|
||||
-
|
||||
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\MessengerDataPersister\\:\\:remove\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: src/Sylius/Bundle/ApiBundle/DataPersister/MessengerDataPersister.php
|
||||
|
||||
-
|
||||
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\MessengerDataPersister\\:\\:remove\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
|
||||
count: 1
|
||||
path: src/Sylius/Bundle/ApiBundle/DataPersister/MessengerDataPersister.php
|
||||
|
||||
-
|
||||
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\MessengerDataPersister\\:\\:supports\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
|
||||
count: 1
|
||||
path: src/Sylius/Bundle/ApiBundle/DataPersister/MessengerDataPersister.php
|
||||
|
||||
-
|
||||
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\MessengerDataPersister\\:\\:supports\\(\\) has parameter \\$data with no type specified\\.$#"
|
||||
count: 1
|
||||
path: src/Sylius/Bundle/ApiBundle/DataPersister/MessengerDataPersister.php
|
||||
|
||||
-
|
||||
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ProductDataPersister\\:\\:persist\\(\\) has parameter \\$data with no type specified\\.$#"
|
||||
count: 1
|
||||
|
|
|
|||
|
|
@ -18,11 +18,6 @@
|
|||
<services>
|
||||
<defaults public="true" />
|
||||
|
||||
<service id="Sylius\Bundle\ApiBundle\DataPersister\MessengerDataPersister">
|
||||
<argument type="service" id="api_platform.messenger.data_persister" />
|
||||
<tag name="api_platform.data_persister" />
|
||||
</service>
|
||||
|
||||
<service id="Sylius\Bundle\ApiBundle\DataPersister\CountryDataPersister">
|
||||
<argument type="service" id="api_platform.doctrine.orm.data_persister" />
|
||||
<argument type="service" id="Sylius\Component\Addressing\Checker\CountryProvincesDeletionCheckerInterface" />
|
||||
|
|
|
|||
|
|
@ -112,5 +112,14 @@
|
|||
<argument type="service" id="sylius_api.creator.taxon_image" />
|
||||
<tag name="api_platform.state_processor" />
|
||||
</service>
|
||||
|
||||
<service
|
||||
id="sylius_api.state_processor.shop.messenger.persist"
|
||||
class="Sylius\Bundle\ApiBundle\StateProcessor\Common\MessengerPersistProcessor"
|
||||
decorates="api_platform.state_processor.write"
|
||||
>
|
||||
<argument type="service" id=".inner" />
|
||||
<tag name="api_platform.state_processor" />
|
||||
</service>
|
||||
</services>
|
||||
</container>
|
||||
|
|
|
|||
|
|
@ -19,19 +19,19 @@ use ApiPlatform\State\ProcessorInterface;
|
|||
use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException;
|
||||
use Sylius\Bundle\ApiBundle\Exception\PaymentMethodCannotBeRemoved;
|
||||
use Sylius\Component\Core\Model\PaymentMethodInterface;
|
||||
use Sylius\Component\Core\Model\ProductInterface;
|
||||
use Webmozart\Assert\Assert;
|
||||
|
||||
/** @implements ProcessorInterface<PaymentMethodInterface> */
|
||||
/** @implements ProcessorInterface<PaymentMethodInterface, void> */
|
||||
final readonly class RemoveProcessor implements ProcessorInterface
|
||||
{
|
||||
/** @param ProcessorInterface<PaymentMethodInterface, void> $removeProcessor */
|
||||
public function __construct(
|
||||
private ProcessorInterface $removeProcessor,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ProductInterface $data
|
||||
* @param PaymentMethodInterface $data
|
||||
*/
|
||||
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): void
|
||||
{
|
||||
|
|
|
|||
|
|
@ -11,27 +11,26 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Bundle\ApiBundle\DataPersister;
|
||||
namespace Sylius\Bundle\ApiBundle\StateProcessor\Common;
|
||||
|
||||
use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface;
|
||||
use ApiPlatform\Metadata\Operation;
|
||||
use ApiPlatform\State\ProcessorInterface;
|
||||
use Symfony\Component\Messenger\Exception\DelayedMessageHandlingException;
|
||||
use Symfony\Component\Messenger\Exception\HandlerFailedException;
|
||||
|
||||
final class MessengerDataPersister implements ContextAwareDataPersisterInterface
|
||||
/** @implements ProcessorInterface<object, mixed> */
|
||||
final readonly class MessengerPersistProcessor implements ProcessorInterface
|
||||
{
|
||||
public function __construct(private ContextAwareDataPersisterInterface $decoratedDataPersister)
|
||||
/** @param ProcessorInterface<object, mixed> $decoratedProcessor */
|
||||
public function __construct(private ProcessorInterface $decoratedProcessor)
|
||||
{
|
||||
}
|
||||
|
||||
public function supports($data, array $context = []): bool
|
||||
{
|
||||
return $this->decoratedDataPersister->supports($data, $context);
|
||||
}
|
||||
|
||||
public function persist($data, array $context = [])
|
||||
/** @throws \Throwable */
|
||||
public function process($data, Operation $operation, array $uriVariables = [], array $context = [])
|
||||
{
|
||||
try {
|
||||
return $this->decoratedDataPersister->persist($data, $context);
|
||||
return $this->decoratedProcessor->process($data, $operation, $uriVariables, $context);
|
||||
} catch (DelayedMessageHandlingException|HandlerFailedException $e) {
|
||||
while ($e instanceof DelayedMessageHandlingException) {
|
||||
/** @var \Throwable $e */
|
||||
|
|
@ -45,9 +44,4 @@ final class MessengerDataPersister implements ContextAwareDataPersisterInterface
|
|||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
public function remove($data, array $context = [])
|
||||
{
|
||||
$this->decoratedDataPersister->remove($data, $context);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Sylius Sp. z o.o.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace spec\Sylius\Bundle\ApiBundle\DataPersister;
|
||||
|
||||
use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface;
|
||||
use PhpSpec\ObjectBehavior;
|
||||
use Prophecy\Argument;
|
||||
use Sylius\Bundle\ApiBundle\Command\Checkout\CompleteOrder;
|
||||
use Symfony\Component\HttpKernel\Kernel;
|
||||
use Symfony\Component\Messenger\Envelope;
|
||||
use Symfony\Component\Messenger\Exception\DelayedMessageHandlingException;
|
||||
use Symfony\Component\Messenger\Exception\HandlerFailedException;
|
||||
|
||||
final class MessengerDataPersisterSpec extends ObjectBehavior
|
||||
{
|
||||
function let(ContextAwareDataPersisterInterface $decoratedDataPersister)
|
||||
{
|
||||
$this->beConstructedWith($decoratedDataPersister);
|
||||
}
|
||||
|
||||
function it_calls_supports_method_from_decorated_data_presister(
|
||||
ContextAwareDataPersisterInterface $decoratedDataPersister,
|
||||
): void {
|
||||
$decoratedDataPersister->supports(Argument::any(), [])->shouldBeCalled();
|
||||
|
||||
$this->supports(Argument::any(), []);
|
||||
}
|
||||
|
||||
function it_unwraps_delayed_message_handling_exception(ContextAwareDataPersisterInterface $decoratedDataPersister): void
|
||||
{
|
||||
$completeOrder = new CompleteOrder('ThankYou');
|
||||
$completeOrder->setOrderTokenValue('ORDERTOKEN');
|
||||
$envelope = new Envelope($completeOrder);
|
||||
|
||||
if (version_compare(Kernel::VERSION, '6.3.5', '>=')) {
|
||||
$exception = new DelayedMessageHandlingException([new \RuntimeException('Delayed message exception')], $envelope);
|
||||
} else {
|
||||
$exception = new DelayedMessageHandlingException([new \RuntimeException('Delayed message exception')]);
|
||||
}
|
||||
|
||||
$decoratedDataPersister->persist($envelope, [])->willThrow($exception);
|
||||
|
||||
$this->shouldThrow(new \RuntimeException('Delayed message exception'))->during('persist', [$envelope, []]);
|
||||
}
|
||||
|
||||
function it_unwraps_handler_failed_exception(ContextAwareDataPersisterInterface $decoratedDataPersister): void
|
||||
{
|
||||
$completeOrder = new CompleteOrder('ThankYou');
|
||||
$completeOrder->setOrderTokenValue('ORDERTOKEN');
|
||||
$envelope = new Envelope($completeOrder);
|
||||
|
||||
$decoratedDataPersister->persist($envelope, [])->willThrow(
|
||||
new HandlerFailedException(
|
||||
$envelope,
|
||||
[new \RuntimeException('Delayed message exception')],
|
||||
),
|
||||
);
|
||||
|
||||
$this->shouldThrow(new \RuntimeException('Delayed message exception'))->during('persist', [$envelope, []]);
|
||||
}
|
||||
|
||||
function it_calls_remove_method_from_decorated_data_presister(
|
||||
ContextAwareDataPersisterInterface $decoratedDataPersister,
|
||||
): void {
|
||||
$decoratedDataPersister->remove(Argument::any(), [])->shouldBeCalled();
|
||||
|
||||
$this->remove(Argument::any(), []);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Sylius Sp. z o.o.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace spec\Sylius\Bundle\ApiBundle\StateProcessor\Common;
|
||||
|
||||
use ApiPlatform\Metadata\Post;
|
||||
use ApiPlatform\State\ProcessorInterface;
|
||||
use PhpSpec\ObjectBehavior;
|
||||
use Sylius\Bundle\ApiBundle\Command\Checkout\CompleteOrder;
|
||||
use Symfony\Component\Messenger\Envelope;
|
||||
use Symfony\Component\Messenger\Exception\DelayedMessageHandlingException;
|
||||
use Symfony\Component\Messenger\Exception\HandlerFailedException;
|
||||
|
||||
final class MessengerPersistProcessorSpec extends ObjectBehavior
|
||||
{
|
||||
function let(ProcessorInterface $decoratedProcessor): void
|
||||
{
|
||||
$this->beConstructedWith($decoratedProcessor);
|
||||
}
|
||||
|
||||
function it_implements_processor_interface(): void
|
||||
{
|
||||
$this->shouldImplement(ProcessorInterface::class);
|
||||
}
|
||||
|
||||
function it_unwraps_delayed_message_handling_exception(ProcessorInterface $decoratedProcessor): void
|
||||
{
|
||||
$command = new CompleteOrder('ThankYou', 'token');
|
||||
$envelope = new Envelope($command);
|
||||
$operation = new Post();
|
||||
|
||||
$exception = new DelayedMessageHandlingException([new \RuntimeException('Delayed message exception')], $envelope);
|
||||
|
||||
$decoratedProcessor->process($envelope, $operation, [], [])->willThrow($exception);
|
||||
|
||||
$this
|
||||
->shouldThrow(new \RuntimeException('Delayed message exception'))
|
||||
->during('process', [$envelope, $operation, [], []])
|
||||
;
|
||||
}
|
||||
|
||||
function it_unwraps_handler_failed_exception(ProcessorInterface $decoratedProcessor): void
|
||||
{
|
||||
$command = new CompleteOrder('ThankYou', 'token');
|
||||
$envelope = new Envelope($command);
|
||||
$operation = new Post();
|
||||
|
||||
$decoratedProcessor->process($envelope, $operation, [], [])->willThrow(
|
||||
new HandlerFailedException(
|
||||
$envelope,
|
||||
[new \RuntimeException('Delayed message exception')],
|
||||
),
|
||||
);
|
||||
|
||||
$this
|
||||
->shouldThrow(new \RuntimeException('Delayed message exception'))
|
||||
->during('process', [$envelope, $operation, [], []])
|
||||
;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue