skip to Main Content

I try to configure two cache pools in my Synfony5 app to use a certain namespace and set a default expiration date for the items. After trying for the umpteenth time the umteenth variation I get the feeling that my configuration is going in circles.

What I understood so far:
In the constructor of the RedisAdapter you can set the namespace and the default expiration time
In the createConnection method you set the url of your redis server.

However the constructor of the RedisAdapter seems to already need a redis client (= redis connection?)
RedisAdapter:

/**
 * @param Redis|RedisArray|RedisCluster|PredisClientInterface $redisClient     The redis client
 * @param string                                                   $namespace       The default namespace
 * @param int                                                      $defaultLifetime The default lifetime
 */
public function __construct($redisClient, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null)
{
    $this->init($redisClient, $namespace, $defaultLifetime, $marshaller);
}

How can I inject my namespaces and defaultLifetimes into the RedisAdapter?

What I tried so far:
cache.yaml:

framework:
    cache:
        pools:
            cache.sap:
                adapter: cache.adapter.redis
                provider: app.service.puc_sap_redis_adapter
            cache.pers:
                adapter: cache.adapter.redis
                provider: app.service.puc_pers_redis_adapter

services.yaml:

app.my_redis_adapter:
    class: 'Redis'
    factory: ['SymfonyComponentCacheAdapterRedisAdapter', 'createConnection']
    arguments:
        - 'redis://%env(string:REDIS_URL)%:%env(int:REDIS_PORT)%'
        - { retry_interval: 2, timeout: 5 }

app.service.puc_sap_redis_adapter:
    class: SymfonyComponentCacheAdapterRedisAdapter
    arguments:
        $redisClient: '@app.my_redis_adapter'
        $namespace: 'sapData'
        $defaultLifetime: '%env(SAP_CACHE_TIMEOUT)%'

app.service.puc_pers_redis_adapter:
    class: SymfonyComponentCacheAdapterRedisAdapter
    arguments:
        $redisClient: '@app.my_redis_adapter'
        $namespace: 'persData'
        $defaultLifetime: '%env(CACHE_TIMEOUT)%'

This gets me the error message:

line: 62, 
file: "/var/www/vendor/symfony/cache/Traits/RedisTrait.php", 
message: ""Symfony\Component\Cache\Traits\RedisTrait::init()" 
expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\ClientInterface, 
"Symfony\Component\Cache\Adapter\RedisAdapter" given."

How can I configure the namespaces and expiration time for my two cache pools?

2

Answers


  1. Chosen as BEST ANSWER

    After several days of blood, sweat and tears I leave this here so nobody else will have to experience this deep desperation.

    This is how it works. You will need no extra class "just" this nifty cache.yaml in the folder for your environment:

    framework:
        cache:
            pools:
                cache.sap:
                    adapter: app.cache.adapter.sap_redis  # custom namespace and item expiration defined there
                    provider: app.cache.custom_redis_provider # Which server connection should be used
                cache.pers:
                    adapter: app.cache.adapter.pers_redis # custom namespace and item expiration defined there
                    provider: app.cache.custom_redis_provider # Which server connection should be used
    
    services:
        app.cache.custom_redis_provider: # this defines our connection to the redis server
            class: Redis
            factory: ['SymfonyComponentCacheAdapterRedisAdapter', 'createConnection']
            arguments:
                - 'redis://%env(string:REDIS_URL)%:%env(int:REDIS_PORT)%' # this defines the url to the redis server. "redis" up front is mandatory
                - { retry_interval: 2, timeout: 5 }  # defines number of connection retries and connection timeout (not item expiration!)
    
        app.cache.adapter.sap_redis: # here we pass namespace and expiration timeout into the constructor of the redis adapter
            parent: 'cache.adapter.redis'
            tags:
                - { name: 'cache.pool', namespace: 'sapData', default_lifetime: '%env(int:SAP_CACHE_TIMEOUT)%' }
    
        app.cache.adapter.pers_redis: # here we pass a different namespace and expiration timeout into the constructor of the redis adapter
            parent: 'cache.adapter.redis'
            tags:
                - { name: 'cache.pool', namespace: 'persData', default_lifetime: '%env(int:CACHE_TIMEOUT)%' }
    

  2. You can also set those parameters within the usual cache-pool configuration.

    framework:
        cache:
            default_memcached_provider: 'memcached://localhost'
            # could also replace with 
            # default_redis_provider: 'redis://localhost' # or '%env(REDIS_DSN)%'
    
            pools:
                # creates a "custom_thing.cache" service
                # autowireable via "CacheInterface $customThingCache"
                # uses the "app" cache configuration
                custom_thing.cache:
                    adapter: cache.app 
    
                # creates a "my_cache_pool" service
                # autowireable via "CacheInterface $myCachePool"
                my_cache_pool:
                    adapter: cache.adapter.filesystem
    
                # uses the default_memcached_provider from above
                acme.cache:
                    adapter: cache.adapter.memcached
    
                # control adapter's configuration - customised provider adaptor & DSN
                foobar.cache:
                    adapter: cache.adapter.memcached
                    provider: 'memcached://user:[email protected]'
    
                # uses the "foobar.cache" pool as its backend but controls
                # the lifetime and (like all pools) has a separate cache namespace
                short_cache:
                    adapter: foobar.cache
                    default_lifetime: 60
    

    The page (linked above) goes on to say how to tag a service for a specific namespace, but the various configured pools already have one set by default:

    Each pool manages a set of independent cache keys: keys from different pools never collide, even if they share the same backend. This is achieved by prefixing keys with a namespace that’s generated by hashing the name of the pool, the name of the compiled container class and a configurable seed that defaults to the project directory.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search