Reputation: 159
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?
Upvotes: 2
Views: 1328
Reputation: 159
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);
Upvotes: 0
Reputation:
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.
Upvotes: 3