我使用的是API平台3.1。我需要在创建后生成某些实体的缩略图。我想使用 Symfony Messenger 来触发此操作并异步执行,因为可能需要一些时间来处理,但我希望立即保存实体。
当资源同时使用信使和自定义处理器(以保存实体)时,如果使用
messenger=true
,则不会创建消息,或者如果使用 messenger='input'
,则不会调用处理器。
如何重现
#[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
API 平台文档在Symfony Messenger Integration中提到:
注意:在 Doctrine 实体中使用
ApiResource 属性时,不会调用 Doctrine 处理器。如果你希望 Doctrine Processor 被调用,你应该装饰一个内置的状态处理器并实现你自己的逻辑。messenger=true
在 GitHub 问题上建议我应该装饰消息处理程序以保存实体。但是,我需要立即保存我的实体,而不是等待它被 messenger:consume
工作人员消耗。
解耦实体创建和缩略图生成: 不要直接从实体创建过程触发缩略图生成,而是考虑将其解耦。创建实体后,立即保存实体并使用 Symfony Messenger 发送一条消息,指示需要为新创建的实体生成缩略图。
使用消息处理程序生成缩略图: 创建一个单独的消息处理程序,用于侦听实体创建过程分派的缩略图生成消息。该处理程序应负责生成缩略图并使用生成的缩略图信息更新实体。它还可以在更新实体后立即持久化和刷新实体。
实体处理:
在 MyEntityProcessor
类中,仅专注于处理实体并避免处理缩略图生成逻辑。这样,您可以保持关注点分离并保持逻辑清晰。
MyEntity
实例后,
MyEntityProcessor
会立即保存它来处理它。
MyEntityHandler
消息处理程序接收消息,生成缩略图,更新实体,然后立即保留并将实体刷新到数据库。
请记住在
messenger.yaml
中正确配置消息处理程序和路由,以确保缩略图生成消息由适当的消息处理程序处理 (
MyEntityHandler
)。此方法需要对代码进行一些重组,但应该可以帮助您实现使用 Symfony Messenger 和 API 平台立即保存实体和异步缩略图生成的目标。