Компонент Symfony Messenger теряет соединение и дублирует сохранение записей
Настраиваю компонент Messenger в Symfony 4.4.
Схема работы такая: отправляю в контролер json (далее преобразую json в объект) -> затем отправляю объект в очередь(в качестве транспорта использую доктрин) -> далее хендлер вычитывает сообщение и сохраняет объект в БД. Проблема: при асинхронной обработки сообщений, сохраняется несколько дублей объекта в БД + хенделер пишет об ошибках в соединении (см скрин).
Нашел описание этой проблемы на symfony casts, там предлагают при сохранении объекта в БД использовать функцию flush, без предварительного использовании функции persist. При таком подходе сохранение в БД не происходит.
При синхронном сохранении, такой ошибки не происходит.
Кто-н знает решение этой проблемы?
ApiController:
/**
* @Route("/api/task")
* @param Request $request
* @param MessageBusInterface $messageBus
* @return Response
*/
public function createTask(Request $request, MessageBusInterface $messageBus): Response
{
try {
$serializer = SerializerBuilder::create()->build();
$this->inputCalculatorTaskDto = $serializer->deserialize($request->getContent(),
InputCalculatorTaskDto::class,
'json');
$this->inputCalculatorTaskDto
->setTaskGuid(Uuid::uuid4())
->setServiceName(ServicesListEnum::SERVICE_CALULATOR)
->setTaskName(TaskListEnum::CALCULATE_ORDER_PRICE)
->setCreatedAt(DateTime::createFromFormat('U.u', microtime(TRUE)));
$calculatorTaskMessage = new CalculatorTaskMessage($this->inputCalculatorTaskDto);
$messageBus->dispatch($calculatorTaskMessage);
$this->logger->info('done ' . $this->inputCalculatorTaskDto->getTaskGuid());
return new Response('done');
} catch (\Throwable $t) {
$this->logger->error($t->getMessage());
return new Response('error ' . $t->getMessage());
}
}
Messanger:
class CalculatorTaskMessage
{
/**
* @var InputCalculatorTaskDto
*/
private InputCalculatorTaskDto $inputCalculatorTaskDto;
public function __construct(InputCalculatorTaskDto $inputCalculatorTaskDto)
{
$this->inputCalculatorTaskDto = $inputCalculatorTaskDto;
}
/**
* @return InputCalculatorTaskDto
*/
public function getInputCalculatorTaskDto(): InputCalculatorTaskDto
{
return $this->inputCalculatorTaskDto;
}
}
MessageHandler
class CalculatorNewTaskCreatorHandler implements MessageHandlerInterface { public InputCalculatorTaskDtoToTaskEntityImpl $inputCalculatorTaskDtoToTaskEntity; public EntityManagerInterface $entityManager; public TasksRepository $tasksRepository; private CalculatorTaskProducer $calculatorTaskProducer;
/**
* CalculatorTaskCreatorHandler constructor.
* @param EntityManagerInterface $entityManager
* @param TasksRepository $tasksRepository
* @param CalculatorTaskProducer $calculatorTaskProducer
*/
public function __construct(EntityManagerInterface $entityManager,
TasksRepository $tasksRepository,
CalculatorTaskProducer $calculatorTaskProducer)
{
$this->inputCalculatorTaskDtoToTaskEntity = new InputCalculatorTaskDtoToTaskEntityImpl();
$this->entityManager = $entityManager;
$this->tasksRepository = $tasksRepository;
$this->calculatorTaskProducer = $calculatorTaskProducer;
}
public function __invoke(CalculatorTaskMessage $calculatorTaskMessage)
{
$inputCalculatorTaskDto = $calculatorTaskMessage->getInputCalculatorTaskDto();
$tasks = $this->inputCalculatorTaskDtoToTaskEntity->map($inputCalculatorTaskDto);
$this->entityManager->persist($tasks);
$this->entityManager->flush();
$this->calculatorTaskProducer->sendMessage($inputCalculatorTaskDto);
}
}
Ответы (1 шт):
Проблема в консьюмере rabbit. Как только была добавлена обработка ошибок для консьюмера, дублирование объектов прекратилось
