From c716acf260af0124e520423ac62be425c69c789f Mon Sep 17 00:00:00 2001 From: MGatner Date: Fri, 30 Apr 2021 19:21:04 +0000 Subject: [PATCH] Improve expiry handling --- system/Cache/CacheInterface.php | 2 +- system/Cache/Handlers/FileHandler.php | 30 +++++++++++++-------- system/Cache/Handlers/MemcachedHandler.php | 9 ++++--- system/Cache/Handlers/PredisHandler.php | 6 +++-- system/Cache/Handlers/RedisHandler.php | 6 +++-- system/Cache/Handlers/WincacheHandler.php | 4 +-- user_guide_src/source/libraries/caching.rst | 2 +- 7 files changed, 37 insertions(+), 22 deletions(-) diff --git a/system/Cache/CacheInterface.php b/system/Cache/CacheInterface.php index b402d43674e3..9e1377a03aae 100644 --- a/system/Cache/CacheInterface.php +++ b/system/Cache/CacheInterface.php @@ -110,7 +110,7 @@ public function getCacheInfo(); * * @return array|false|null * Returns null if the item does not exist, otherwise array - * with at least the 'expires' key for absolute epoch expiry. + * with at least the 'expires' key for absolute epoch expiry (or null). * Some handlers may return false when an item does not exist, which is deprecated. */ public function getMetaData(string $key); diff --git a/system/Cache/Handlers/FileHandler.php b/system/Cache/Handlers/FileHandler.php index 82a3faf17720..4791b3f06a1b 100644 --- a/system/Cache/Handlers/FileHandler.php +++ b/system/Cache/Handlers/FileHandler.php @@ -284,7 +284,7 @@ public function getCacheInfo() * * @return array|false|null * Returns null if the item does not exist, otherwise array - * with at least the 'expires' key for absolute epoch expiry. + * with at least the 'expires' key for absolute epoch expiry (or null). * Some handlers may return false when an item does not exist, which is deprecated. */ public function getMetaData(string $key) @@ -298,23 +298,31 @@ public function getMetaData(string $key) $data = @unserialize(file_get_contents($this->path . $key)); - if (is_array($data)) + if (! is_array($data) || ! isset($data['ttl'])) { - $mtime = filemtime($this->path . $key); + return false; // This will return null in a future release + } + + // Consider expired items as missing + $expire = $data['time'] + $data['ttl']; - if (! isset($data['ttl'])) + // @phpstan-ignore-next-line + if ($data['ttl'] > 0 && time() > $expire) + { + // If the file is still there then remove it + if (is_file($this->path . $key)) { - return false; // This will return null in a future release + unlink($this->path . $key); } - return [ - 'expire' => $data['time'] + $data['ttl'], - 'mtime' => $mtime, - 'data' => $data['data'], - ]; + return false; // This will return null in a future release } - return false; // This will return null in a future release + return [ + 'expire' => $expire, + 'mtime' => filemtime($this->path . $key), + 'data' => $data['data'], + ]; } //-------------------------------------------------------------------- diff --git a/system/Cache/Handlers/MemcachedHandler.php b/system/Cache/Handlers/MemcachedHandler.php index 0cb8089e1ec7..e9a1b919e38b 100644 --- a/system/Cache/Handlers/MemcachedHandler.php +++ b/system/Cache/Handlers/MemcachedHandler.php @@ -344,7 +344,7 @@ public function getCacheInfo() * * @return array|false|null * Returns null if the item does not exist, otherwise array - * with at least the 'expires' key for absolute epoch expiry. + * with at least the 'expires' key for absolute epoch expiry (or null). * Some handlers may return false when an item does not exist, which is deprecated. */ public function getMetaData(string $key) @@ -359,10 +359,13 @@ public function getMetaData(string $key) return false; // This will return null in a future release } - list($data, $time, $ttl) = $stored; + list($data, $time, $limit) = $stored; + + // Calculate the remaining time to live from the original limit + $ttl = time() - $time - $limit; return [ - 'expire' => $time + $ttl, + 'expire' => $limit > 0 ? $time + $limit : null, 'mtime' => $time, 'data' => $data, ]; diff --git a/system/Cache/Handlers/PredisHandler.php b/system/Cache/Handlers/PredisHandler.php index 9567d832cd0b..22c77af27eeb 100644 --- a/system/Cache/Handlers/PredisHandler.php +++ b/system/Cache/Handlers/PredisHandler.php @@ -273,7 +273,7 @@ public function getCacheInfo() * * @return array|false|null * Returns null if the item does not exist, otherwise array - * with at least the 'expires' key for absolute epoch expiry. + * with at least the 'expires' key for absolute epoch expiry (or null). */ public function getMetaData(string $key) { @@ -282,8 +282,10 @@ public function getMetaData(string $key) if (isset($data['__ci_value']) && $data['__ci_value'] !== false) { $time = time(); + $ttl = $this->redis->ttl($key); + return [ - 'expire' => $time + $this->redis->ttl($key), + 'expire' => $ttl > 0 ? time() + $ttl : null, 'mtime' => $time, 'data' => $data['__ci_value'], ]; diff --git a/system/Cache/Handlers/RedisHandler.php b/system/Cache/Handlers/RedisHandler.php index 442c7aaf7023..29c6a6fa8905 100644 --- a/system/Cache/Handlers/RedisHandler.php +++ b/system/Cache/Handlers/RedisHandler.php @@ -319,7 +319,7 @@ public function getCacheInfo() * * @return array|null * Returns null if the item does not exist, otherwise array - * with at least the 'expires' key for absolute epoch expiry. + * with at least the 'expires' key for absolute epoch expiry (or null). */ public function getMetaData(string $key) { @@ -330,8 +330,10 @@ public function getMetaData(string $key) if ($value !== null) { $time = time(); + $ttl = $this->redis->ttl($key); + return [ - 'expire' => $time + $this->redis->ttl($key), + 'expire' => $ttl > 0 ? time() + $ttl : null, 'mtime' => $time, 'data' => $value, ]; diff --git a/system/Cache/Handlers/WincacheHandler.php b/system/Cache/Handlers/WincacheHandler.php index 6cb329ec779b..f925a6ea4f6f 100644 --- a/system/Cache/Handlers/WincacheHandler.php +++ b/system/Cache/Handlers/WincacheHandler.php @@ -212,7 +212,7 @@ public function getCacheInfo() * * @return array|false|null * Returns null if the item does not exist, otherwise array - * with at least the 'expires' key for absolute epoch expiry. + * with at least the 'expires' key for absolute epoch expiry (or null). * Some handlers may return false when an item does not exist, which is deprecated. * * @codeCoverageIgnore @@ -228,7 +228,7 @@ public function getMetaData(string $key) $hitcount = $stored['ucache_entries'][1]['hitcount']; return [ - 'expire' => time() + $ttl, + 'expire' => $ttl > 0 ? time() + $ttl : null, 'hitcount' => $hitcount, 'age' => $age, 'ttl' => $ttl, diff --git a/user_guide_src/source/libraries/caching.rst b/user_guide_src/source/libraries/caching.rst index 01dadc700308..9a9f22eb0471 100644 --- a/user_guide_src/source/libraries/caching.rst +++ b/user_guide_src/source/libraries/caching.rst @@ -216,7 +216,7 @@ Class Reference .. php:method:: getMetadata(string $key) :param string $key: Cache item name - :returns: Metadata for the cached item with at least the "expires" key for absolute epoch expiry, ``null`` for missing items. + :returns: Metadata for the cached item. ``null`` for missing items, or an array with at least the "expire" key for absolute epoch expiry (``null`` for never expires). :rtype: array|null This method will return detailed information on a specific item in the