Race Condition при включенной автогенерации гидраторов Doctrine ORM

// Апрель 27th, 2016 // Doctrine 2

Как-то раз столкнулись с очень странной ошибкой. Периодически на продакшене вылетал то один то другой запрос с ошибкой PHP Fatal error: Class ‘Hydrators\VendorDefaultBundleDocumentUserHydrator’ not found in /web/vendor/doctrine/mongodb-odm/lib/Doctrine/ODM/MongoDB/Hydrator/HydratorFactory.php.

Проблема

Что было очень странно, так как файл гидратора спокойно лежал по этому пути. При проверке на  develop-машине подобный баг не воспроизводился, только под нагрузкой. Довольно долго гадали, в чём там дело, пока наш доблестный админ не обратил внимание на время изменение файлов гидраторов. Оно постоянно менялось на текущее. А это значит, что гидраторы постоянно перезаписывались. Не буду говорить, как это фигово с точки зрения производительности. Но кроме того, при наличии двух одновременных запросов, первый из них начинал генерировать гидратор, а второй не находил файл и падал. Главное условие одновременность запросов.

Решение

Солюшен прост. Надо сделать так, чтобы на боевом сервере прокси классы и гидраторы генерировались один раз при деплое, а потом не перегенерялись при запросах. Примерно так:

$autoGenerateDoctrine = (APPLICATION_ENV == 'production')? false : true;

// Для Doctrine 2 ORM
$config = new \Doctrine\ORM\Configuration();
$config->setAutoGenerateProxyClasses($autoGenerateDoctrine);
$connectionOptions = array(...);
$evm = new \Doctrine\Common\EventManager();
$em = \Doctrine\ORM\EntityManager::create($connectionOptions, $config, $evm);

// Для Doctrine 2 ODM
$config = new \Doctrine\ODM\MongoDB\Configuration();
$config->setAutoGenerateProxyClasses($autoGenerateDoctrine);
$config->setAutoGenerateHydratorClasses($autoGenerateDoctrine);
$mongoConfigOptions = ...;
$dm = \Doctrine\ODM\MongoDB\DocumentManager::create(new \Doctrine\MongoDB\Connection($dsn, $mongoConfigOptions), $config);

После этого гидраторы перестали перегенеряться и ошибка пропала.

Share

Спасибо!


Если вам помогла статья, или вы хотите поддержать мои исследования и блог - вот лучший способ сделать это:


Комментировать