Symfony using Redis for the default cache the compiled container - php

I have a Symfony application, and I would like to use Redis as a caching system. The default caching system for Symfony out of the box is filesystem caching.
from the documentation I learned there are two named caches in Symfony; cache.app and cache.system so I set both to Redis with the following cache.yaml:
framework:
cache:
# Put the unique name of your app here: the prefix seed
# is used to compute stable namespaces for cache keys.
prefix_seed: myteam/myapp
default_redis_provider: "redis://redis:6379"
# The app cache caches to the filesystem by default.
# Other options include:
# cache.app via Redis
app: cache.adapter.redis
# cache.system also
system: cache.adapter.redis
After doing this, I loaded an example page and monitored the cache folder. I found that files were still being created in the cache folder, even though keys were being created in Redis.
I know that Symfony do not recommend messing with the files that the Kernel creates in the file cache, but even the cache/prod/Containerxxxxx folder was being written to.
What could be caching in the folder that isn't part of app or system? Is there another named cache that I have missed?

The files at cache/prod/Containerxxxxx are the compiled container files.
These are always written into your file system and never be written into other, secondary cache systems.
Symfony wouldn't know how to access Redis in the first place without getting that information from the container, the container is always cached to the filesystem when compiled and built.
cache.system is used for things like annotations, serializer, and validation; but not for the compiled container itself.
cache.app is the application cache, that is available for you to use in your app if you typehint CacheInterface or Psr\\Cache\\CacheItemPoolInterface in your services methods.
Summing up, there is no other cache you can configure so Symfony would store the compiled container there. These files are code and are stored on the filesystem.

Related

How to enable cache in dev mode?

I'm working on a heavy-load Symfony optimization, trying out template cache, doctrine cache, etc. But unless I'm wrong, those caches are disabled in dev, so it's hard to evaluate the effect of those optimizations.
Is there a way to enable caching in dev mode, so I can the application optimization results while keeping the debug bar?
Note that there are couple of assumptions in your question that are not true:
By default, Twig is always cached. Check the docs here. You can only disable caching, if for some reason you need to disable it during development. But more likely than not, it's not going to be great for you.
There is no default Doctrine caching enabled on production. If you want to enable caching, you'd need to do it yourself (by creating the appropriate file in config/packages/prod/doctrine.yml, but you'd first need to verify exactly what type of caching you'd need and how to configure it. Check some docs about doctrine caching here.
In the end, changing settings on dev (or any environment) it's just a matter of creating the another file with the appropriate settings within config/packages/[environment_name].
You should already have a few inside config/packages/dev/.
To create specific settings for an environment just add a couple of files to adjust these settings.
E.g. you could have a config/packages/dev/doctrine.yml with this inside (a basic doctrine caching configuration):
services:
doctrine.result_cache_provider:
class: Symfony\Component\Cache\DoctrineProvider
public: false
arguments:
- '#doctrine.result_cache_pool'
doctrine.system_cache_provider:
class: Symfony\Component\Cache\DoctrineProvider
public: false
arguments:
- '#doctrine.system_cache_pool'
framework:
cache:
pools:
doctrine.result_cache_pool:
adapter: cache.app
doctrine.system_cache_pool:
adapter: cache.system
Have you checked the configuration for each of these parts? For example, in older Symfony versions, there could be a file somewhere (depending on the Symfony version you've started the project with, it could for example reside at config/packages/dev/twig.yaml) that defines the Twig cache as following:
twig:
cache: false
By setting this to a valid caching directory, you can enable the cache, regardless of the environment running your application.
In other packages, there might be similar settings. Have a look for overriden settings, either in config/packages/dev and config/packages/prod for more recent versions or files like config/services_prod.yaml and config/services_dev.yaml for a bit older versions. But without knowing which packages you use, it's hard to provide a general answer.

Symfony: Speed up development enviroment for frontend developers

I'm trying to create a development enviroment for the frontend developers. As long as they don't change any php code I thought it might be a good idea do this, if possible:
Create a new entry point all app_frontend.php i.e., disabling the debug
Create a config_frontend.yml file and cache php files generation but disable twig cache as well as js and css
Is there any way to do this? I'm not sure if it's possible
You can create as many environments as you want. After all, environments are just sets of different configuration, nothing more.
This means that if you want to create a frontend environment, you have to do just some things:
Create some sort of front controller that constructs AppKernel using new AppKernel('frontend', false);
As AppKernel::registerContainerConfiguration() in the Symfony Standard Edition uses the environment to determine the config file to load, you have to create app/config/config_frontend.yml as well (or change the logic in the AppKernel method)
Inside this config file, make sure you import the settings that are in common. This often means importing app/config/config.yml. Besides that, you can configure things how you like it. E.g.
# app/config/config_frontend.yml
imports:
- { resource: config.yml }
twig:
cache: false
You can read more about this topic in the Symfony docs.

What is the best way to clear apc_cache when deploying a symfony project to an autoscaling application?

I am running a symfony application on 4 heroku dynos and I want to use apc_cache.
How do I make sure that the apc_cache is cleared on all dynos during deployment?
I found a trick online for clearing apc_cache during deployment that entails making a request to a (temporarily) publically available php file that clears the apc_cache. I do not understand how this would work reliably with multiple dynos, since any single request is always routed to only one of the dynos. Is this an issue at all, since my server monitoring tools indicate that the application is temporarily scaled down to one dyno during deployment, to be scaled back up when deployment is complete.
Maybe the following question should be a question on its own, but I am planning to migrate the application to Amazon EC2 in the near future and deploy automatically using Codeship, Docker and AWS Elastic Beanstalk (EB). Is there perhaps a more straightforward solution for the problem using Amazon EC2 instances in an autoscaling group?
Caching the Autoloader with APC (Found in Symfony docs)
Symfony comes with a class - ApcClassLoader - that does exactly this. To use it, just adapt your front controller file. If you're using the Standard Distribution, this code should already be available as comments in this file:
// app.php
// ...
$loader = require_once __DIR__.'/../app/bootstrap.php.cache';
// Use APC for autoloading to improve performance
// Change 'sf2' by the prefix you want in order
// to prevent key conflict with another application
/*
$loader = new ApcClassLoader('sf2', $loader);
$loader->register(true);
*/
// ...
NOTE: When using the APC autoloader, if you add new classes, they will be found automatically and everything will work the same as before (i.e. no reason to "clear" the cache). However, if you change the location of a particular namespace or prefix, you'll need to flush your APC cache. Otherwise, the autoloader will still be looking at the old location for all classes inside that namespace.
You could use this bundle https://github.com/ornicar/ApcBundle or https://github.com/Smart-Core/AcceleratorCacheBundle and add the commands to your post-install-cmd
Clear all APC cache (opcode+user):
$ php app/console apc:clear
or if you use the Capifony:
after "deploy", "symfony:clear_accelerator_cache"
after "deploy:rollback:cleanup", "symfony:clear_accelerator_cache"
Edited :
However, APC's object cache stores information on the local instance only, so once you have multiple dynos (instances), they won't share the cache.
For that, you could consider Memcached

What should be first: setting or cache object

I've a very basic question which drives me nuts. I maintain my own little framework. I can configure the framework with a YAML/JSON/XML/whatever settings file. The framework uses also a cache (any of memcached/couchbase/whatever even file based caching if no caching server is installed).
So no I've the following problem: I like to cache my settings parsed from the settings file in the cache but I would like to define the cache type used for that in the settings file.
What would be a proper solution for this? I can't imagine how I should manage this which leeds me to the thought that I probably have a very basic design / architecture error in my framework. Is there any solution at all?
Well as my experience from Symfony1 and Symfony2 goes, cache as much as you can.
In their production environment everything is cached, so you would run into your problem that the cache type is described in the settings file which is itself cached.
The proper solution to this is: As in Symfony: Delete the cache in prod, once you made changes to settings.
For dev the settings are always re-read as you do not profile in debug, so ease of development is more important that bootstrap time.
I recommend splitting this like symfony did.
For prod your settings are seldomly changed so parsing a file that can be cached is wasted resources and speed is typically priority 1 in prod.
Edit: Your options regarding the order of bootstrapping:
Always read settings first then decide which cache you will need.
Use a settings configuration cache that is hard coded (e.g file based)
I recommend using option 2. Your framework is cache agnostic as this can be configured, which is good but for basic settings of your framework you simply do not need that. You don't want to setup different cache mechanisms like memcache, sql etc just for basic settings.
Symfony solves this by the most effective way, as it provides a default cache generation for settings and this is simply a php file. Thats all. When symfony loads settings it looks for a certain file to include, if it does not exist, symfony caches it by creating plain php and then reads it.
You can determine the file type from the file extension. Then you can read the cache type and create a cache. The cache should be a singleton.
For the creation of the cache I would use an abstract factory, which implementation is dependent on the file type. The appropriate implementation of the abstract factory then can read the settings file and create the right cache.

Configuring Symfony 2 at Runtime

I'm creating web services for my company using Symfony2. Our company uses a centralized configuration service (Zookeeper/etcd) to manage configuration information for our services. Such as connection/host information for MySQL, Redis, Memcached, etc. The configuration is subject to change randomly through out the day. For instance when MySQL servers are added or removed from our database cluster. So hard coding the configuration in yml/xml is not possible.
So I'm looking for a way to modify the config.yml values when the application boots. Some of the values in the config will be static. For instance Twig and Switfmailer configurations, but other values for Doctrine and Redis need to be set on the fly.
The configuration values cannot be determined until the Symfony application boots, and the values cannot be cached or compiled. I've tried a few things to hook into the boot process and modify the configuration, but nothing works.
Additional Information
An example of the architecture I'm dealing with is described here: http://aredko.blogspot.com/2013/10/coordination-and-service-discovery-with.html Along with services like MySQL and Redis, we also need to discover our own RESTful services. Zookeeper is being used as a service discovery agent. The location (host name) and exact configuration for the services aren't known until runtime/boot.
I'd suggest you to take a look at OpenSkyRuntimeConfigBundle.
The bundle allows you to replace traditional container parameters (that you usually write to parameters.yml) with some logic. This provides you a way to make a query to Zookeeper to check the latest configuration variables and inject them to Symfony2 services without a need to rebuild the container.
As you can write the logic in any possible way, you can also implement local cache for the parameters. ZK reads are performant but always require a network round-trip. If performance is important for you, utilize a cache here too.
I wouldn't even consider running Symfony 2 without a cache if you care about performance.
It sounds like you've not quite identified the best way to compose your infrastructure whilst scaling things up / down. It's hard to be specific without knowing more about the bigger picture, but how about pointing the Symfony 2 db config to a proxy server, and manage the routing at the network level. The app then stays blissfully ignorant of the churn of db servers...

Categories