class MC { private static $_proxy; // Singleton for our class, extended of native Memcache class private static function _proxy() { if (is_null(self::$_proxy) || self::$_proxy->closed) self::$_proxy = new Memcache_Proxy; return self::$_proxy; } public static function get($key = '') { return self::_proxy()->get($key); } public static function set($key = '', $data = NULL, $flag = FALSE, $timeout = 3600) { return self::_proxy()->set($key, $data, $flag, $timeout); } public static function delete($key = '') { return self::_proxy()->delete($key); } public static function increment($key = '', $increment = 1) { return self::_proxy()->increment($key, $increment); } }
class Memcache_Proxy extends Memcache { public $closed = false; public function __construct() { $this->connect(MEMCACHE_HOST, MEMCACHE_PORT, null); $this->closed = false; } function __destruct() { $this->close(); $this->closed = true; } /** * Mirror for $memcache->get() method */ public function get($key = '') { if (empty($key)) return FALSE; $data = parent::get($key); if ($data !== FALSE && $this->_is_valid_cache($data)) { if (!isset($data['_dc_cache'])) $data['_dc_cache'] = NULL; //check lifetime if (time() > $data['_dc_life_end']) { //expired, save the same for a longer time for other connections $this->set($key, $data['_dc_cache'], FALSE, $data['_dc_cache_time']); return FALSE; } else { //still alive return $data['_dc_cache']; } } return FALSE; } /** * Mirror for $memcache->set() method */ public function set($key = '', $data, $flag = FALSE, $timeout = 3600) { if (empty($key)) return FALSE; // Place here "_inc" key check if (is_int($data) || $data === FALSE) parent::delete($key . '_increment'); // Maximum timeout = 15 days - 1 second if ((int)$timeout == 0 || (int)$timeout > 1295999) $timeout = 1295999; return $this->_set($key, $data, $flag, $timeout * 2); } /** * Mirror for $memcache->delete() method */ public function delete($key = '') { if (empty($key)) return FALSE; // Magic for increment. Place here "_inc" key check parent::delete($key . '_increment'); return parent::delete($key); } public function increment($key, $increment = 1) { $inc_value = parent::increment($key . '_increment', $increment); $data = parent::get($key); if ($data === FALSE) return FALSE; if ($this->_is_valid_cache($data)) { if ($inc_value === FALSE) { $inc_value = $data['_dc_cache'] + $increment; parent::set($key . '_increment', $inc_value, FALSE, $data['_dc_cache_time'] * 2); } $time = $data['_dc_life_end'] - time(); if ($time > 0) { $this->_set($key, $inc_value, FALSE, $time); return $inc_value; } } return $inc_value; } private function _set($key = '', $data, $flag = FALSE, $timeout = 3600) { $cache = array('_dc_cache' => $data, '_dc_life_end' => time() + $timeout, '_dc_cache_time' => $timeout); return parent::set($key, $cache, $flag, $timeout); } // Maybe we have pure Memcache data, not our array structure private function _is_valid_cache($value) { return (is_array($value) && isset($value['_dc_life_end']) && isset($value['_dc_cache_time']) && !empty($value['_dc_life_end']) && !empty($value['_dc_cache_time']) ) ? TRUE : FALSE; } }
$data = MC::get('some_key'); if ($data === FALSE) { // $data = huge_generate_func_call(); MC::set('some_key', $data, FALSE, 3600); }
Source: https://habr.com/ru/post/128275/
All Articles