Closed darkalchemy closed 5 years ago
Hey @darkalchemy
One of the things I really like about the Scrapbook architecture, is that you can just create another class that wraps over the rest, like how most of the features are currently implemented.
You could simply create another class that will relay all function calls to the actual storage, but (de)compresses first. Something like this (untested, might contain syntax errors):
class Compressor implements \MatthiasMullie\Scrapbook\KeyValueStore
{
/**
* @var KeyValueStore
*/
protected $cache;
/**
* @param KeyValueStore $cache
*/
public function __construct(KeyValueStore $cache)
{
$this->cache = $cache;
}
/**
* {@inheritdoc}
*/
public function get($key, &$token = null)
{
$value = $this->cache->get($key, $token);
return $this->decompress($value);
}
/**
* {@inheritdoc}
*/
public function getMulti(array $keys, array &$tokens = null)
{
$values = $this->cache->getMulti($keys, $tokens);
return array_map(function($value) {
return $this->decompress($value);
}, $values);
}
/**
* {@inheritdoc}
*/
public function set($key, $value, $expire = 0)
{
$value = $this->compress($value);
return $this->cache->set($key, $value, $expire ?: $this->defaultExpire);
}
/**
* {@inheritdoc}
*/
public function setMulti(array $items, $expire = 0)
{
$items = array_map(function($value) {
return $this->compress($value);
}, $items);
return $this->cache->setMulti($items, $expire ?: $this->defaultExpire);
}
/**
* {@inheritdoc}
*/
public function delete($key)
{
return $this->cache->delete($key);
}
/**
* {@inheritdoc}
*/
public function deleteMulti(array $keys)
{
return $this->cache->deleteMulti($keys);
}
/**
* {@inheritdoc}
*/
public function add($key, $value, $expire = 0)
{
$value = $this->compress($value);
return $this->cache->add($key, $value, $expire ?: $this->defaultExpire);
}
/**
* {@inheritdoc}
*/
public function replace($key, $value, $expire = 0)
{
$value = $this->compress($value);
return $this->cache->replace($key, $value, $expire ?: $this->defaultExpire);
}
/**
* {@inheritdoc}
*/
public function cas($token, $key, $value, $expire = 0)
{
$value = $this->compress($value);
return $this->cache->cas($token, $key, $value, $expire ?: $this->defaultExpire);
}
/**
* {@inheritdoc}
*/
public function increment($key, $offset = 1, $initial = 0, $expire = 0)
{
// @todo might have to go through uncompressed?
return $this->cache->increment($key, $offset, $initial, $expire ?: $this->defaultExpire);
}
/**
* {@inheritdoc}
*/
public function decrement($key, $offset = 1, $initial = 0, $expire = 0)
{
// @todo might have to go through uncompressed?
return $this->cache->decrement($key, $offset, $initial, $expire ?: $this->defaultExpire);
}
/**
* {@inheritdoc}
*/
public function touch($key, $expire)
{
return $this->cache->touch($key, $expire ?: $this->defaultExpire);
}
/**
* {@inheritdoc}
*/
public function flush()
{
return $this->cache->flush();
}
/**
* {@inheritdoc}
*/
public function getCollection($name)
{
return $this->cache->getCollection($name);
}
/**
* @param string $value
* @return string
*/
protected function compress($value)
{
// @todo gzencode expects string input
// might be ok for your use, or you might have to force $value to string,
// or implement a completely different compression
return gzencode($value, $level, FORCE_GZIP);
}
/**
* @param string $value
* @return string
*/
protected function decompress($value)
{
// @todo same note about strings
return gzdecode($value);
}
}
You would then use it like this:
// create \Memcached object pointing to your Memcached server
$client = new \Memcached();
$client->addServer('localhost', 11211);
// create Scrapbook cache object
$cache = new \MatthiasMullie\Scrapbook\Adapters\Memcached($client);
// add compression layer on top
$cache = new Compressor($cache);
Thanks!
Is there an easy way to implement data compression before storing?
I am thinking I can create new methods that would compress before and decompress after. But, I am looking for a simpler method.
Thanks