Skip to content

Commit

Permalink
#334 - added the appPrefix attribute to each of the CacheProviderInte…
Browse files Browse the repository at this point in the history
…rface providers to ensure that multiple apps using the same caching service do not have a key clash
  • Loading branch information
alphadevx committed Jun 10, 2018
1 parent 3ca6a1f commit 66a53ef
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 19 deletions.
23 changes: 19 additions & 4 deletions Alpha/Util/Cache/CacheProviderAPC.php
Expand Up @@ -3,6 +3,7 @@
namespace Alpha\Util\Cache;

use Alpha\Util\Logging\Logger;
use Alpha\Util\Config\ConfigProvider;

/**
* An implementation of the CacheProviderInterface interface that uses APC/APCu as the
Expand Down Expand Up @@ -58,6 +59,16 @@ class CacheProviderAPC implements CacheProviderInterface
*/
private static $logger = null;

/**
* Cache key prefix to use, based on the application title, to prevent key clashes between different apps
* using the same cache provider.
*
* @var string
*
* @since 3.0.0
*/
private $appPrefix;

/**
* Constructor.
*
Expand All @@ -66,6 +77,10 @@ class CacheProviderAPC implements CacheProviderInterface
public function __construct()
{
self::$logger = new Logger('CacheProviderAPC');

$config = ConfigProvider::getInstance();

$this->appPrefix = preg_replace("/[^a-zA-Z0-9]+/", "", $config->get('app.title'));
}

/**
Expand All @@ -76,7 +91,7 @@ public function get($key)
self::$logger->debug('>>get(key=['.$key.'])');

try {
$value = apcu_fetch($key);
$value = apcu_fetch($this->appPrefix.'-'.$key);

self::$logger->debug('<<get: ['.print_r($value, true).'])');

Expand All @@ -96,9 +111,9 @@ public function set($key, $value, $expiry = 0)
{
try {
if ($expiry > 0) {
apcu_store($key, $value, $expiry);
apcu_store($this->appPrefix.'-'.$key, $value, $expiry);
} else {
apcu_store($key, $value);
apcu_store($this->appPrefix.'-'.$key, $value);
}
} catch (\Exception $e) {
self::$logger->error('Error while attempting to store a value to APC cache: ['.$e->getMessage().']');
Expand All @@ -111,7 +126,7 @@ public function set($key, $value, $expiry = 0)
public function delete($key)
{
try {
apcu_delete($key);
apcu_delete($this->appPrefix.'-'.$key);
} catch (\Exception $e) {
self::$logger->error('Error while attempting to remove a value from APC cache: ['.$e->getMessage().']');
}
Expand Down
23 changes: 19 additions & 4 deletions Alpha/Util/Cache/CacheProviderArray.php
Expand Up @@ -3,6 +3,7 @@
namespace Alpha\Util\Cache;

use Alpha\Util\Logging\Logger;
use Alpha\Util\Config\ConfigProvider;

/**
* An implementation of the CacheProviderInterface interface that uses an array as the
Expand Down Expand Up @@ -67,6 +68,16 @@ class CacheProviderArray implements CacheProviderInterface
*/
public static $cacheArray = array();

/**
* Cache key prefix to use, based on the application title, to prevent key clashes between different apps
* using the same cache provider.
*
* @var string
*
* @since 3.0.0
*/
private $appPrefix;

/**
* Constructor.
*
Expand All @@ -75,6 +86,10 @@ class CacheProviderArray implements CacheProviderInterface
public function __construct()
{
self::$logger = new Logger('CacheProviderArray');

$config = ConfigProvider::getInstance();

$this->appPrefix = preg_replace("/[^a-zA-Z0-9]+/", "", $config->get('app.title'));
}

/**
Expand All @@ -86,8 +101,8 @@ public function get($key)

self::$logger->debug('Getting value for key ['.$key.']');

if (array_key_exists($key, self::$cacheArray)) {
return self::$cacheArray[$key];
if (array_key_exists($this->appPrefix.'-'.$key, self::$cacheArray)) {
return self::$cacheArray[$this->appPrefix.'-'.$key];
} else {
return false;
}
Expand All @@ -100,7 +115,7 @@ public function set($key, $value, $expiry = 0)
{
self::$logger->debug('Setting value for key ['.$key.']');

self::$cacheArray[$key] = $value;
self::$cacheArray[$this->appPrefix.'-'.$key] = $value;
}

/**
Expand All @@ -110,6 +125,6 @@ public function delete($key)
{
self::$logger->debug('Removing value for key ['.$key.']');

unset(self::$cacheArray[$key]);
unset(self::$cacheArray[$this->appPrefix.'-'.$key]);
}
}
20 changes: 17 additions & 3 deletions Alpha/Util/Cache/CacheProviderFile.php
Expand Up @@ -59,6 +59,16 @@ class CacheProviderFile implements CacheProviderInterface
*/
private static $logger = null;

/**
* Cache key prefix to use, based on the application title, to prevent key clashes between different apps
* using the same cache provider.
*
* @var string
*
* @since 3.0.0
*/
private $appPrefix;

/**
* Constructor.
*
Expand All @@ -67,6 +77,10 @@ class CacheProviderFile implements CacheProviderInterface
public function __construct()
{
self::$logger = new Logger('CacheProviderFile');

$config = ConfigProvider::getInstance();

$this->appPrefix = preg_replace("/[^a-zA-Z0-9]+/", "", $config->get('app.title'));
}

/**
Expand All @@ -79,7 +93,7 @@ public function get($key)
self::$logger->debug('Getting value for key ['.$key.']');

$config = ConfigProvider::getInstance();
$filepath = $config->get('app.file.store.dir').'/cache/files/'.$key;
$filepath = $config->get('app.file.store.dir').'/cache/files/'.$this->appPrefix.'-'.$key;

if (file_exists($filepath)) {
return unserialize(file_get_contents($filepath));
Expand All @@ -96,7 +110,7 @@ public function set($key, $value, $expiry = 0)
self::$logger->debug('Setting value for key ['.$key.']');

$config = ConfigProvider::getInstance();
$filepath = $config->get('app.file.store.dir').'/cache/files/'.$key;
$filepath = $config->get('app.file.store.dir').'/cache/files/'.$this->appPrefix.'-'.$key;

file_put_contents($filepath, serialize($value));
}
Expand All @@ -109,7 +123,7 @@ public function delete($key)
self::$logger->debug('Removing value for key ['.$key.']');

$config = ConfigProvider::getInstance();
$filepath = $config->get('app.file.store.dir').'/cache/files/'.$key;
$filepath = $config->get('app.file.store.dir').'/cache/files/'.$this->appPrefix.'-'.$key;

unlink($filepath);
}
Expand Down
20 changes: 16 additions & 4 deletions Alpha/Util/Cache/CacheProviderMemcache.php
Expand Up @@ -69,6 +69,16 @@ class CacheProviderMemcache implements CacheProviderInterface
*/
private $connection;

/**
* Cache key prefix to use, based on the application title, to prevent key clashes between different apps
* using the same cache provider.
*
* @var string
*
* @since 3.0.0
*/
private $appPrefix;

/**
* Constructor.
*
Expand All @@ -80,6 +90,8 @@ public function __construct()

$config = ConfigProvider::getInstance();

$this->appPrefix = preg_replace("/[^a-zA-Z0-9]+/", "", $config->get('app.title'));

try {
$this->connection = new Memcached();
$this->connection->addServer($config->get('cache.memcached.host'), $config->get('cache.memcached.port'));
Expand All @@ -97,7 +109,7 @@ public function get($key)
self::$logger->debug('>>get(key=['.$key.'])');

try {
$value = $this->connection->get($key);
$value = $this->connection->get($this->appPrefix.'-'.$key);

self::$logger->debug('<<get: ['.print_r($value, true).'])');

Expand All @@ -117,9 +129,9 @@ public function set($key, $value, $expiry = 0)
{
try {
if ($expiry > 0) {
$this->connection->set($key, $value, $expiry);
$this->connection->set($this->appPrefix.'-'.$key, $value, $expiry);
} else {
$this->connection->set($key, $value);
$this->connection->set($this->appPrefix.'-'.$key, $value);
}
} catch (\Exception $e) {
self::$logger->error('Error while attempting to store a value to Memcached instance: ['.$e->getMessage().']');
Expand All @@ -132,7 +144,7 @@ public function set($key, $value, $expiry = 0)
public function delete($key)
{
try {
$this->connection->delete($key);
$this->connection->delete($this->appPrefix.'-'.$key);
} catch (\Exception $e) {
self::$logger->error('Error while attempting to remove a value from Memcached instance: ['.$e->getMessage().']');
}
Expand Down
20 changes: 16 additions & 4 deletions Alpha/Util/Cache/CacheProviderRedis.php
Expand Up @@ -69,6 +69,16 @@ class CacheProviderRedis implements CacheProviderInterface
*/
private $connection;

/**
* Cache key prefix to use, based on the application title, to prevent key clashes between different apps
* using the same cache provider.
*
* @var string
*
* @since 3.0.0
*/
private $appPrefix;

/**
* Constructor.
*
Expand All @@ -80,6 +90,8 @@ public function __construct()

$config = ConfigProvider::getInstance();

$this->appPrefix = preg_replace("/[^a-zA-Z0-9]+/", "", $config->get('app.title'));

try {
$this->connection = new Redis();
$this->connection->connect($config->get('cache.redis.host'), $config->get('cache.redis.port'));
Expand All @@ -98,7 +110,7 @@ public function get($key)
self::$logger->debug('>>get(key=['.$key.'])');

try {
$value = $this->connection->get($key);
$value = $this->connection->get($this->appPrefix.'-'.$key);

self::$logger->debug('<<get: ['.print_r($value, true).'])');

Expand All @@ -118,9 +130,9 @@ public function set($key, $value, $expiry = 0)
{
try {
if ($expiry > 0) {
$this->connection->setex($key, $expiry, $value);
$this->connection->setex($this->appPrefix.'-'.$key, $expiry, $value);
} else {
$this->connection->set($key, $value);
$this->connection->set($this->appPrefix.'-'.$key, $value);
}
} catch (\Exception $e) {
self::$logger->error('Error while attempting to store a value to Redis instance: ['.$e->getMessage().']');
Expand All @@ -133,7 +145,7 @@ public function set($key, $value, $expiry = 0)
public function delete($key)
{
try {
$this->connection->delete($key);
$this->connection->delete($this->appPrefix.'-'.$key);
} catch (\Exception $e) {
self::$logger->error('Error while attempting to remove a value from Redis instance: ['.$e->getMessage().']');
}
Expand Down
28 changes: 28 additions & 0 deletions test/Alpha/Test/Util/Cache/CacheProviderTest.php
Expand Up @@ -3,6 +3,7 @@
namespace Alpha\Test\Util\Cache;

use Alpha\Util\Service\ServiceFactory;
use Alpha\Util\Config\ConfigProvider;

/**
* Test cases for the CacheProviderInterface implementations.
Expand Down Expand Up @@ -92,4 +93,31 @@ public function testSetGetDelete($provider)

$this->assertFalse($cache->get('cached'), 'Testing the delete method');
}

/**
* Testing the application key prefix is working as expected to prevent collisions
*
* @since 3.0
* @dataProvider getCacheProviders
*/
public function testKeyPrefix($provider)
{
$config = ConfigProvider::getInstance();

$config->set('app.title', 'Application 1');
$cache = ServiceFactory::getInstance($provider, 'Alpha\Util\Cache\CacheProviderInterface');
$cache->set('testkey', 'testkey value for application 1');

$config->set('app.title', 'Application 2');
$cache = ServiceFactory::getInstance($provider, 'Alpha\Util\Cache\CacheProviderInterface');
$cache->set('testkey', 'testkey value for application 2');

$config->set('app.title', 'Application 1');
$cache = ServiceFactory::getInstance($provider, 'Alpha\Util\Cache\CacheProviderInterface');
$this->assertEquals('testkey value for application 1', $cache->get('testkey'));

$config->set('app.title', 'Application 2');
$cache = ServiceFactory::getInstance($provider, 'Alpha\Util\Cache\CacheProviderInterface');
$this->assertEquals('testkey value for application 2', $cache->get('testkey'));
}
}

0 comments on commit 66a53ef

Please sign in to comment.