Created
May 23, 2020 00:44
-
-
Save doried-a-a/d4c577abcf456bf1a72facb352b23260 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
use Liip\ImagineBundle\Binary\BinaryInterface; | |
use Liip\ImagineBundle\Imagine\Cache\Resolver\ResolverInterface; | |
use Predis\Client; | |
use Symfony\Component\Messenger\MessageBusInterface; | |
class CacheResolver implements ResolverInterface | |
{ | |
protected $redis; | |
protected $redisImageServer; | |
protected $messengerBus; | |
public function __construct(Client $imageCacheRedisClient, | |
MessageBusInterface $bus, | |
RedisImageServer $redisImageServer | |
){ | |
$this->redis = $imageCacheRedisClient; | |
$this->redisImageServer = $redisImageServer; | |
$this->messengerBus = $bus; | |
$this->cachePrefix = "image_cache"; | |
} | |
private function getKey($path, $filter){ | |
$pathKey = $path? md5($path) : ""; | |
return "image_cache_$filter-$pathKey"; | |
} | |
public function isStored($path, $filter) | |
{ | |
$key = $this->getKey($path, $filter); | |
# If we don't have any entries for this image in Redis yet, then no filter was generated | |
list($isStored, $content) = $this->redis->mget([$key."_stored", $key."_content"]); | |
if( ($isStored && $isStored !== "false") || $content != null) return true; | |
return false; | |
} | |
public function resolve($path, $filter) | |
{ | |
$key = $this->getKey($path, $filter); | |
# If this function was called, there should always be a redis entry (as isStored won't return true unless there is) | |
$isStored = $this->redis->get($key."_stored"); | |
# if the result was already stored in permanent storage, return the image path from there | |
# replace following piece of code with something that retuns a deterministic path to your image/filter in your permanent storage (cloud storage) | |
if($isStored && $isStored !== "false") return $this->mountManager->getWebUrl($this->getFileUrl($path, $filter)); | |
# otherwise, serve it from redis. | |
# $redisImageServer is just a symfony-service that would return a url to the nodejs service we'll cleate. You can replace this directly | |
# with something like localhost:8008/get/$key, if you wanted to run the nodejs image service on port 8008 | |
else return $this->redisImageServer->getUrlForImage($key); | |
} | |
public function store(BinaryInterface $binary, $path, $filter) | |
{ | |
$key = $this->getKey($path, $filter); | |
$values = [ | |
$key."_stored" => false, | |
$key.'_content' => base64_encode($binary->getContent()) | |
]; | |
$this->redis->mset($values); | |
$this->redis->expire($key."_content", 60*60); | |
try { | |
# this part is to send a message to symfony-messenger that an image filter got applied. You need to configure Messenger correctly | |
$this->messengerBus->dispatch(new ImageFilterAppliedMessage($key, $this->getFileUrl($path, $filter))); | |
} catch (\AMQPConnectionException $ee){ | |
error_log("AMQP: could not send ImageFilterAppliedMessage"); | |
} | |
} | |
public function remove(array $paths, array $filters) | |
{ | |
# you'll find a way to implement this ;) it does not matter for this demo | |
} | |
protected function getFileUrl($path, $filter) | |
{ | |
// crude way of sanitizing URL scheme ("protocol") part | |
$path = str_replace('://', '---', $path); | |
return $this->cachePrefix.'/'.$filter.'/'.ltrim($path, '/'); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment