Skip to content
This repository has been archived by the owner on Nov 25, 2020. It is now read-only.

Commit

Permalink
When using APC as cache driver and when in CLI context, we need to fo…
Browse files Browse the repository at this point in the history
…rward delete instructions to server. Group all instructions inside a unique http call at the end of the process.
  • Loading branch information
cdujeu committed Jun 25, 2016
1 parent 0067484 commit 9dd8d3c
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 27 deletions.
133 changes: 106 additions & 27 deletions core/src/plugins/core.cache/AbstractCacheDriver.php
Expand Up @@ -26,11 +26,17 @@
define('AJXP_CACHE_SERVICE_NS_NODES', 'nodes');

use Doctrine\Common\Cache;
use Psr\Http\Message\ResponseInterface;
use Pydio\Access\Core\Model\AJXP_Node;


use Pydio\Cache\Doctrine\Ext\PydioApcuCache;
use Pydio\Core\PluginFramework\Plugin;
use Pydio\Cache\Doctrine\Ext\PatternClearableCache;
use Pydio\Core\Services\ConfService;
use GuzzleHttp\Client;
use Pydio\Core\Utils\ApplicationState;
use Pydio\Log\Core\Logger;

/**
* @package AjaXplorer_Plugins
Expand All @@ -55,6 +61,16 @@ abstract class AbstractCacheDriver extends Plugin
*/
protected $namespacedCaches = array();

/**
* Keep a pointer to an http client if necessary
* @var Client
*/
protected $httpClient;

/**
* @var array
*/
private $httpDeletion = [];

/**
* @param string $namespace
Expand Down Expand Up @@ -104,29 +120,6 @@ public static function computeFullRepositoryId($repositoryId, $cacheType){
return $ID = $cacheType."://".$repositoryId."/";
}

/**
* @param string $namespace
* @return bool
*/
public function supportsPatternDelete($namespace)
{
$cacheDriver = $this->getCacheDriver($namespace);
return $cacheDriver instanceof PatternClearableCache;
}

/**
* @param string $namespace
* @param string $id
* @return bool
*/
public function deleteKeyStartingWith($namespace, $id){
$cacheDriver = $this->getCacheDriver($namespace);
if(!($cacheDriver instanceof PatternClearableCache)){
return false;
}
return $cacheDriver->deleteKeysStartingWith($id);
}

/**
* Fetches an entry from the cache.
*
Expand Down Expand Up @@ -194,11 +187,17 @@ public function save($namespace, $id, $data, $lifeTime = 0){
* @return bool TRUE if the entry was successfully deleted, FALSE otherwise.
*/
public function delete($namespace, $id){

$cacheDriver = $this->getCacheDriver($namespace);
if($this->requiresHttpForwarding($cacheDriver)){
$this->httpDeletion[$namespace.$id.'key'] = ["namespace"=>$namespace, "key" => $id];
return true;
}

if (isset($cacheDriver) && $cacheDriver->contains($id)) {
$result = $cacheDriver->delete($id);
return $result;
Logger::debug("CacheDriver::Http", "Clear Key ".$id, ["namespace" => $namespace]);
$result = $cacheDriver->delete($id);
return $result;
}

return false;
Expand All @@ -212,23 +211,103 @@ public function delete($namespace, $id){
*
*/
public function deleteAll($namespace){

$cacheDriver = $this->getCacheDriver($namespace);
if($this->requiresHttpForwarding($cacheDriver)){
$this->httpDeletion[$namespace.'all'] = ["namespace"=>$namespace, "all" => "true"];
return true;
}

if (isset($cacheDriver)) {
$result = $cacheDriver->deleteAll();
return $result;
Logger::debug("CacheDriver::Http", "Clear All", ["namespace" => $namespace]);
$result = $cacheDriver->deleteAll();
return $result;
}

return false;
}

/**
* @param string $namespace
* @return bool
*/
public function supportsPatternDelete($namespace)
{
$cacheDriver = $this->getCacheDriver($namespace);
return $cacheDriver instanceof PatternClearableCache;
}

/**
* @param string $namespace
* @param string $id
* @return bool
*/
public function deleteKeyStartingWith($namespace, $id){

$cacheDriver = $this->getCacheDriver($namespace);
if($this->requiresHttpForwarding($cacheDriver)){
$this->httpDeletion[$namespace.$id.'pattern'] = ["namespace"=>$namespace, "pattern" => $id];
return true;
}

if(!($cacheDriver instanceof PatternClearableCache)){
return false;
}
Logger::debug("CacheDriver::Http", "Clear Pattern ".$id, ["namespace" => $namespace]);
return $cacheDriver->deleteKeysStartingWith($id);
}


/**
* @return array
*/
public function listNamespaces(){
return [AJXP_CACHE_SERVICE_NS_SHARED, AJXP_CACHE_SERVICE_NS_NODES];
}

/**
* @param $namespace
* @return array|null
*/
public function getStats($namespace){
$cacheDriver = $this->getCacheDriver($namespace);
return $cacheDriver->getStats();
}

/**
* @param CacheProvider
* @return bool
*/
protected function requiresHttpForwarding($cacheDriver){
if(!empty($cacheDriver) && $cacheDriver instanceof PydioApcuCache && ConfService::currentContextIsCommandLine()){
return true;
}
return false;
}

/**
* @return Client
*/
protected function getHttpClient(){
if(!isSet($this->httpClient)){
$this->httpClient = new Client([
'base_url' => ApplicationState::detectServerURL(true)
]);
}
return $this->httpClient;
}

public function __destruct()
{
if(count($this->httpDeletion)){
Logger::debug("CacheDriver::CLI", "Sending cache clear to http", $this->httpDeletion);
$this->getHttpClient()->post('/?get_action=clear_cache_key', [
'body' => [
'data' => json_encode($this->httpDeletion)
]
]);

}
}

}
29 changes: 29 additions & 0 deletions core/src/plugins/core.cache/CoreCacheLoader.php
Expand Up @@ -33,6 +33,7 @@
use Pydio\Access\Core\Model\AJXP_Node;
use Pydio\Core\Utils\Vars\InputFilter;

use Pydio\Log\Core\Logger;
use Zend\Diactoros\Response\JsonResponse;

defined('AJXP_EXEC') or die( 'Access not allowed');
Expand Down Expand Up @@ -238,5 +239,33 @@ public function clearCacheByNS(ServerRequestInterface $requestInterface, Respons

}

/**
* Service to clear a cache key or a pattern
* @param ServerRequestInterface $requestInterface
* @param ResponseInterface $responseInterface
*/
public function clearCacheKey(ServerRequestInterface $requestInterface, ResponseInterface &$responseInterface){
$cacheDriver = ConfService::getCacheDriverImpl();
if($cacheDriver === null) {
$responseInterface = new JsonResponse(["result" => "NOCACHEFOUND"]);
return;
}
$params = $requestInterface->getParsedBody();
$data = json_decode($params["data"], true);
foreach($data as $key => $params){
$ns = $params['namespace'];
if(isSet($params["key"])){
Logger::info("CoreCacheLoader", "Clear Key ".$params["key"], $params);
$cacheDriver->delete($ns, $params["key"]);
}else if(isSet($params["pattern"])){
Logger::info("CoreCacheLoader", "Clear Pattern ".$params["pattern"], $params);
$cacheDriver->deleteKeyStartingWith($ns, $params["pattern"]);
}else if(isSet($params["all"])) {
Logger::info("CoreCacheLoader", "Clear All ", $params);
$cacheDriver->deleteAll($ns);
}
}
$responseInterface = new JsonResponse(["result" => "SUCCESS"]);
}

}
5 changes: 5 additions & 0 deletions core/src/plugins/core.cache/manifest.xml
Expand Up @@ -24,6 +24,11 @@
<serverCallback methodName="clearCacheByNS" restParams="/namespace"/>
</processing>
</action>
<action name="clear_cache_key" skipSecureToken="true">
<processing>
<serverCallback methodName="clearCacheKey" restParams="/namespace"/>
</processing>
</action>
</actions>
<hooks>
<serverCallback methodName="loadNodeInfoFromCache" hookName="node.info.start"/>
Expand Down

0 comments on commit 9dd8d3c

Please sign in to comment.