FRED™  3.0
FRED™: Framework for Rapid and Easy Development
Cache.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Rsi\Fred;
4 
5 /**
6  * Wrapper for the Doctrine cache.
7  */
8 class Cache extends Component{
9 
10  const TYPE_ARRAY = 'array';
11  const TYPE_CHAIN = 'chain';
12 
13  public $busyPlaceholder = null; //!< Placeholder for preventing cache slam.
14  public $defaultTtl = null; //!< Default lifetime.
15  public $ttlVariation = null; //!< Variation (plus and minus; percentage) of input value.
16  public $statPrefix = null; //!< Set to something to stat all cache requests (hit/miss).
17 
18  protected $_type = self::TYPE_ARRAY; //!< Cache type to use.
19  protected $_params = null; //!< Parameters (arguments) for this type of cache.
20  protected $_altType = self::TYPE_CHAIN;
21  protected $_altParams = [self::TYPE_ARRAY => null,null => null];
22  protected $_busyTtl = null; //!< Lifetime for cache slam prevention (default = current timeout).
23 
24  protected $_provider = null;
25  protected $_altProvider = null;
26  protected $_useAlt = false;
27  protected $_refresh = false;
28  protected $_refreshed = [];
29  protected $_duploCount = [];
30 
31  protected function init(){
32  parent::init();
33  $this->publish(['type','refresh']);
34  }
35 
36  public function createProvider($type,$params = null){
37  if($type == self::TYPE_CHAIN){
38  $providers = [];
39  foreach($params as $sub_type => $sub_params)
40  $providers[] = $sub_type ? $this->createProvider($sub_type,$sub_params) : $this->_provider;
41  $params = [$providers];
42  }
43  $reflect = new \ReflectionClass('\\Doctrine\\Common\\Cache\\' . ucfirst($type) . 'Cache');
44  return $reflect->newInstanceArgs($params ?: []);
45  }
46  /**
47  * Save data to the cache.
48  * @param string $id Cache id.
49  * @param mixed $data
50  * @param int $ttl Cache lifetime (null = use default, 0 = never expire).
51  */
52  public function save($id,$data,$ttl = null){
53  $log = $this->component('log');
54  $log->debug(__CLASS__ . "::save('$id',...,$ttl)",__FILE__,__LINE__);
55  if($data === false) $log->warning("Saving false in cache for id '$id' (means 'no cache found')",__FILE__,__LINE__);
56  if($this->_refresh) $this->_refreshed[] = $id;
57  if($ttl === null) $ttl = $this->defaultTtl;
58  if($this->ttlVariation) $ttl *= 1 + rand(-1000,1000) * $this->ttlVariation / 100000;
59  return $this->provider->save($id,$data,$ttl);
60  }
61  /**
62  * Fetch with callback function in case cache fails.
63  * @param string $id Cache id.
64  * @param int $ttl Cache lifetime (null = use default, 0 = never expire).
65  * @param function $callback Function to get data if cache fails (parameters: $id; returns data).
66  * @return mixed Data (false on fail).
67  */
68  public function fetch($id,$ttl = null,$callback = null){
69  $time = $this->statPrefix ? microtime(true) : null;
70  do{
71  $data = $this->_refresh && !in_array($id,$this->_refreshed) ? false : $this->provider->fetch($id);
72  if($busy = $this->busyPlaceholder && ($data === $this->busyPlaceholder)) sleep(1);
73  }
74  while($busy);
75  $log = $this->component('log');
76  $log->debug(__CLASS__ . "::fetch('$id',$ttl,...)",__FILE__,__LINE__,['cache' => $id,'found' => $data !== false]);
77  if($data !== false) $time = false;
78  elseif($callback){
79  if($this->busyPlaceholder) $this->save($id,$this->busyPlaceholder,$this->_busyTtl ?: ini_get('max_execution_time'));
80  $this->save($id,$data = call_user_func($callback,$id),$ttl);
81  }
82  if($this->statPrefix) $this->component('stats')->inc(
83  $this->statPrefix . ':' . $id . ':' . ($time ? 'miss' : 'hit'),
84  $time && $callback ? microtime(true) - $time : null
85  );
86  if($this->_fred->debug){
87  if(array_key_exists($id,$this->_duploCount))
88  $log->info('Duplicate fetch' . ($this->_duploCount[$id]++ ? ' (' . $this->_duploCount[$id] . ')' : ''),__FILE__,__LINE__,compact('id','ttl'));
89  else $this->_duploCount[$id] = 0;
90  }
91  return $data;
92  }
93 
94  protected function getProvider(){
95  if(!$this->_provider) $this->_provider = $this->createProvider($this->_type,$this->_params);
96  if(!$this->_useAlt) return $this->_provider;
97  if(!$this->_altProvider) $this->_altProvider = $this->createProvider($this->_altType,$this->_altParams);
98  return $this->_altProvider;
99  }
100 
101  protected function setRefresh($value){
102  $this->_refresh = $value;
103  $this->_refreshed = [];
104  }
105  /**
106  * See vendor/doctrine/cache/lib/Doctrine/Common/Cache/Cache.php for the available functions (save, contains, fetch, delete,
107  * flushAll, getStats) and more explanation.
108  */
109  public function __call($func_name,$params){
110  if($this->_useAlt = substr($func_name,0,1) == '_'){
111  $result = call_user_func_array([$this,substr($func_name,1)],$params);
112  $this->_useAlt = false;
113  return $result;
114  }
115  if(in_array($func_name,['save','contains','fetch','delete']))
116  $this->component('log')->debug(__CLASS__ . "::$func_name('$params[0]')",__FILE__,__LINE__);
117  return call_user_func_array([$this->provider,$func_name],$params);
118  }
119 
120  public function __invoke($id){
121  return $this->provider->fetch($id);
122  }
123 
124 }
fetch($id, $ttl=null, $callback=null)
Fetch with callback function in case cache fails.
Definition: Cache.php:68
Wrapper for the Doctrine cache.
Definition: Cache.php:8
$ttlVariation
Variation (plus and minus; percentage) of input value.
Definition: Cache.php:15
$statPrefix
Set to something to stat all cache requests (hit/miss).
Definition: Cache.php:16
setRefresh($value)
Definition: Cache.php:101
$_busyTtl
Lifetime for cache slam prevention (default = current timeout).
Definition: Cache.php:22
$defaultTtl
Default lifetime.
Definition: Cache.php:14
__invoke($id)
Definition: Cache.php:120
const TYPE_CHAIN
Definition: Cache.php:11
$busyPlaceholder
Placeholder for preventing cache slam.
Definition: Cache.php:13
save($id, $data, $ttl=null)
Save data to the cache.
Definition: Cache.php:52
$_params
Parameters (arguments) for this type of cache.
Definition: Cache.php:19
publish($property, $visibility=self::READABLE)
Publish a property (or hide it again).
Definition: Thing.php:27
Basic component class.
Definition: Component.php:8
__call($func_name, $params)
See vendor/doctrine/cache/lib/Doctrine/Common/Cache/Cache.php for the available functions (save...
Definition: Cache.php:109
const TYPE_ARRAY
Definition: Cache.php:10
createProvider($type, $params=null)
Definition: Cache.php:36
$_type
Cache type to use.
Definition: Cache.php:18
component($name)
Get a component (local or default).
Definition: Component.php:80