Implementation of TTL for caching

This commit is contained in:
Maria Sormanova 2016-07-25 16:14:39 +02:00
parent 5e1db1d1c7
commit 51f8a3056b
8 changed files with 192 additions and 18 deletions

View File

@ -83,6 +83,12 @@ echo $engine->render(
) )
); );
``` ```
upgrading to newer versions
-----
If you are upgrading to the new library version which uses TTL with Disk cache,
first do not forget to delete all the files in the cache directory
created by older versions, since the data structure has changed.
contribution contribution
------------ ------------

View File

@ -9,6 +9,7 @@
* @package Handlebars * @package Handlebars
* @author fzerorubigd <fzerorubigd@gmail.com> * @author fzerorubigd <fzerorubigd@gmail.com>
* @author Behrooz Shabani <everplays@gmail.com> * @author Behrooz Shabani <everplays@gmail.com>
* @author Mária Šormanová <maria.sormanova@gmail.com>
* @copyright 2012 (c) ParsPooyesh Co * @copyright 2012 (c) ParsPooyesh Co
* @copyright 2013 (c) Behrooz Shabani * @copyright 2013 (c) Behrooz Shabani
* @license MIT <http://opensource.org/licenses/MIT> * @license MIT <http://opensource.org/licenses/MIT>
@ -46,14 +47,17 @@ interface Cache
public function get($name); public function get($name);
/** /**
* Set a cache * Set a cache with $ttl, if present
* If $ttl set to -1, the cache expires immediately
* If $ttl set to 0 (default), cache is never purged
* *
* @param string $name cache id * @param string $name cache id
* @param mixed $value data to store * @param mixed $value data to store
* @param int $ttl time to live in seconds
* *
* @return void * @return void
*/ */
public function set($name, $value); public function set($name, $value, $ttl = 0);
/** /**
* Remove cache * Remove cache

View File

@ -9,6 +9,7 @@
* @package Handlebars * @package Handlebars
* @author Joey Baker <joey@byjoeybaker.com> * @author Joey Baker <joey@byjoeybaker.com>
* @author Behrooz Shabani <everplays@gmail.com> * @author Behrooz Shabani <everplays@gmail.com>
* @author Mária Šormanová <maria.sormanova@gmail.com>
* @copyright 2013 (c) Meraki, LLP * @copyright 2013 (c) Meraki, LLP
* @copyright 2013 (c) Behrooz Shabani * @copyright 2013 (c) Behrooz Shabani
* @license MIT <http://opensource.org/licenses/MIT> * @license MIT <http://opensource.org/licenses/MIT>
@ -50,11 +51,12 @@ class APC implements Cache
} }
/** /**
* Get cache for $name if exist. * Get cache for $name if exist
* and if the cache is not older than defined TTL.
* *
* @param string $name Cache id * @param string $name Cache id
* *
* @return mixed data on hit, boolean false on cache not found * @return mixed data on hit, boolean false on cache not found/expired
*/ */
public function get($name) public function get($name)
{ {
@ -66,16 +68,19 @@ class APC implements Cache
} }
/** /**
* Set a cache * Set a cache with $ttl, if present
* If $ttl set to -1, the cache expires immediately
* If $ttl set to 0 (default), cache is never purged
* *
* @param string $name cache id * @param string $name cache id
* @param mixed $value data to store * @param mixed $value data to store
* @param int $ttl time to live in seconds
* *
* @return void * @return void
*/ */
public function set($name, $value) public function set($name, $value, $ttl = 0)
{ {
apc_store($this->_getKey($name), $value); apc_store($this->_getKey($name), $value, $ttl);
} }
/** /**

View File

@ -9,6 +9,7 @@
* @package Handlebars * @package Handlebars
* @author Alex Soncodi <alex@brokerloop.com> * @author Alex Soncodi <alex@brokerloop.com>
* @author Behrooz Shabani <everplays@gmail.com> * @author Behrooz Shabani <everplays@gmail.com>
* @author Mária Šormanová <maria.sormanova@gmail.com>
* @copyright 2013 (c) Brokerloop, Inc. * @copyright 2013 (c) Brokerloop, Inc.
* @copyright 2013 (c) Behrooz Shabani * @copyright 2013 (c) Behrooz Shabani
* @license MIT <http://opensource.org/licenses/MIT> * @license MIT <http://opensource.org/licenses/MIT>
@ -25,6 +26,7 @@ use Handlebars\Cache;
* @category Xamin * @category Xamin
* @package Handlebars * @package Handlebars
* @author Alex Soncodi <alex@brokerloop.com> * @author Alex Soncodi <alex@brokerloop.com>
* @author Mária Šormanová <maria.sormanova@gmail.com>
* @copyright 2013 (c) Brokerloop, Inc. * @copyright 2013 (c) Brokerloop, Inc.
* @license MIT <http://opensource.org/licenses/MIT> * @license MIT <http://opensource.org/licenses/MIT>
* @version Release: @package_version@ * @version Release: @package_version@
@ -81,33 +83,49 @@ class Disk implements Cache
} }
/** /**
* Get cache for $name if it exists. * Get cache for $name if it exists
* and if the cache is not older than defined TTL.
* *
* @param string $name Cache id * @param string $name Cache id
* *
* @return mixed data on hit, boolean false on cache not found * @return mixed data on hit, boolean false on cache not found/expired
*/ */
public function get($name) public function get($name)
{ {
$path = $this->_getPath($name); $path = $this->_getPath($name);
$output = false;
return (file_exists($path)) ? if (file_exists($path)) {
unserialize(file_get_contents($path)) : false; $file = fopen($path, "r");
$ttl = fgets($file);
$ctime = filectime($path);
$time = time();
if ($ttl == -1 || ($ttl > 0 && $time - $ctime > $ttl)) {
unlink($path);
} else {
$serialized_data = fread($file, filesize($path));
$output = unserialize($serialized_data);
}
fclose($file);
}
return $output;
} }
/** /**
* Set a cache * Set a cache with $ttl, if present
* If $ttl set to -1, the cache expires immediately
* If $ttl set to 0 (default), cache is never purged
* *
* @param string $name cache id * @param string $name cache id
* @param mixed $value data to store * @param mixed $value data to store
* @param int $ttl time to live in seconds
* *
* @return void * @return void
*/ */
public function set($name, $value) public function set($name, $value, $ttl = 0)
{ {
$path = $this->_getPath($name); $path = $this->_getPath($name);
file_put_contents($path, serialize($value)); file_put_contents($path, $ttl.PHP_EOL.serialize($value));
} }
/** /**

View File

@ -9,6 +9,7 @@
* @package Handlebars * @package Handlebars
* @author fzerorubigd <fzerorubigd@gmail.com> * @author fzerorubigd <fzerorubigd@gmail.com>
* @author Behrooz Shabani <everplays@gmail.com> * @author Behrooz Shabani <everplays@gmail.com>
* @author Mária Šormanová <maria.sormanova@gmail.com>
* @copyright 2012 (c) ParsPooyesh Co * @copyright 2012 (c) ParsPooyesh Co
* @copyright 2013 (c) Behrooz Shabani * @copyright 2013 (c) Behrooz Shabani
* @license MIT <http://opensource.org/licenses/MIT> * @license MIT <http://opensource.org/licenses/MIT>
@ -55,10 +56,14 @@ class Dummy implements Cache
* *
* @param string $name cache id * @param string $name cache id
* @param mixed $value data to store * @param mixed $value data to store
* @param int $ttl time to live in seconds
*
* $ttl is ignored since the cache is implemented
* by an array and lives only inside one request
* *
* @return void * @return void
*/ */
public function set($name, $value) public function set($name, $value, $ttl = 0)
{ {
$this->_cache[$name] = $value; $this->_cache[$name] = $value;
} }

View File

@ -10,6 +10,7 @@
* @author fzerorubigd <fzerorubigd@gmail.com> * @author fzerorubigd <fzerorubigd@gmail.com>
* @author Behrooz Shabani <everplays@gmail.com> * @author Behrooz Shabani <everplays@gmail.com>
* @author Jeff Turcotte <jeff.turcotte@gmail.com> * @author Jeff Turcotte <jeff.turcotte@gmail.com>
* @author Mária Šormanová <maria.sormanova@gmail.com>
* @copyright 2010-2012 (c) Justin Hileman * @copyright 2010-2012 (c) Justin Hileman
* @copyright 2012 (c) ParsPooyesh Co * @copyright 2012 (c) ParsPooyesh Co
* @copyright 2013 (c) Behrooz Shabani * @copyright 2013 (c) Behrooz Shabani
@ -85,6 +86,13 @@ class Handlebars
*/ */
private $_cache; private $_cache;
/**
* @var int time to live parameter in seconds for the cache usage
* default set to 0 which means that entries stay in cache
* forever and are never purged
*/
private $_ttl = 0;
/** /**
* @var string the class to use for the template * @var string the class to use for the template
*/ */
@ -138,6 +146,10 @@ class Handlebars
$this->setCache($options['cache']); $this->setCache($options['cache']);
} }
if (isset($options['ttl'])) {
$this->setTtl($options['ttl']);
}
if (isset($options['template_class'])) { if (isset($options['template_class'])) {
$this->setTemplateClass($options['template_class']); $this->setTemplateClass($options['template_class']);
} }
@ -337,6 +349,28 @@ class Handlebars
return $this->_cache; return $this->_cache;
} }
/**
* Set time to live for the used cache
*
* @param int $ttl time to live in seconds
*
* @return void
*/
public function setTtl($ttl)
{
$this->_ttl = $ttl;
}
/**
* Get ttl
*
* @return int
*/
public function getTtl()
{
return $this->_ttl;
}
/** /**
* Get current escape function * Get current escape function
* *
@ -545,7 +579,7 @@ class Handlebars
} }
/** /**
* try to tokenize source, or get them from cache if available * Try to tokenize source, or get them from cache if available
* *
* @param string $source handlebars source code * @param string $source handlebars source code
* *
@ -558,7 +592,7 @@ class Handlebars
if ($tree === false) { if ($tree === false) {
$tokens = $this->getTokenizer()->scan($source); $tokens = $this->getTokenizer()->scan($source);
$tree = $this->getParser()->parse($tokens); $tree = $this->getParser()->parse($tokens);
$this->getCache()->set($hash, $tree); $this->getCache()->set($hash, $tree, $this->_ttl);
} }
return $tree; return $tree;

View File

@ -9,6 +9,7 @@
* @package Handlebars * @package Handlebars
* @author fzerorubigd <fzerorubigd@gmail.com> * @author fzerorubigd <fzerorubigd@gmail.com>
* @author Dmitriy Simushev <simushevds@gmail.com> * @author Dmitriy Simushev <simushevds@gmail.com>
* @author Mária Šormanová <maria.sormanova@gmail.com>
* @copyright 2013 (c) f0ruD A * @copyright 2013 (c) f0ruD A
* @license MIT <http://opensource.org/licenses/MIT> * @license MIT <http://opensource.org/licenses/MIT>
* @version GIT: $Id$ * @version GIT: $Id$
@ -92,9 +93,26 @@ class APCTest extends \PHPUnit_Framework_TestCase
$this->assertEquals(20, $driver->get('foo')); $this->assertEquals(20, $driver->get('foo'));
$driver->set('foo', array(22)); $driver->set('foo', array(22));
$this->assertEquals(array(22), $driver->get('foo')); $this->assertEquals(array(22), $driver->get('foo'));
$driver->remove('foo'); $driver->remove('foo');
$this->assertEquals(false, $driver->get('foo')); $this->assertEquals(false, $driver->get('foo'));
} }
/**
* Test ttl
*
* @return void
*/
public function testTtl()
{
$driver = $this->_getCacheDriver();
$driver->set('foo', 10, -1);
$this->assertEquals(false, $driver->get('foo'));
$driver->set('foo', 20, 3600);
$this->assertEquals(20, $driver->get('foo'));
}
} }

View File

@ -0,0 +1,84 @@
<?php
/**
* This file is part of Handlebars-php
* Base on mustache-php https://github.com/bobthecow/mustache.php
*
* PHP version 5.3
*
* @category Xamin
* @package Handlebars
* @author Mária Šormanová <maria.sormanova@gmail.com>
* @copyright 2016 (c) Mária Šormanová
* @license MIT <http://opensource.org/licenses/MIT>
* @version GIT: $Id$
* @link http://xamin.ir
*/
/**
* Test of Disk cache driver
*
* @category Xamin
* @package Handlebars
* @subpackage Test
* @author Mária Šormanová <maria.sormanova@gmail.com>
* @license MIT <http://opensource.org/licenses/MIT>
* @version Release: @package_version@
* @link http://xamin.ir
*/
class DiskTest extends \PHPUnit_Framework_TestCase
{
/**
* {@inheritdoc}
*
* @return void
*/
public function setUp()
{
\Handlebars\Autoloader::register();
}
/**
* Return the new driver
*
* @param string $path folder where the cache is located
*
* @return \Handlebars\Cache\Disk
*/
private function _getCacheDriver( $path = '')
{
return new \Handlebars\Cache\Disk($path);
}
/**
* Test the Disk cache
*
* @return void
*/
public function testDiskCache()
{
$cache_dir = getcwd().'/tests/cache';
$driver = $this->_getCacheDriver($cache_dir);
$this->assertEquals(false, $driver->get('foo'));
$driver->set('foo', "hello world");
$this->assertEquals("hello world", $driver->get('foo'));
$driver->set('foo', "hello world", -1);
$this->assertEquals(false, $driver->get('foo'));
$driver->set('foo', "hello world", 3600);
$this->assertEquals("hello world", $driver->get('foo'));
$driver->set('foo', array(12));
$this->assertEquals(array(12), $driver->get('foo'));
$driver->remove('foo');
$this->assertEquals(false, $driver->get('foo'));
rmdir($cache_dir);
}
}
?>