Doctrinebundle: Force lazy loading listeners during container compilation

Created on 23 May 2018  Â·  10Comments  Â·  Source: doctrine/DoctrineBundle

Is there a way to always use lazy loaded listeners during the container compilation phase? It will prevent lots of errors caused by trying to instantiate the listeners and also recursively their parent dependencies (which is of course really bad).

For example:

/srv/sylius # bin/console cache:clear -vvv

In CurlFactory.php line 185:

  [GuzzleHttp\Exception\ConnectException]
  cURL error 6: Could not resolve host: auth (see http://curl.haxx.se/libcurl
  /c/libcurl-errors.html)


Exception trace:
 GuzzleHttp\Handler\CurlFactory::createRejection() at /srv/sylius/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php:149
 GuzzleHttp\Handler\CurlFactory::finishError() at /srv/sylius/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php:102
 GuzzleHttp\Handler\CurlFactory::finish() at /srv/sylius/vendor/guzzlehttp/guzzle/src/Handler/CurlHandler.php:43
 GuzzleHttp\Handler\CurlHandler->__invoke() at /srv/sylius/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php:28
 GuzzleHttp\Handler\Proxy::GuzzleHttp\Handler\{closure}() at /srv/sylius/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php:51
 GuzzleHttp\Handler\Proxy::GuzzleHttp\Handler\{closure}() at /srv/sylius/vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php:66
 GuzzleHttp\PrepareBodyMiddleware->__invoke() at /srv/sylius/vendor/guzzlehttp/guzzle/src/Middleware.php:30
 GuzzleHttp\Middleware::GuzzleHttp\{closure}() at /srv/sylius/vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php:70
 GuzzleHttp\RedirectMiddleware->__invoke() at /srv/sylius/vendor/guzzlehttp/guzzle/src/Middleware.php:60
 GuzzleHttp\Middleware::GuzzleHttp\{closure}() at /srv/sylius/vendor/guzzlehttp/guzzle/src/HandlerStack.php:67
 GuzzleHttp\HandlerStack->__invoke() at /srv/sylius/vendor/guzzlehttp/guzzle/src/Client.php:277
 GuzzleHttp\Client->transfer() at /srv/sylius/vendor/guzzlehttp/guzzle/src/Client.php:125
 GuzzleHttp\Client->requestAsync() at /srv/sylius/vendor/guzzlehttp/guzzle/src/Client.php:131
 GuzzleHttp\Client->request() at /srv/sylius/vendor/php-opencloud/openstack/src/Common/Api/OperatorTrait.php:118
 OpenStack\Common\Resource\OperatorResource->sendRequest() at /srv/sylius/vendor/php-opencloud/openstack/src/Common/Api/OperatorTrait.php:126
 OpenStack\Common\Resource\OperatorResource->execute() at /srv/sylius/vendor/php-opencloud/openstack/src/Identity/v3/Models/Token.php:124
 OpenStack\Identity\v3\Models\Token->create() at /srv/sylius/vendor/php-opencloud/openstack/src/Identity/v3/Service.php:84
 OpenStack\Identity\v3\Service->generateToken() at /srv/sylius/vendor/php-opencloud/openstack/src/Identity/v3/Service.php:42
 OpenStack\Identity\v3\Service->authenticate() at /srv/sylius/vendor/php-opencloud/openstack/src/Common/Service/Builder.php:96
 OpenStack\Common\Service\Builder->stockHttpClient() at /srv/sylius/vendor/php-opencloud/openstack/src/Common/Service/Builder.php:82
 OpenStack\Common\Service\Builder->createService() at /srv/sylius/vendor/php-opencloud/openstack/src/OpenStack.php:174
 OpenStack\OpenStack->objectStoreV1() at /srv/sylius/var/cache/dev/ContainerK6cuif2/appDevDebugProjectContainer.php:5599
 ContainerK6cuif2\appDevDebugProjectContainer->getGaufrette_SyliusImageAdapterService() at /srv/sylius/var/cache/dev/ContainerK6cuif2/appDevDebugProjectContainer.php:4012
 ContainerK6cuif2\appDevDebugProjectContainer->getGaufrette_SyliusImageFilesystemService() at /srv/sylius/var/cache/dev/ContainerK6cuif2/appDevDebugProjectContainer.php:4052
 ContainerK6cuif2\appDevDebugProjectContainer->getKnpGaufrette_FilesystemMapService() at /srv/sylius/var/cache/dev/ContainerK6cuif2/appDevDebugProjectContainer.php:7149
 ContainerK6cuif2\appDevDebugProjectContainer->getSylius_ImageUploaderService() at /srv/sylius/var/cache/dev/ContainerK6cuif2/appDevDebugProjectContainer.php:7179
 ContainerK6cuif2\appDevDebugProjectContainer->getSylius_Listener_ImagesRemoveService() at /srv/sylius/var/cache/dev/ContainerK6cuif2/appDevDebugProjectContainer.php:3863
 ContainerK6cuif2\appDevDebugProjectContainer->getDoctrine_Dbal_DefaultConnectionService() at /srv/sylius/var/cache/dev/ContainerK6cuif2/appDevDebugProjectContainer.php:3936
 ContainerK6cuif2\appDevDebugProjectContainer->getDoctrine_Orm_DefaultEntityManagerService() at /srv/sylius/var/cache/dev/ContainerK6cuif2/appDevDebugProjectContainer.php:3881
 ContainerK6cuif2\appDevDebugProjectContainer->ContainerK6cuif2\{closure}() at /srv/sylius/var/cache/dev/ContainerK6cuif2/EntityManager_9a5be93.php:235
 Closure->__invoke() at /srv/sylius/var/cache/dev/ContainerK6cuif2/EntityManager_9a5be93.php:235
 EntityManager_9a5be93->getConfiguration() at /srv/sylius/vendor/symfony/symfony/src/Symfony/Bridge/Doctrine/CacheWarmer/ProxyCacheWarmer.php:51
 Symfony\Bridge\Doctrine\CacheWarmer\ProxyCacheWarmer->warmUp() at /srv/sylius/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/CacheWarmer/CacheWarmerAggregate.php:52
 Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerAggregate->warmUp() at /srv/sylius/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php:686
 Symfony\Component\HttpKernel\Kernel->initializeContainer() at /srv/sylius/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php:137
 Symfony\Component\HttpKernel\Kernel->boot() at /srv/sylius/app/AppKernel.php:33
 AppKernel->boot() at /srv/sylius/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Console/Application.php:64
 Symfony\Bundle\FrameworkBundle\Console\Application->doRun() at /srv/sylius/vendor/symfony/symfony/src/Symfony/Component/Console/Application.php:148
 Symfony\Component\Console\Application->run() at /srv/sylius/bin/console:29

In thise case getSylius_Listener_ImagesRemoveService() should never have been called during container compilation, even when its doctrine.event_listener tag does not have lazy set to true.

Most helpful comment

It is much better to keep it as-is and have users:

  1. not initialize sockets or equivalent as part of service instantiations
  2. not generate proxies at runtime

Closing as won't fix here, as the correct resolution is to make OpenStack\OpenStack (or whichever detail of that component that causes the HTTP call) lazy.

All 10 comments

Well, the way to enforce lazy-loading is to mark the listener as lazy.

But here, the actual issue I see is that some service is doing an HTTP request in its constructor. That's the service being bad in a DI environment (the Doctrine listener is one of its consumers, but you could have others with the same kind of issues)

Yes, you're right. But we could never expect all classes being designed to cater to a container compilation kind of scenario.

The reason why I ask if we could force lazy loading during container compilation is because it'll be an easy win. (Think the 80/20 rule.) And actually, it wouldn't be a problem what classes do in their constructors as they usually should not get instantiated during container compilation. It is Doctrine that is causing them to get instantiated at this point, so...

Listeners need to be instantiated because compiler passes may rely on
metadata. On their own, no initialisation is really performed.

If anything in your system uses metadata or any ORM information at
compile-time, you will get this sort of call.

Can you check which one caused this one, specifically?

On Thu, 24 May 2018, 09:18 Teoh Han Hui, notifications@github.com wrote:

Yes, you're right. But we could never expect all classes being designed to
cater to a container compilation kind of scenario.

The reason why I ask if we could force lazy loading during container
compilation is because it'll be an easy win. (Think the 80/20 rule.) And
actually, it wouldn't be a problem what classes do in their constructors as
they usually should get instantiated during container compilation. It is
Doctrine that is causing them to get instantiated at this point, so...

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/doctrine/DoctrineBundle/issues/822#issuecomment-391614261,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAJakIX3YqBoUA2ZmXdyzpQLQ6VCO9Miks5t1l6xgaJpZM4ULEQO
.

It's not caused by listeners using this event, right?

https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/events.html#load-classmetadata-event

So it has to be something that explicitly requests for Doctrine metadata... I'll look into it.

Do you see a way forward? Is it possible to defer loading other event listeners other than for the loadClassMetadata event?

@teohhanhui make the service that is failing lazy, rather than the entire listener chain.

Yes, that avoids the problem. But what I'm trying to address here is a way for there not to be such a problem in the first place. If there is no reason for the listeners to be loaded during compile time, it'd be best if their instantiation could be made lazy. It'll prevent a lot of other future problems for the users.

It is much better to keep it as-is and have users:

  1. not initialize sockets or equivalent as part of service instantiations
  2. not generate proxies at runtime

Closing as won't fix here, as the correct resolution is to make OpenStack\OpenStack (or whichever detail of that component that causes the HTTP call) lazy.

Was this page helpful?
0 / 5 - 0 ratings