Я использую Symfony 3.1 с новым Cache Component (https://symfony.com/doc/current/components/cache.html), я использую адаптер REDISSymfony 3.1 Cache - DeleteItem не работает в прод
config.yml
cache:
app: cache.adapter.redis
default_redis_provider: "redis://127.0.0.1:6379"
В основном, Я сохраняю данные в redis, когда я делаю GET для определенного ресурса, и я удаляю его из redis, когда я выполняю POST.
С Symfony в режиме dev данные сохраняются/удаляются из кеша, как я ожидал. Но когда я изменить его на прод, то «DeleteItem» больше не удаляет элемент из Redis кэша .. я не могу найти какую-либо ошибку в журналах, так что я получаю немного потерял с ним ..
Это это пример того, как я использую кэш
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 - Я обнаружил, что может быть причиной этой проблемы
Это часть кода симфони AbstractAdapter и 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;
}
Это часть кода из 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);
}
Когда я называю DeleteItem ('пример-ключ'), он затем называет deleteItems (..), чтобы удалить этот ключ ..
дело в том, deleteItems() вызывает doDelete() и передавая массив как 'example-key' => 'prefix_example-key'
The doDelete(), то вызов клиента Redis, передавая тот же массив string => string
, когда я думаю, что это Shoul d быть, index => string
, например: [0] => 'prefix_example-key'
вместо ['example-key'] => 'prefix_example-key'
Затем клиент REDIS при обработке команды для выполнения, получает этот массив в качестве $ аргументов, и в течение цикла, он делает это: $argument = $arguments[$i];
, так как массив в формат string => string
, он не будет работать в режиме разработчика, он показывает Уведомление не определено смещение 0 ошибка
Это странное
- в режиме «DEV», он выдаст сообщение об ошибке, и поэтому d eleteItems() поймает его и попытается удалить элемент снова, на этот раз, правильно отправив аргументы
- В режиме «prod» Уведомление о неопределенном смещении 0 не знаю почему, но оно не выбрасывает исключение, поэтому deleteItems (..) не поймает его, возвращается прямо там ..
Я нашел способ, чтобы заставить его работать для меня, если я добавляю array_values в методе doDelete, он работает:
protected function doDelete(array $ids)
{
if ($ids) {
$this->redis->del(array_values($ids));
}
return true;
}
Я не знаю, если все это делает чувство или нет, я думаю, что я открою проблему в симфони багтрекер