All Projects → eMAGTechLabs → annotation-cache-bundle

eMAGTechLabs / annotation-cache-bundle

Licence: MIT license
Annotation based caching for services inside a symfony container

Programming Languages

PHP
23972 projects - #3 most used programming language

Projects that are alternatives of or similar to annotation-cache-bundle

symbok-bundle
Symfony annotations bundle
Stars: ✭ 50 (+212.5%)
Mutual labels:  symfony-bundle, annotations
dochooks
WordPress hooks in method comments. Annotated hooks.
Stars: ✭ 33 (+106.25%)
Mutual labels:  annotations
GoogleTranslateBundle
A Symfony bundle to deals with Google Translate API
Stars: ✭ 44 (+175%)
Mutual labels:  symfony-bundle
vite-bundle
Integration with your Symfony app & Vite
Stars: ✭ 56 (+250%)
Mutual labels:  symfony-bundle
RulerZBundle
Symfony Bundle for RulerZ
Stars: ✭ 38 (+137.5%)
Mutual labels:  symfony-bundle
GuzzleBundleOAuth2Plugin
OAuth2 Plugin for GuzzleBundle
Stars: ✭ 13 (-18.75%)
Mutual labels:  symfony-bundle
ClassifyCNV
ClassifyCNV: a tool for clinical annotation of copy-number variants
Stars: ✭ 33 (+106.25%)
Mutual labels:  annotations
mjml-bundle
✉️ Symfony bundle for MJML
Stars: ✭ 87 (+443.75%)
Mutual labels:  symfony-bundle
adversaria
Typeclass interfaces to access user-defined Scala annotations
Stars: ✭ 22 (+37.5%)
Mutual labels:  annotations
Symfony-4-by-Samples
Symfony 4 by Samples is a personal project in which I will be creating small demos with tutorial in which to learn the symfony framework 4. Each of the samples contains a README.md file that indicates the purpose of the sample plus an step by step guide to reproduce it. Basic topics, login and register form, authentication, webpack encore, sass…
Stars: ✭ 40 (+150%)
Mutual labels:  annotations
SimpleVideoAnnotation
A simple video annotation made with python + OpenCV for detection in YoloV2 format
Stars: ✭ 13 (-18.75%)
Mutual labels:  annotations
SinchBundle
📦 Provides integration with Sinch.com SMS API.
Stars: ✭ 12 (-25%)
Mutual labels:  symfony-bundle
etiketai
Etiketai is an online tool designed to label images, useful for training AI models
Stars: ✭ 63 (+293.75%)
Mutual labels:  annotations
AtoumBundle
This bundle provides a simple integration of atoum into Symfony 2.
Stars: ✭ 44 (+175%)
Mutual labels:  symfony-bundle
linkedresearch.org
🌐 linkedresearch.org
Stars: ✭ 32 (+100%)
Mutual labels:  annotations
php-simple-request
php-simple-request is a request parser library designed to simplify requests validation and filtering using annotations, generating at the same time an object representation from the request data.
Stars: ✭ 15 (-6.25%)
Mutual labels:  annotations
com2ann
Tool for translation type comments to type annotations in Python
Stars: ✭ 115 (+618.75%)
Mutual labels:  annotations
supervisor-bundle
Easily update your @Supervisor configuration by using annotations in Symfony commands.
Stars: ✭ 35 (+118.75%)
Mutual labels:  symfony-bundle
windigo-android
Windigo is easy to use type-safe rest/http client for android
Stars: ✭ 23 (+43.75%)
Mutual labels:  annotations
features-bundle
Symfony bundle for managing feature tags
Stars: ✭ 18 (+12.5%)
Mutual labels:  symfony-bundle

Annotation Cache Bundle

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


Annotation based caching for method responses in services inside a Symfony container.

This bundle helps you to add caching with a simple annotation or attribute. You can store the cache in any class that implements PSR-6: Caching Interface be it a simple array or a redis/memcache storage.

How it works

This bundle will scan all the methods from the defined services and look for the Cache annotation or attribute (for PHP 8+).

For all the services where the Cache annotation/attribute is found, it will create a proxy class (using ocramius/proxy-manager) that extends the service class, include the CacheableClassTrait and overwrite the methods that have the Cache annotation/attribute.

The overwritten methods consist of a call to the getCached method that identifies the annotation details, gets the key, gets the Cache PSR-6 implementation and then gets the result from cache. If no data with the generated cache key is found, it will call the original method and then save the response in the given provider.

The bundle has a CompilerPass implementation that will search and overwrite the service definition with the proxy class created in the process explained above.

Installation

With Symfony Flex

The easiest way to install and configure the AnnotationCacheBundle with Symfony is by using 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 will automatically register and configure the bundle.

Without Symfony Flex

If your application does not use Symfony Flex you can configure the bundle manually by following the steps below

Step 1: Download the bundle

Open a command console, enter your project directory and execute the following command to download the latest stable version of this bundle:

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

Step 2: Enable the bundle

Then, enable the bundle by adding it to the list of registered bundles in the config/bundles.php file of your project:

// config/bundles.php

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

Step 3: Configuration

The easiest way is to dump the config and copy it to configs/packages/emag_annotation_cache.yaml.

bin/console config:dump-reference AnnotationCacheBundle
Configuration example

You have to configure the name of the service that is PSR6 compliant, that means it will have to implement 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

Usage

Add the Cache annotation for the methods you want to cache.

Annotation parameters:

  • cache - cache prefix, string, default value: null (eg: 'my_custom_prefix_')
  • key - name of argument(s) to include in cache key hash generation, string, arg name separated by a comma, default value: '' (eg: 'a,b')
  • ttl - time to store the cache in seconds, int, default value: 600 (eg: '3600')
  • reset - if the cache should be reset or not, boolean, default value: false (eg: 'true')
  • storage - if multiple providers are defined, you can specify which provider to use, string, default value: 'default' (eg: 'array')

Annotations defined with Doctrine Annotations library

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 ]]]])
 */

Example

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;
    }
}

Annotations defined with PHP 8 attributes

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')]

Example

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;
    }
}

Use cases

Below you can find two ways you can use this Bundle

Config

# 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\\'

Service Code

This bundle can be used in multiple ways, two of them are shown below.

The first case is the most common one, where you have a method that does multiple time-consuming operations, and you want to cache the response in redis with a prefix (simple_time_consuming_operation_) for a given time (60s in the case below). The logic here is to look for the value in redis, and if not found, run the actual method, get the result and cache it for further use taking into account the arguments passed in the @Cache annotation.

The second case could be used if you want to generate the cache in a command and have it already warmed up, or maybe update the cache when a certain event is triggered, or you update the information in a database. Based on the example below, you could set a cron to run every ~3000 seconds and that will recreate the cache before it expires. Because we are using the same cache prefix and keys, when the same argument values are passed for both methods(getTimeConsumingOperationValueWithReset and getTimeConsumingOperationValue), the generated cache key will be the same, in this case: time_consuming_operation_7fe49b314fb356bee76dbd3b8716b4d5ab5db600. That means that both methods will write (and read) the cache in (from) the same cache key. Because the second method has the reset argument set to true, any call to the second method will overwrite the cache value in the key time_consuming_operation_7fe49b314fb356bee76dbd3b8716b4d5ab5db600 with the new result of the function.

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;
    }
}

Service calls

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

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

Contributing

Thanks for your interest in contributing! There are many ways to contribute to this project. Get started here.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].