BraCa
BraCa

Reputation: 351

Symfony 3.1 Cache - DeleteItem not working in prod

I've been using Symfony 3.1 with new Cache Component (https://symfony.com/doc/current/components/cache.html), I'm using the redis adapter

config.yml

cache:
    app: cache.adapter.redis
    default_redis_provider: "redis://127.0.0.1:6379"

Basically, I save data in redis when I do a GET to a specific resource, and I remove it from redis, when I do a POST..

With symfony in dev mode data is stored/removed from cache as I expected. But when I change it to prod, the 'deleteItem' no longer removes the item from redis cache.. I cannot find any error in logs, so I'm getting a little bit lost with it..

This is a sample of how I'm using the cache

protected function getCache(){
   return $this->get('cache.app');
}

public function getAction(){        
    $cacheItem = $this->getCache()->getItem('example-key');
    $data = ... // Check cacheItem isHit() ...      
    $cacheItem->expiresAfter($this->defaultCacheTime);
    $cacheItem->set($data);
    $this->getCache()->save($cacheItem);        
}

public function postAction() {
    ...
    $this->getCache()->deleteItem('example-key');
}

Update - I've found what might be causing this issue

This is part of the code of symfony AbstractAdapter and RedisAdapter:

public function deleteItem($key)
{
    return $this->deleteItems(array($key));
}

public function deleteItems(array $keys)
{
    $ids = array();

    foreach ($keys as $key) {
        $ids[$key] = $this->getId($key);
        unset($this->deferred[$key]);
    }

    try {
        if ($this->doDelete($ids)) {
            return true;
        }
    } catch (\Exception $e) {
    }

    $ok = true;

    // When bulk-delete failed, retry each item individually
    foreach ($ids as $key => $id) {
        try {
            $e = null;
            if ($this->doDelete(array($id))) {
                continue;
            }
        } catch (\Exception $e) {
        }
        CacheItem::log($this->logger, 'Failed to delete key "{key}"', array('key' => $key, 'exception' => $e));
        $ok = false;
    }

    return $ok;
}

protected function doDelete(array $ids)
{
    if ($ids) {
        $this->redis->del($ids);
    }

    return true;
}

This is part of code from Predis StreamConnection.php:

public function writeRequest(CommandInterface $command)
{
    $commandID = $command->getId();
    $arguments = $command->getArguments();

    $cmdlen = strlen($commandID);
    $reqlen = count($arguments) + 1;

    $buffer = "*{$reqlen}\r\n\${$cmdlen}\r\n{$commandID}\r\n";

    for ($i = 0, $reqlen--; $i < $reqlen; $i++) {
        $argument = $arguments[$i];
        $arglen = strlen($argument);
        $buffer .= "\${$arglen}\r\n{$argument}\r\n";
    }

    $this->write($buffer);
}   

When I call deleteItem('example-key'), it then calls the deleteItems(..) to remove that key..

The thing is, deleteItems() is calling doDelete() and passing an array like 'example-key' => 'prefix_example-key'

The doDelete(), then calls the Redis client, passing that same array string => string, when I think it should be, index => string,eg: [0] => 'prefix_example-key' instead of ['example-key'] => 'prefix_example-key'

Then the redis client when processing the command to execute, receives that array as $arguments, and in the for loop, it does this: $argument = $arguments[$i]; since the array is in string => string format, it won't work, in dev mode, it shows Notice undefined offset 0 error

This is the strange part

I've found a way to make it work for me, if I add array_values in the doDelete method, it works:

protected function doDelete(array $ids)
{
    if ($ids) {
        $this->redis->del(array_values($ids));
    }

    return true;
}

I don't know if all of this is making sense or not, I think I'll open an issue in symfony bug tracker

Upvotes: 3

Views: 849

Answers (1)

BraCa
BraCa

Reputation: 351

My bad, this was caused by an outdated version of Predis, I tought I had the latest version of Predis, but I didn't

Everything is working fine with the latest version

Upvotes: 0

Related Questions