2

This is my current setup:

snc_redis:
    clients:
        default:
            type: predis
            alias: cache
            dsn: "redis://127.0.0.1"
    doctrine:
            metadata_cache:
                client: cache
                entity_manager: default
                document_manager: default
            result_cache:
                client: cache
                entity_manager: [bo, aff, fs]
            query_cache:
                client: cache
                entity_manager: default

I have an API which gets multiple duplicate requests (usually in quick succession), can I use this setup to send back a cached response on duplicate request? Also is it possible to set cache expiry?

2
  • Are you running the API (i.e. do you want to cache the responses to requests you're receiving) or are you requesting data from an API (i.e. you want to cache the responses from that API)? Commented Aug 24, 2015 at 7:37
  • I am running the API, I want to cache the responses Commented Aug 24, 2015 at 7:38

2 Answers 2

3

From the config sample you provided I'm guessing you want to cache the Doctrine results rather than the full HTTP responses (although the latter is possible, see below).

If so, the easiest way to do this is that whenever you create a Doctrine query, set it to use the result cache which you've set up above to use redis.

$qb = $em->createQueryBuilder();
// do query things
$query = $qb->getQuery();
$query->useResultCache(true, 3600, 'my_cache_id');

This will cache the results for that query for an hour with your cache ID. Clearning the cache is a bit of a faff:

$cache = $em->getConfiguration()->getResultCacheImpl();
$cache->delete('my_cache_id');

If you want to cache full responses - i.e. you do some processing in-app which takes a long time - then there are numerous ways of doing that. Serializing and popping it into redis is possible:

$myResults = $service->getLongRunningResults();
$serialized = serialize($myResults);
$redisClient = $container->get('snc_redis.default');
$redisClient->setex('my_id', $serialized, 3600);

Alternatively look into dedicated HTTP caching solutions like varnish or see the Symfony documentation on HTTP caching.

Edit: The SncRedisBundle provides its own version of Doctrine's CacheProvider. So whereas in your answer you create your own class, you could also do:

my_cache_service:
    class: Snc\RedixBundle\Doctrine\Cache\RedisCache
    calls:
        - [ setRedis, [ @snc_redis.default ] ]

This will do almost exactly what your class is doing. So instead of $app_cache->get('id') you do $app_cache->fetch('id'). This way you can switch out the backend for your cache without changing your app class, just the service description.

Sign up to request clarification or add additional context in comments.

Comments

0

In the end I created a cache manager and registered it as a service called @app_cache.

use Predis;

class CacheManager
{
    protected $cache;

    function __construct()
    {
        $this->client = new Predis\Client();
    }

    /**
     * @return Predis\Client
     */
    public function getInstance()
    {
        return $this->client;
    }
}

In the controller I can then md5 the request_uri

$id = md5($request->getRequestUri()); 

Check it exists, if it does return the $result

if($result = $app_cache->get($id)) {
   return $result;
}

If it doesn't do..whatever...and save the response for next time

$app_cache->set($id,$response);

To set the expiry use the 3rd and 4th parameter ex = seconds and px = milliseconds.

$app_cache->set($id,$response,'ex',3600);

1 Comment

Ah, I see what you were getting at now. I've updated my answer with a solution that might be better.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.