php - 如果在 APIPlatform 3.1 中的同一资源上使用处理器,Messenger 将无法工作

标签 php symfony api-platform.com

我正在使用 API 平台 3.1。我需要在创建后生成某些实体的缩略图。我想使用Symfony Messenger触发此操作并异步执行,因为可能需要一些时间来处理,但我希望立即保存实体。

当资源同时使用信使和自定义处理器(以保存实体)时,如果使用 messenger=true 则不会创建消息,或者如果使用 则不会调用处理器>messenger='输入'

如何重现

#[ORM\Entity]
#[ApiResource(
    operations: [
        new Post(
            processor: MyEntityProcessor::class,
            messenger: 'input',
            deserialize: false, 
        )
    ]
)]
class MyEntity
{
}
final class MyEntityProcessor implements ProcessorInterface
{
    public function __construct(private ProcessorInterface $persistProcessor)
    {
    }

    public function process($data, Operation $operation, array $uriVariables = [], array $context = [])
    {
        $result = $this->persistProcessor->process($data, $operation, $uriVariables, $context);
        return $result;
    }
}
final class MyEntityHandler implements MessageHandlerInterface
{
    public function __construct(private EntityManagerInterface $entityManager)
    {
    }

    public function __invoke(MyEntity $myEntity)
    {
        // my long running function

        $this->entityManager->persist($myEntity);
        $this->entityManager->flush();
    }
}

services.yaml

services:
    App\State\MyEntityProcessor:
        bind:
            $persistProcessor: '@api_platform.doctrine.orm.state.item_provider'

messenger.yaml

framework:
    messenger:
        transports:
            async: 'doctrine://default'

        routing:
            'App\Entity\MyEntity': async

Symfony Messenger Integration 中提到的 API 平台文档:

Note: when using messenger=true ApiResource attribute in a Doctrine entity, the Doctrine Processor is not called. If you want the Doctrine Processor to be called, you should decorate a built-in state processor and implement your own logic.

这是 suggested on a GitHub issue我应该装饰消息处理程序以保存实体。但是,我需要立即保存我的实体,而不是等待它被 messenger:consume 工作线程消耗。

最佳答案

一个可能的解决方案是在第一次持久化实体后在您的处理器中分派(dispatch)消息。也许不是那么干净,因为它需要更多代码,但是您可以更好地控制 Message 的处理方式和时间。此外,您还可以使用 DelayStamp 来发送它。 .

在你的处理器中我会 dispatch the Message像这样:

final class MyEntityProcessor implements ProcessorInterface
{
    
    public function __construct(
        private ProcessorInterface $persistProcessor,
        private MessageBusInterface $bus,
    ) {
    }

    public function process($data, Operation $operation, array $uriVariables = [], array $context = [])
    {
        $result = $this->persistProcessor->process($data, $operation, $uriVariables, $context);

        // $data should be your MyEntity Entity.
        $this->bus->dispatch(new GenerateThumbMessage($data), [
            // wait 5 seconds before processing
            new DelayStamp(5000),
        ]);
        
        return $result;
    }
}

Create the Message App\Message\GenerateThumbMessage.php:

class GenerateThumbMessage
{

    public function __construct(private readonly MyEntity $myEntity) {}

    public function getMyEntity(): MyEntity
    {
        return $this->myEntity;
    }

}

然后create your MessageHandler App\Message\GenerateThumbMessageHandler.php:

final class GenerateThumbMessageHandler implements MessageHandlerInterface
{
    public function __construct(private EntityManagerInterface $em) {}

    public function __invoke(GenerateThumbMessage $generateThumbMessage)
    {
        $myEntity = $generateThumbMessage->getMyEntity();
        
        // your long running function to generate a thumbnail

        $this->em->persist($myEntity);
        $this->em->flush();
    }
}

您的 messenger.yaml 配置应如下所示:

framework:
    messenger:
        transports:
            async: 'doctrine://default'

        routing:
            'App\Message\GenerateThumbMessage': async

在配置中,您没有使用实体,而是将消息配置为异步处理。

类似的解决方案可以在 API Platform documentation 中找到

关于php - 如果在 APIPlatform 3.1 中的同一资源上使用处理器,Messenger 将无法工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76972957/

相关文章:

javascript - jQuery AJAX 请求未收到响应

php - 装饰服务的循环引用问题

php - 自定义集合操作和IRI转换问题

symfony - 如何在 symfony 中使用 api-platform 来编辑发布数据?

php - 什么是 Doctrine hydration 作用?

php - 查询运行次数与刷新次数相同

javascript - 检查用户是否在线使用 Firebase 制作的聊天应用程序

php - Symfony2 - 如何将嵌套记录和递归函数实现到实体字段或 Twig 布局中?

php - Symfony2 : Undefined Function "ftp_ssl_connect"

php - 使用 SQS 在 PHP (Symfony2) 上发送数千个通知