Доктрина: Как не допустить, чтобы транзакция превратилась в «только откат» из-за перехваченного исключения? - PullRequest
0 голосов
/ 24 января 2019

Ошибка удаления объекта из-за исключения в обработчике события postRemove.Даже если исключение обнаружено, удаление завершается неудачно, поскольку транзакция больше не может быть зафиксирована. Как решить эту проблему?

Полная история:

Мне нужно отслеживать некоторые удаленные объекты в веб-службе на основе Symfony 3.4используя Doctrine.

Для этого я создал EventSubscriber, который обрабатывает событие postRemove, чтобы проверить, нужно ли регистрировать удаленную сущность.В этом случае UUID сущности хранится в таблице DeleteLog этой БД.

Это работает нормально, но в редких случаях сохранение значения DeleteLogEntry завершается неудачно, так как уже существует запись в журнале для данногоUUID, который должен быть уникальным.

Источник этой проблемы - какой-то сторонний код, который я не могу изменить самостоятельно.В качестве временного решения попытался поймать UniqueConstraintViolationException.Это не решает проблему, поскольку теперь я получаю ConnectionException

Не удалось выполнить транзакцию, поскольку транзакция была помечена только для отката.

Возможно ли этоЧтобы решить эту дилемму?

Конечно, я мог бы проверить, существует ли DeleteLogEntry с данным UUID, прежде чем создавать новый.Но поскольку эта проблема возникает только в редких случаях, проверка будет отрицательной в большинстве случаев.Конечно, выполнение проверки в любом случае не приводит к катастрофическим последствиям для производительности, но просто кажется не лучшим решением.

Можно ли перехватить исключение и не допустить, чтобы транзакция была помечена только как откат?

1 Ответ

0 голосов
/ 25 января 2019

Нет, удержать транзакцию от пометки невозможно.

Doctine запускает вложенную транзакцию для postRemove и, если она не проходит, других транзакций нетдолжно быть совершено.Пометка транзакции только для отката (и даже закрытие менеджера сущностей) является ожидаемым поведением в таком сценарии, поскольку у Doctrine нет другого способа обеспечить согласованность, поскольку нет поддержки для реальных вложенных транзакций.

Если производительность не является проблемой, тогда проверка на DeleteLogEntry является хорошим вариантом.

Другие возможные обходные пути:

  • где-то храните идентификатор (Redis, Memcache, файл,и т. д.) временно и обновите DeleteLogEntry позже, после первоначального удаления
  • используйте отдельный менеджер сущностей / соединение для обновления DeleteLogEntry
  • удаления Unique Constrain и используйте фоновую задачу для просмотрадля дубликатов
...