willdurand / BazingaHateoasBundle

Integration of the Hateoas library into Symfony.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Add cache warmer

jaikdean opened this issue · comments

It would be really useful to have a cache warmer registered automatically. We've done this manually by adding the following to our services.yaml:

    hateoas.configuration.metadata.cache.cache_warmer:
        class: JMS\SerializerBundle\Cache\CacheWarmer
        arguments:
            $includePaths: ['%kernel.project_dir%/src/Entity']
            $metadataFactory: '@hateoas.configuration.metadata_factory'
        tags: [kernel.cache_warmer]

@jaikdean Do you confirm that if you really want your warmup to be 100% done you will also have to include the files inside the hateoas library? Otherwise in production, if cache is only readable it will fail because e.g. Hateoas-Representation-CollectionRepresentation.cache.php will not be generated.

EDIT: my first paragraph doesn't seem to solve the issue. Even by adding the generation of the classes in from hateoas vendor in production it stills fails because it cannot write into the cache:

It seems to want to save into the pool

[2018-12-18 13:00:33] cache.WARNING: Failed to save key "%5BHateoas%5CRepresentation%5CRouteAwareRepresentation%23__construct%5D%5B1%5D" (array) {"key":"%5BHateoas%5CRepresentation%5CRouteAwareRepresentation%23__construct%5D%5B1%5D","type":"array","exception":"[object] (ErrorException(code: 0): file_put_contents(/app/var/cache/prod/pools/hvoJTUZdSU/5c18ef714695b6.83591465): failed to open stream: Permission denied at /app/vendor/symfony/cache/Traits/FilesystemCommonTrait.php:92)"} []

While I do have this in /var/cache/prod/hateoas/

4 -rw-r--r--    1 root     root           186 Dec 18 12:59 Hateoas-Representation-AbstractSegmentedRepresentation.cache.php
4 -rw-r--r--    1 root     root           493 Dec 18 12:59 Hateoas-Representation-CollectionRepresentation.cache.php
4 -rw-r--r--    1 root     root           181 Dec 18 12:59 Hateoas-Representation-Factory-PagerfantaFactory.cache.php
8 -rw-r--r--    1 root     root          5349 Dec 18 12:59 Hateoas-Representation-OffsetRepresentation.cache.php
8 -rw-r--r--    1 root     root          5206 Dec 18 12:59 Hateoas-Representation-PaginatedRepresentation.cache.php
4 -rw-r--r--    1 root     root          1183 Dec 18 12:59 Hateoas-Representation-RouteAwareRepresentation.cache.php
4 -rw-r--r--    1 root     root           489 Dec 18 12:59 Hateoas-Representation-VndErrorRepresentation.cache.php

And according the symfony's doc (https://symfony.com/doc/current/setup/file_permissions.html):

In the prod environment (i.e. when APP_ENV is prod and APP_DEBUG is 0), as long as you run php bin/console cache:warmup, no cache files will need to be written to disk at runtime.

@jaikdean Any ideas?

@tonivdv Out of the box with Symfony, that quote from the documentation is true. However, third-party bundles might try to write there regardless of the env/debug settings.

I'm not sure about the issue you're having I'm afraid, I've not touched this since I opened the original issue, and the solution in my first post seems to work for us. We're probably only using a subset of the functionality in this bundle though.

Can be done similarly as what implemented in schmittjoh/JMSSerializerBundle#615

@jaikdean Ok. And also it depends if you made the /var/cache writable or not ... if writable then you don't "detect" this kind of issue

@goetas What do you mean with that? I currently took the snippet from @jaikdean which does warm the cache up, but still could the above error. Unless you mean something else with the reference?

Thanks

@jaikdean is actually using the feature implemented in schmittjoh/JMSSerializerBundle#615

@goetas Yes I understood that. But by doing like @jaikdean is doing:

hateoas.configuration.metadata.cache.cache_warmer:
        class: JMS\SerializerBundle\Cache\CacheWarmer
        arguments:
            $includePaths: ['%kernel.project_dir%/src/Entity']
            $metadataFactory: '@hateoas.configuration.metadata_factory'
        tags: [kernel.cache_warmer]

It does not take into account some classes present in the hateoas library. So I changed to:

# Cache Warmer Service for Hateoas. Necessary until:
    hateoas.configuration.metadata.cache.cache_warmer:
        class: JMS\SerializerBundle\Cache\CacheWarmer
        arguments:
          $includePaths: ['%kernel.project_dir%/src', '%kernel.project_dir%/vendor/willdurand/hateoas/src/Hateoas/Representation']
          $metadataFactory: '@hateoas.configuration.metadata_factory'
        tags: [kernel.cache_warmer]

But this still didn't do the trick while it did add the files in the var/cache/prod/hateoas directory.

I'm playing with this at the moment and what I just discovered is that it also needs to have those files in src/Hateoas/Representation for the JMS.

In conclusion I need to tell JMS warmup to also take into account src/Hateoas/Representation.

I will try that and let you guys know if it worked ... If it does ... wouldn't this be nice to have this configured in this bundle as per @jaikdean 's suggestion?

Ok so that was the issue. The next configuration solves the issue and allows you to keep your cache folder read-only in production (assuming you don't have any other third party hitting the cache directory as mentioned by @jaikdean ):

config/jms_serializer.yaml

jms_serializer:

  metadata:
    warmup:
      paths:
        included:
          - '%kernel.root_dir%'
          - '%kernel.project_dir%/vendor/willdurand/hateoas/src/Hateoas/Representation'

What's important in the above snippet is the second include. The first one can be enhanced if you're files are more regrouped.

config/services.yaml

hateoas.configuration.metadata.cache.cache_warmer:
    class: JMS\SerializerBundle\Cache\CacheWarmer
    arguments:
      $includePaths: ['%kernel.project_dir%/src', '%kernel.project_dir%/vendor/willdurand/hateoas/src/Hateoas/Representation']
      $metadataFactory: '@hateoas.configuration.metadata_factory'
    tags: [kernel.cache_warmer]

@goetas Wouldn't it be useful to have a part of this config in the bundle itself? Or at least have it documented?! (I'd be happy to provide a PR for both solutions)

I agree that would be to have it. A pr (with tests) would be welcome!