Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception "Your hydrator directory must be writable." for writable directory #2520

Open
maximzasorin opened this issue Apr 1, 2023 · 3 comments

Comments

@maximzasorin
Copy link

Bug Report

Q A
BC Break no
Version 2.2.2

Summary

Exception "Your hydrator directory must be writable." occurs for a directory that definitely is writable. The exception occurs from time to time when a directory needs to be created and looks like a race condition.

The code that throws the exception is similar to this:
https://github.com/kalessil/phpinspectionsea/blob/master/docs/probable-bugs.md#mkdir-race-condition

Current behavior

I got the following exception for a directory that definitely was writable:

Your hydrator directory must be writable.
#0 /var/www/releases/20230328170455/backend/vendor/doctrine/mongodb-odm/lib/Doctrine/ODM/MongoDB/Hydrator/HydratorFactory.php(437): Doctrine\ODM\MongoDB\Hydrator\HydratorException::hydratorDirectoryNotWritable()
#1 /var/www/releases/20230328170455/backend/vendor/doctrine/mongodb-odm/lib/Doctrine/ODM/MongoDB/Hydrator/HydratorFactory.php(143): Doctrine\ODM\MongoDB\Hydrator\HydratorFactory->generateHydratorClass()
#2 /var/www/releases/20230328170455/backend/vendor/doctrine/mongodb-odm/lib/Doctrine/ODM/MongoDB/Hydrator/HydratorFactory.php(496): Doctrine\ODM\MongoDB\Hydrator\HydratorFactory->getHydratorFor()
#3 /var/www/releases/20230328170455/backend/vendor/doctrine/mongodb-odm/lib/Doctrine/ODM/MongoDB/UnitOfWork.php(2690): Doctrine\ODM\MongoDB\Hydrator\HydratorFactory->hydrate()
#4 /var/www/releases/20230328170455/backend/vendor/doctrine/mongodb-odm/lib/Doctrine/ODM/MongoDB/Persisters/DocumentPersister.php(635): Doctrine\ODM\MongoDB\UnitOfWork->getOrCreateDocument()
#5 /var/www/releases/20230328170455/backend/vendor/doctrine/mongodb-odm/lib/Doctrine/ODM/MongoDB/Persisters/DocumentPersister.php(504): Doctrine\ODM\MongoDB\Persisters\DocumentPersister->createDocument()
#6 /var/www/releases/20230328170455/backend/vendor/doctrine/mongodb-odm/lib/Doctrine/ODM/MongoDB/Repository/DocumentRepository.php(172): Doctrine\ODM\MongoDB\Persisters\DocumentPersister->load()
...

How to reproduce

  1. I have a web app where I use doctrine/mongodb-odm
  2. I have a writable directory /some/path/temp
  3. The configuration of the DocumentManager looks like this:
    $config = new Configuration;
    $config->setProxyDir('/some/path/temp/doctrine/proxy');
    $config->setHydratorDir('/some/path/temp/doctrine/hydrator');
    // ...
    DocumentManager::create(null, $config)
  4. I originally got an exception on the production server when I was doing the deployment of the new version. At the moment I switched the app to the new directory /some/path/temp, I got an exception Your hydrator directory must be writable.
  5. Later I was able to reproduce this in my stage environment. I first remove /some/path/temp/doctrine directory and then run: ab -c 50 -n 50 https://.... After several tries I get an exception "Your hydrator directory must be writable." in the app logs.

Expected behavior

The directory is created without any exceptions.

@malarzm
Copy link
Member

malarzm commented Apr 3, 2023

The easiest solution is to avoid this race condition altogether and have the folders created before ODM tries to do so itself. Is that an option? There also was a schoold of pre-generating all hydrators/proxies before during deployment :)

@maximzasorin
Copy link
Author

Yes, that's an option for me, thanks for the tip!

If I generate hydrators and proxies when I build the app before the deployment, can I leave the directories for them read-only in that case? The application code and all dependencies are not changed after the build. Build and deploy are performed on different machines.

@malarzm
Copy link
Member

malarzm commented Apr 4, 2023

Yes, the code generation branch is executed only if the file does not exist:

case Configuration::AUTOGENERATE_FILE_NOT_EXISTS:
if (! file_exists($fileName)) {
$this->generateHydratorClass($class, $hydratorClassName, $fileName);
}
require $fileName;

You may also consider using Configuration::AUTOGENERATE_NEVER mode which will just fail if the file was not generated earlier.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants