emag-tech-labs/annotation-cache-bundle

用于Symfony容器内服务基于注解的缓存

安装量 32,875

依赖项: 0

建议者: 0

安全性: 0

星标: 19

关注者: 20

分支: 5

公开问题: 3

类型:symfony-bundle

6.0.2 2023-03-30 17:08 UTC

README

Packagist Version Build Status Total Downloads Latest Stable Version License Coverage Status

用于Symfony容器内方法响应的基于注解的缓存。

此包可以帮助您通过简单的注解或属性添加缓存。您可以将缓存存储在任何实现了PSR-6:Caching Interface的类中,无论是简单的数组还是redis/memcache存储。

工作原理

此包将扫描定义的服务中的所有方法,并查找Cache注解或属性(PHP 8+)。

对于找到Cache注解/属性的任何服务,它将创建一个代理类(使用ocramius/proxy-manager),该类扩展服务类,包含CacheableClassTrait并重写具有Cache注解/属性的方法。

重写的方法包括调用getCached方法,该方法识别注解详细信息,获取键,获取Cache PSR-6实现,然后从缓存中获取结果。如果没有找到具有生成缓存键的数据,它将调用原始方法,然后将其响应保存到提供的提供者中。

该包有一个CompilerPass实现,将搜索并重写服务定义,以使用上述过程中创建的代理类。

安装

使用Symfony Flex

使用Symfony Flex安装和配置AnnotationCacheBundle的简单方法是使用Symfony Flex

 composer require symfony/flex ^1.0
 composer config extra.symfony.allow-contrib true
 composer require emag-tech-labs/annotation-cache-bundle

Symfony Flex将自动注册和配置此包。

不使用Symfony Flex

如果您的应用程序不使用Symfony Flex,您可以通过以下步骤手动配置此包:

步骤1:下载包

打开命令行,进入项目目录,并执行以下命令以下载此包的最新稳定版本

composer require emag-tech-labs/annotation-cache-bundle

步骤2:启用包

然后,通过将其添加到项目的config/bundles.php文件中注册的包列表来启用包

// config/bundles.php

return [
    // ...
    EmagTechLabs\AnnotationCacheBundle\AnnotationCacheBundle::class => ['all' => true],
];

步骤3:配置

最简单的方法是导出配置并将其复制到configs/packages/emag_annotation_cache.yaml

bin/console config:dump-reference AnnotationCacheBundle
配置示例

您必须配置PSR6兼容的服务名称,这意味着它必须实现Psr\Cache\CacheItemPoolInterface

# app/config/services.yaml

services:
    cache.array:
        class: Symfony\Component\Cache\Adapter\ArrayAdapter
    cache.redis:
        class: Symfony\Component\Cache\Adapter\RedisAdapter
        arguments: ['@predis']
#configs/packages/emag_annotation_cache.yaml

# Annotation Cache Bundle
annotation_cache:
    provider: 
        default: cache.redis
        array: cache.array
    ignore_namespaces:
      - 'Symfony\\'
      - 'Doctrine\\'
    ignore_names:
      - legacy
      - type
      - required

用法

为要缓存的类方法添加Cache注解。

注解参数

  • cache - 缓存前缀,字符串默认值:null(例如:'my_custom_prefix_')
  • key - 要包括在缓存键哈希生成中的参数名称,字符串,参数名称由逗号分隔默认值:''(例如:'a,b')
  • ttl - 缓存存储时间(秒),整型默认值:600(例如:'3600')
  • reset - 是否重置缓存,布尔型默认值:false(例如:'true')
  • storage - 如果定义了多个提供者,您可以使用它指定要使用的提供者,字符串默认值:'default'(例如:'array')

使用Doctrine Annotations库定义的注解

use EmagTechLabs\AnnotationCacheBundle\Annotation\Cache;

/**
 * @Cache(cache="<put your prefix>", [key="<name of argument to include in cache key separated by comma>",  [ttl=600, [reset=true, [storage=default ]]]])
 */

示例

namespace AppCacheBundle\Service;

use EmagTechLabs\AnnotationCacheBundle\Annotation\Cache;

class AppService
{
    /**
     * @Cache(cache="app_high_cpu", ttl=60)
     *
     * @return int
     */
    public function getHighCPUOperation(): int
    {
        sleep(10); // 'Simulate a time consuming operation';
        return 20;
    }
}

使用PHP 8属性定义的注解

use EmagTechLabs\AnnotationCacheBundle\Annotation\Cache;

 #[Cache(cache:'<put your prefix>', key:'<name of argument to include in cache key separated by comma>', ttl:600, reset: true, storage: 'default')]

示例

namespace AppCacheBundle\Service;

use EmagTechLabs\AnnotationCacheBundle\Annotation\Cache;

class AppService
{
    #[Cache(cache:'app_high_cpu', ttl: 60)]
    public function getHighCPUOperation(): int
    {
        sleep(10); // 'Simulate a time consuming operation';
        return 20;
    }
}

用例

以下提供两种使用此包的方法

配置

# app/config/services.yaml

services:
    cache.array:
        class: Symfony\Component\Cache\Adapter\ArrayAdapter
    cache.redis:
        class: Symfony\Component\Cache\Adapter\RedisAdapter
        arguments: ['@predis']
#configs/packages/emag_annotation_cache.yaml

# Annotation Cache Bundle
annotation_cache:
    provider: 
        default: cache.array
        redis: cache.redis
    ignore_namespaces:
      - 'Symfony\\'

服务代码

此包可以以多种方式使用,以下展示两种。

第一种情况是最常见的一种,你有一个执行多个耗时操作的方法,并且你想要在Redis中缓存响应,使用前缀(simple_time_consuming_operation_)和给定的时间(下面示例中的60秒)。这里的逻辑是先在Redis中查找值,如果没有找到,就运行实际的方法,获取结果并缓存起来,以便后续使用,同时考虑到@Cache注解中传入的参数。

第二种情况可以用于生成缓存命令并预热缓存,或者当某个事件触发时更新缓存,或者更新数据库中的信息。根据下面的示例,你可以设置一个cron任务,每3000秒运行一次,以便在缓存过期之前重新创建缓存。因为我们使用相同的缓存前缀和键,当两个方法(getTimeConsumingOperationValueWithResetgetTimeConsumingOperationValue)传入相同的参数值时,生成的缓存键将是相同的,在这个例子中是:time_consuming_operation_7fe49b314fb356bee76dbd3b8716b4d5ab5db600。这意味着两个方法都将(从)同一个缓存键写入(读取)缓存。因为第二个方法将reset参数设置为true,所以对第二个方法的任何调用都将使用函数的新结果覆盖键time_consuming_operation_7fe49b314fb356bee76dbd3b8716b4d5ab5db600中的缓存值。

namespace AppCacheBundle\Service;

use EmagTechLabs\AnnotationCacheBundle\Annotation\Cache;

class AppService
{
    /**
     * @Cache(cache="simple_time_consuming_operation_", ttl=60, storage="redis")
     *
     * @param int $a
     * @param int $b
     * 
     * @return int
     */
    public function getSimpleTimeConsumingOperationValue(int $a, int $b): int
    {
        sleep(10); // 'Simulate a time consuming operation';
        return $a + $b;
    }
    
    #[Cache(cache:'time_consuming_operation_', key: 'a,b', ttl: 3600, storage: 'redis')]
    public function getTimeConsumingOperationValue(int $a, int $b): int
    {
        return $this->getTimeConsumingOperationValueWithReset($a, $b);
    }
    
    #[Cache(cache:'time_consuming_operation_', key: 'a,b', ttl: 3600, reset: true, storage: 'redis')]
    public function getTimeConsumingOperationValueWithReset(int $a, int $b): int
    {
        sleep(10); // 'Simulate a time consuming operation';
        return $a + $b;
    }
}

服务调用

// from controller
/** AppService $appService */
$appService->getTimeConsumingOperationValue(1, 2);

// from command
/** AppService $appService */
$appService->getTimeConsumingOperationValueWithReset(1, 2);

贡献

感谢您对贡献的兴趣!有许多方式可以为这个项目做出贡献。从这里开始这里