Symfony 3.1 缓存组件中的缓存失效
Cache invalidation in Symfony 3.1 cache component
我使用 Symfony 3.1 的 cache component 为我的实体存储一些自定义元数据。我想在与这些元数据关联的任何文件发生更改后立即使其失效。
我没有找到一种方法来告诉 Symfony 或特别是缓存组件观察特定文件集的变化,我错过了什么?
在我用来创建缓存项池的代码下方:
<?php
class MetadataCacheFactory implements MetadataCacheFactoryInterface
{
const CACHE_NAMESPACE = 'my_namespace';
/** @var string */
protected $cacheDir;
public function __construct(KernelInterface $kernel)
{
$this->cacheDir = $kernel->getCacheDir();
}
/**
* {@inheritdoc}
*/
public function create(): CacheItemPoolInterface
{
return AbstractAdapter::createSystemCache(self::CACHE_NAMESPACE, 0, null, $this->cacheDir);
}
}
以及使用它的代码:
<?php
class ExampleMetadataFactory implements MetadataFactoryInterface
{
const CACHE_KEY = 'example_metadata';
[...]
/** @var ExampleMetadata */
protected $metadata;
public function __construct(MetadataCacheFactoryInterface $cacheFactory)
{
$this->cache = $cacheFactory->create();
$this->metadata = null;
}
/**
* {@inheritdoc}
*/
public function create(): ExampleMetadata
{
if ($this->metadata !== null) {
return $this->metadata;
}
try {
$cacheItem = $this->cache->getItem(md5(self::CACHE_KEY));
if ($cacheItem->isHit()) {
return $cacheItem->get();
}
} catch (CacheException $e) {
// Ignore
}
$this->metadata = $this->createMetadata();
if (!isset($cacheItem)) {
return $this->metadata;
}
$cacheItem->set($this->metadata);
$this->cache->save($cacheItem);
return $this->metadata;
}
}
当我在运行时查看代码时,AbstractAdapter
选择给我一个 PhpFilesAdapter
(我想在开发中足够公平)。
但是当我查看这个适配器的代码时,我发现:
<?php
protected function doFetch(array $ids) {
[...]
foreach ($ids as $id) {
try {
$file = $this->getFile($id);
list($expiresAt, $values[$id]) = include $file;
if ($now >= $expiresAt) {
unset($values[$id]);
}
} catch (\Exception $e) {
continue;
}
}
}
所以除了过期日期之外,根本没有检查过期的逻辑。
您知道在文件更改时使缓存无效的方法吗(当然是在开发环境中)?还是我自己实现..?
感谢您的帮助。
我找到了解决方案:ConfigCache。你可以给它一个资源数组来观察,它会在每次读取缓存时检查它们的最后修改时间。
上面的例子变成这样:
<?php
class MetadataCacheFactory implements MetadataCacheFactoryInterface
{
const CACHE_NAMESPACE = 'my_namespace';
/** @var \Symfony\Component\HttpKernel\KernelInterface */
protected $kernel;
public function __construct(KernelInterface $kernel)
{
$this->kernel = $kernel;
}
/**
* {@inheritdoc}
*/
public function create(): ConfigCache
{
return new ConfigCache($this->kernel->getCacheDir().'/'.self::CACHE_NAMESPACE, $this->kernel->isDebug());
}
}
以及使用它的代码:
<?php
class ExampleMetadataFactory implements MetadataFactoryInterface
{
const CACHE_KEY = 'example_metadata';
[...]
/** @var ExampleMetadata */
protected $metadata;
public function __construct(MetadataCacheFactoryInterface $cacheFactory)
{
$this->cache = $cacheFactory->create();
$this->metadata = null;
}
/**
* {@inheritdoc}
*/
public function create(): ExampleMetadata
{
if ($this->metadata !== null) {
return $this->metadata;
}
try {
if ($this->cache->isFresh()) {
$this->metadata = unserialize(file_get_contents($this->cache->getPath()));
return $this->metadata;
}
} catch (CacheException $e) {
// Ignore
}
$resources = [];
$this->metadata = $this->createMetadata($resources);
$this->cache->write(serialize($this->metadata), $resources);
return $this->metadata;
}
/**
* Creates the metadata.
*
* @param array $resources
*
* @return ExampleMetadata
*/
protected function createMetadata(&$resources): ExampleMetadata
{
$metadata = new ExampleMetadata();
$resourcesCollection = $this->resourcesCollectionFactory->create();
foreach ($resourcesCollection as $resourceClass => $resourcePath) {
// The important part, it's an instance of \Symfony\Component\Config\Resource\FileResource.
$resources[] = new FileResource($resourcePath);
$resourceMetadata = $this->resourceMetadataFactory->create($resourceClass);
$metadata->registerResourceMetadata($resourceMetadata);
}
return $metadata;
}
}
希望能帮到别人。
我使用 Symfony 3.1 的 cache component 为我的实体存储一些自定义元数据。我想在与这些元数据关联的任何文件发生更改后立即使其失效。
我没有找到一种方法来告诉 Symfony 或特别是缓存组件观察特定文件集的变化,我错过了什么?
在我用来创建缓存项池的代码下方:
<?php
class MetadataCacheFactory implements MetadataCacheFactoryInterface
{
const CACHE_NAMESPACE = 'my_namespace';
/** @var string */
protected $cacheDir;
public function __construct(KernelInterface $kernel)
{
$this->cacheDir = $kernel->getCacheDir();
}
/**
* {@inheritdoc}
*/
public function create(): CacheItemPoolInterface
{
return AbstractAdapter::createSystemCache(self::CACHE_NAMESPACE, 0, null, $this->cacheDir);
}
}
以及使用它的代码:
<?php
class ExampleMetadataFactory implements MetadataFactoryInterface
{
const CACHE_KEY = 'example_metadata';
[...]
/** @var ExampleMetadata */
protected $metadata;
public function __construct(MetadataCacheFactoryInterface $cacheFactory)
{
$this->cache = $cacheFactory->create();
$this->metadata = null;
}
/**
* {@inheritdoc}
*/
public function create(): ExampleMetadata
{
if ($this->metadata !== null) {
return $this->metadata;
}
try {
$cacheItem = $this->cache->getItem(md5(self::CACHE_KEY));
if ($cacheItem->isHit()) {
return $cacheItem->get();
}
} catch (CacheException $e) {
// Ignore
}
$this->metadata = $this->createMetadata();
if (!isset($cacheItem)) {
return $this->metadata;
}
$cacheItem->set($this->metadata);
$this->cache->save($cacheItem);
return $this->metadata;
}
}
当我在运行时查看代码时,AbstractAdapter
选择给我一个 PhpFilesAdapter
(我想在开发中足够公平)。
但是当我查看这个适配器的代码时,我发现:
<?php
protected function doFetch(array $ids) {
[...]
foreach ($ids as $id) {
try {
$file = $this->getFile($id);
list($expiresAt, $values[$id]) = include $file;
if ($now >= $expiresAt) {
unset($values[$id]);
}
} catch (\Exception $e) {
continue;
}
}
}
所以除了过期日期之外,根本没有检查过期的逻辑。
您知道在文件更改时使缓存无效的方法吗(当然是在开发环境中)?还是我自己实现..?
感谢您的帮助。
我找到了解决方案:ConfigCache。你可以给它一个资源数组来观察,它会在每次读取缓存时检查它们的最后修改时间。
上面的例子变成这样:
<?php
class MetadataCacheFactory implements MetadataCacheFactoryInterface
{
const CACHE_NAMESPACE = 'my_namespace';
/** @var \Symfony\Component\HttpKernel\KernelInterface */
protected $kernel;
public function __construct(KernelInterface $kernel)
{
$this->kernel = $kernel;
}
/**
* {@inheritdoc}
*/
public function create(): ConfigCache
{
return new ConfigCache($this->kernel->getCacheDir().'/'.self::CACHE_NAMESPACE, $this->kernel->isDebug());
}
}
以及使用它的代码:
<?php
class ExampleMetadataFactory implements MetadataFactoryInterface
{
const CACHE_KEY = 'example_metadata';
[...]
/** @var ExampleMetadata */
protected $metadata;
public function __construct(MetadataCacheFactoryInterface $cacheFactory)
{
$this->cache = $cacheFactory->create();
$this->metadata = null;
}
/**
* {@inheritdoc}
*/
public function create(): ExampleMetadata
{
if ($this->metadata !== null) {
return $this->metadata;
}
try {
if ($this->cache->isFresh()) {
$this->metadata = unserialize(file_get_contents($this->cache->getPath()));
return $this->metadata;
}
} catch (CacheException $e) {
// Ignore
}
$resources = [];
$this->metadata = $this->createMetadata($resources);
$this->cache->write(serialize($this->metadata), $resources);
return $this->metadata;
}
/**
* Creates the metadata.
*
* @param array $resources
*
* @return ExampleMetadata
*/
protected function createMetadata(&$resources): ExampleMetadata
{
$metadata = new ExampleMetadata();
$resourcesCollection = $this->resourcesCollectionFactory->create();
foreach ($resourcesCollection as $resourceClass => $resourcePath) {
// The important part, it's an instance of \Symfony\Component\Config\Resource\FileResource.
$resources[] = new FileResource($resourcePath);
$resourceMetadata = $this->resourceMetadataFactory->create($resourceClass);
$metadata->registerResourceMetadata($resourceMetadata);
}
return $metadata;
}
}
希望能帮到别人。