From 3ae02f36026a72aefcd8ae8cd2fa4fa8b2dcdac1 Mon Sep 17 00:00:00 2001 From: Spine Date: Wed, 1 Feb 2023 03:42:31 +0000 Subject: [PATCH] gut local caching in PHP instance --- app/Applicant.php | 4 +- app/ApplicantRole.php | 2 +- app/Artist.php | 9 +- app/Cache.php | 417 +++++--------------- app/Collage.php | 2 +- app/Collage/AbstractCollage.php | 3 +- app/Collage/TGroup.php | 3 +- app/Comment/AbstractComment.php | 4 +- app/Debug.php | 35 +- app/Forum.php | 2 +- app/ForumThread.php | 2 +- app/Inbox.php | 3 +- app/Json/AddLog.php | 2 +- app/Manager/Blog.php | 3 +- app/Manager/Bonus.php | 6 +- app/Manager/Comment.php | 3 +- app/Manager/Donation.php | 7 +- app/Manager/News.php | 7 +- app/Manager/Payment.php | 3 +- app/Manager/Privilege.php | 2 +- app/Manager/Session.php | 3 +- app/Manager/StaffBlog.php | 4 +- app/Manager/Subscription.php | 3 +- app/Manager/TGroup.php | 12 +- app/Manager/User.php | 10 +- app/Privilege.php | 4 +- app/Request.php | 4 +- app/Schedule/Tasks/ExpireTagSnatchCache.php | 2 +- app/StaffPM.php | 2 +- app/Stats/User.php | 2 +- app/TGroup.php | 12 +- app/Top10/Torrent.php | 5 +- app/Torrent.php | 4 +- app/User.php | 8 +- app/User/Bonus.php | 4 +- app/User/Bookmark.php | 4 +- app/User/Session.php | 4 +- app/User/Subscription.php | 4 +- app/User/Vote.php | 2 +- app/Util/CacheMultiFlush.php | 2 +- classes/view.class.php | 3 +- gazelle.php | 5 - public/static/functions/debug.js | 1 + scripts/rebuild-votes | 2 +- sections/artist/rename.php | 2 +- sections/reportsv2/takeresolve.php | 2 +- sections/requests/take_new_edit.php | 2 +- sections/tools/development/clear_cache.php | 2 +- sections/tools/managers/ocelot.php | 2 +- sections/torrents/download.php | 2 +- sections/torrents/editgroupid.php | 2 +- sections/torrents/takechangecategory.php | 2 +- sections/torrents/takenewgroup.php | 2 +- sections/upload/upload_handle.php | 4 +- sections/user/index.php | 2 +- sections/user/notify_handle.php | 2 +- templates/debug/cache.twig | 37 +- templates/index/private-footer.twig | 2 +- tests/phpunit/CacheTest.php | 55 +++ 59 files changed, 273 insertions(+), 472 deletions(-) create mode 100644 tests/phpunit/CacheTest.php diff --git a/app/Applicant.php b/app/Applicant.php index 119c7de6a..e7812c806 100644 --- a/app/Applicant.php +++ b/app/Applicant.php @@ -47,7 +47,7 @@ class Applicant extends Base { } protected function flushApplicantList() { - self::$cache->deleteMulti([ + self::$cache->delete_multi([ 'user_applicant_' . $this->userId, self::CACHE_KEY_NEW_COUNT, self::CACHE_KEY_NEW_REPLY, @@ -113,7 +113,7 @@ class Applicant extends Base { $data = self::$cache->get_value($key); if ($data !== false) { $data['Resolved'] = $this->resolved; - self::$cache->replace_value($key, $data, 86400); + self::$cache->cache_value($key, $data, 86400); } self::$cache->delete_value('user_applicant_' . $this->userId); return $this->flushApplicantList(); diff --git a/app/ApplicantRole.php b/app/ApplicantRole.php index 6d96fa7cd..bee44c02e 100644 --- a/app/ApplicantRole.php +++ b/app/ApplicantRole.php @@ -84,7 +84,7 @@ class ApplicantRole extends Base { $this->id); self::$cache->delete_value(self::CACHE_KEY_ALL); self::$cache->delete_value(self::CACHE_KEY_PUBLISHED); - self::$cache->replace_value(sprintf(self::CACHE_KEY, $this->id), + self::$cache->cache_value(sprintf(self::CACHE_KEY, $this->id), [ 'Title' => $this->title, 'Published' => $this->published, diff --git a/app/Artist.php b/app/Artist.php index f246ba350..ef3931380 100644 --- a/app/Artist.php +++ b/app/Artist.php @@ -112,10 +112,7 @@ class Artist extends Base { WHERE ArtistID = ? ", $this->id ); - $cacheKeys = self::$db->collect(0, false); - self::$cache->deleteMulti($cacheKeys); - self::$cache->delete_value($this->cacheKey()); - return count($cacheKeys); + return count(self::$cache->delete_multi([$this->cacheKey(), ...self::$db->collect(0, false)])); } protected function loadAttr(): array { @@ -709,7 +706,7 @@ class Artist extends Base { $this->flushCache(); $similar->flushCache(); - self::$cache->deleteMulti(["similar_positions_$artistId", "similar_positions_$similarArtistId"]); + self::$cache->delete_multi(["similar_positions_$artistId", "similar_positions_$similarArtistId"]); } public function removeSimilar(int $similarId, Manager\Artist $artMan, Manager\Request $reqMan): bool { @@ -991,7 +988,7 @@ class Artist extends Base { $similarArtist = new Artist($similarArtistId, 0); $this->flushCache(); $similarArtist->flushCache(); - self::$cache->deleteMulti(["similar_positions_" . $this->id, "similar_positions_$similarArtistId"]); + self::$cache->delete_multi(["similar_positions_" . $this->id, "similar_positions_$similarArtistId"]); return true; } diff --git a/app/Cache.php b/app/Cache.php index 4e6eeeccf..2b2cc6d9e 100644 --- a/app/Cache.php +++ b/app/Cache.php @@ -10,10 +10,6 @@ This class is a wrapper for the Memcache class, and it's been written in order to better handle the caching of full pages with bits of dynamic content that are different for every user. -As this inherits memcache, all of the default memcache methods work - -however, this class has page caching functions superior to those of -memcache. - Also, Memcache::get and Memcache::set have been wrapped by Gazelle\Cache::get_value and Gazelle\Cache::cache_value. get_value uses the same argument as get, but cache_value only takes the key, the value, @@ -33,20 +29,9 @@ class Cache extends \Memcached { */ const GROUP_VERSION = 6; - protected array $CacheHits = []; - protected array $ClearedKeys = []; - protected array $Servers = []; - protected array $MemcacheDBArray = []; - protected string $MemcacheDBKey = ''; - - protected bool $InTransaction = false; - protected bool $CanClear = false; - protected bool $InternalCache = true; - - protected string $PersistentKeysRegexp = - '/^(?:global_notification$|(?:ajax_requests|query_lock|stats|top10(?:tor|votes)|users_snatched)_)/'; - - public $Time = 0; + protected array $hit; + protected array $delete; + protected float $elapsed; /** * Constructor. Takes a array of $Servers with a host, port, and optionally a weight. @@ -57,16 +42,19 @@ class Cache extends \Memcached { * the $ServerList as Memcached really doesn't like the same server being added hundreds of time * with the same weight. * + * This looks far more complicated than it should be - Spine + * * @see Memcached::getServerList() */ public function __construct() { + $begin = microtime(true); parent::__construct(CACHE_ID); - $this->Servers = MEMCACHE_HOST_LIST; + $Servers = MEMCACHE_HOST_LIST; $ServerList = []; foreach ($this->getServerList() as $Server) { $ServerList["{$Server['host']}:{$Server['port']}"] = true; } - foreach ($this->Servers as $Server) { + foreach ($Servers as $Server) { $ServerCheck = isset($ServerList["{$Server['host']}:{$Server['port']}"]); if ($Server['port'] == 0) { $ServerCheck = $ServerCheck || isset($ServerList["{$Server['host']}:11211"]); @@ -76,332 +64,89 @@ class Cache extends \Memcached { $this->addServer($Server['host'], $Server['port'], $Weight); } } - } - - public function enableCacheClear() { - $this->CanClear = true; - return $this; - } - - public function disableCacheClear() { - $this->CanClear = false; - return $this; - } - - public function enableLocalCache() { - $this->InternalCache = true; - return $this; - } - - public function disableLocalCache() { - $this->InternalCache = false; - return $this; - } - - public function hits(): array { - return $this->CacheHits; + $this->elapsed = (microtime(true) - $begin) * 1000; } //---------- Caching functions ----------// // Wrapper for Memcache::set, with the zlib option removed and default duration of 30 days - public function cache_value($Key, $Value, $Duration = 2592000) { - $StartTime = microtime(true); + public function cache_value($Key, $value, $Duration = 2592000) { + $begin = microtime(true); if (empty($Key)) { trigger_error("Cache insert failed for empty key"); } - if (!$this->set($Key, $Value, $Duration)) { + if (!$this->set($Key, $value, $Duration)) { trigger_error("Cache insert failed for key $Key:" . $this->getResultMessage()); } - if ($this->InternalCache && array_key_exists($Key, $this->CacheHits)) { - $this->CacheHits[$Key] = $Value; - } - $this->Time += (microtime(true) - $StartTime) * 1000; + $this->elapsed += (microtime(true) - $begin) * 1000; } - // Wrapper for Memcache::add, with the zlib option removed and default duration of 30 days - public function add_value($Key, $Value, $Duration = 2592000) { - $StartTime = microtime(true); - $Added = $this->add($Key, $Value, $Duration); - $this->Time += (microtime(true) - $StartTime) * 1000; - return $Added; - } - - public function replace_value($Key, $Value, $Duration = 2592000) { - $StartTime = microtime(true); - $this->replace($Key, $Value, $Duration); - if ($this->InternalCache && array_key_exists($Key, $this->CacheHits)) { - $this->CacheHits[$Key] = $Value; - } - $this->Time += (microtime(true) - $StartTime) * 1000; - } - - public function get_value($Key, $NoCache = false) { - if (!$this->InternalCache) { - $NoCache = true; - } - $StartTime = microtime(true); - if (empty($Key)) { - trigger_error('Cache retrieval failed for empty key'); - } - - if (!empty($_GET['clearcache']) && $this->CanClear && !isset($this->ClearedKeys[$Key]) && !preg_match($this->PersistentKeysRegexp, $Key)) { - if ($_GET['clearcache'] === '1') { - if (count($this->CacheHits) > 0) { - foreach (array_keys($this->CacheHits) as $HitKey) { - if (!isset($this->ClearedKeys[$HitKey]) && !preg_match($this->PersistentKeysRegexp, $Key)) { - $this->delete($HitKey); - unset($this->CacheHits[$HitKey]); - $this->ClearedKeys[$HitKey] = true; - } - } - } - $this->delete($Key); - $this->Time += (microtime(true) - $StartTime) * 1000; - return false; - } elseif ($_GET['clearcache'] == $Key) { - $this->delete($Key); - $this->Time += (microtime(true) - $StartTime) * 1000; - return false; - } elseif (substr($_GET['clearcache'], -1) === '*') { - $Prefix = substr($_GET['clearcache'], 0, -1); - if ($Prefix === '' || $Prefix === substr($Key, 0, strlen($Prefix))) { - $this->delete($Key); - $this->Time += (microtime(true) - $StartTime) * 1000; - return false; - } + public function get_value(string $key) { + $begin = microtime(true); + if (empty($key)) { + $value = false; + } else { + $value = $this->get($key); + if (!isset($this->hit[$key])) { + $this->hit[$key] = 0; } - $this->ClearedKeys[$Key] = true; + ++$this->hit[$key]; } - - // For cases like the forums, if a key is already loaded, grab the existing pointer - if (isset($this->CacheHits[$Key]) && !$NoCache) { - $this->Time += (microtime(true) - $StartTime) * 1000; - return $this->CacheHits[$Key]; - } - - $Return = $this->get($Key); - if ($Return !== false && !$NoCache) { - $this->CacheHits[$Key] = $Return; - } - $this->Time += (microtime(true) - $StartTime) * 1000; - return $Return; + $this->elapsed += (microtime(true) - $begin) * 1000; + return $value; } // Wrapper for Memcache::delete. For a reason, see above. - public function delete_value($Key) { - $StartTime = microtime(true); - if (empty($Key)) { - trigger_error('Cache deletion failed for empty key'); + public function delete_value(string $key) { + $begin = microtime(true); + if (empty($key)) { + $ret = false; + } else { + $ret = $this->delete($key); + if (!isset($this->delete)) { + $this->delete = []; + } + $this->delete[] = $key; } - $ret = $this->delete($Key); - unset($this->CacheHits[$Key]); - $this->Time += (microtime(true) - $StartTime) * 1000; + $this->elapsed += (microtime(true) - $begin) * 1000; + return $ret; + } + public function delete_multi(array $list) { + $begin = microtime(true); + if (empty($list)) { + $ret = false; + } else { + $ret = $this->deleteMulti($list); + if (!isset($this->delete)) { + $this->delete = $list; + } else { + array_push($this->delete, ...$list); + } + } + $this->elapsed += (microtime(true) - $begin) * 1000; return $ret; } - public function increment_value($Key, $Value = 1) { - $StartTime = microtime(true); - $NewVal = $this->increment($Key, $Value); - if (isset($this->CacheHits[$Key])) { - $this->CacheHits[$Key] = $NewVal; + public function increment_value(string $key, int $delta = 1): int { + $begin = microtime(true); + $new = $this->increment($key, $delta); + if (!isset($this->hit[$key])) { + $this->hit[$key] = 0; } - $this->Time += (microtime(true) - $StartTime) * 1000; + ++$this->hit[$key]; + $this->elapsed += (microtime(true) - $begin) * 1000; + return $new; } - public function decrement_value($Key, $Value = 1) { - $StartTime = microtime(true); - $NewVal = $this->decrement($Key, $Value); - if (isset($this->CacheHits[$Key])) { - $this->CacheHits[$Key] = $NewVal; + public function decrement_value($key, $delta = 1): int { + $begin = microtime(true); + $new = $this->decrement($key, $delta); + if (!isset($this->hit[$key])) { + $this->hit[$key] = 0; } - $this->Time += (microtime(true) - $StartTime) * 1000; - } - - //---------- memcachedb functions ----------// - - public function begin_transaction($Key) { - $Value = $this->get($Key); - if (!is_array($Value)) { - $this->InTransaction = false; - $this->MemcacheDBKey = ''; - return false; - } - $this->MemcacheDBArray = $Value; - $this->MemcacheDBKey = $Key; - $this->InTransaction = true; - return true; - } - - public function cancel_transaction() { - $this->InTransaction = false; - $this->MemcacheDBKey = ''; - } - - public function commit_transaction($Time = 2592000) { - if (!$this->InTransaction) { - return false; - } - self::cache_value($this->MemcacheDBKey, $this->MemcacheDBArray, $Time); - $this->InTransaction = false; - } - - // Updates multiple rows in an array - public function update_transaction($Rows, $Values) { - if (!$this->InTransaction) { - return false; - } - $Array = $this->MemcacheDBArray; - if (is_array($Rows)) { - $i = 0; - $Keys = $Rows[0]; - $Property = $Rows[1]; - foreach ($Keys as $Row) { - $Array[$Row][$Property] = $Values[$i]; - $i++; - } - } else { - $Array[$Rows] = $Values; - } - $this->MemcacheDBArray = $Array; - } - - // Updates multiple values in a single row in an array - // $Values must be an associative array with key:value pairs like in the array we're updating - public function update_row($Row, $Values) { - if (!$this->InTransaction) { - return false; - } - if ($Row === false) { - $UpdateArray = $this->MemcacheDBArray; - } else { - $UpdateArray = $this->MemcacheDBArray[$Row]; - } - foreach ($Values as $Key => $Value) { - if (!array_key_exists($Key, $UpdateArray)) { - trigger_error('Bad transaction key ('.$Key.') for cache '.$this->MemcacheDBKey); - } - if ($Value === '+1') { - if (!is_number($UpdateArray[$Key])) { - trigger_error('Tried to increment non-number ('.$Key.') for cache '.$this->MemcacheDBKey); - } - ++$UpdateArray[$Key]; // Increment value - } elseif ($Value === '-1') { - if (!is_number($UpdateArray[$Key])) { - trigger_error('Tried to decrement non-number ('.$Key.') for cache '.$this->MemcacheDBKey); - } - --$UpdateArray[$Key]; // Decrement value - } else { - $UpdateArray[$Key] = $Value; // Otherwise, just alter value - } - } - if ($Row === false) { - $this->MemcacheDBArray = $UpdateArray; - } else { - $this->MemcacheDBArray[$Row] = $UpdateArray; - } - } - - // Increments multiple values in a single row in an array - // $Values must be an associative array with key:value pairs like in the array we're updating - public function increment_row($Row, $Values) { - if (!$this->InTransaction) { - return false; - } - if ($Row === false) { - $UpdateArray = $this->MemcacheDBArray; - } else { - $UpdateArray = $this->MemcacheDBArray[$Row]; - } - foreach ($Values as $Key => $Value) { - if (!array_key_exists($Key, $UpdateArray)) { - trigger_error("Bad transaction key ($Key) for cache ".$this->MemcacheDBKey); - } - if (!is_number($Value)) { - trigger_error("Tried to increment with non-number ($Key) for cache ".$this->MemcacheDBKey); - } - $UpdateArray[$Key] += $Value; // Increment value - } - if ($Row === false) { - $this->MemcacheDBArray = $UpdateArray; - } else { - $this->MemcacheDBArray[$Row] = $UpdateArray; - } - } - - // Insert a value at the beginning of the array - public function insert_front($Key, $Value) { - if (!$this->InTransaction) { - return false; - } - if ($Key === '') { - array_unshift($this->MemcacheDBArray, $Value); - } else { - $this->MemcacheDBArray = [$Key=>$Value] + $this->MemcacheDBArray; - } - } - - // Insert a value at the end of the array - public function insert_back($Key, $Value) { - if (!$this->InTransaction) { - return false; - } - if ($Key === '') { - array_push($this->MemcacheDBArray, $Value); - } else { - $this->MemcacheDBArray = $this->MemcacheDBArray + [$Key=>$Value]; - } - - } - - public function insert($Key, $Value) { - if (!$this->InTransaction) { - return false; - } - if ($Key === '') { - $this->MemcacheDBArray[] = $Value; - } else { - $this->MemcacheDBArray[$Key] = $Value; - } - } - - public function delete_row($Row) { - if (!$this->InTransaction) { - return false; - } - if (!isset($this->MemcacheDBArray[$Row])) { - trigger_error("Tried to delete non-existent row ($Row) for cache ".$this->MemcacheDBKey); - } - unset($this->MemcacheDBArray[$Row]); - } - - public function update($Key, $Rows, $Values, $Time = 2592000) { - if (!$this->InTransaction) { - $this->begin_transaction($Key); - $this->update_transaction($Rows, $Values); - $this->commit_transaction($Time); - } else { - $this->update_transaction($Rows, $Values); - } - } - - /** - * Tries to set a lock. Expiry time is one hour to avoid indefinite locks - * - * @param string $LockName name on the lock - * @return true if lock was acquired - */ - public function get_query_lock($LockName) { - return $this->add_value('query_lock_'.$LockName, 1, 3600); - } - - /** - * Remove lock - * - * @param string $LockName name on the lock - */ - public function clear_query_lock($LockName) { - $this->delete_value('query_lock_'.$LockName); + ++$this->hit[$key]; + $this->elapsed += (microtime(true) - $begin) * 1000; + return $new; } /** @@ -409,11 +154,31 @@ class Cache extends \Memcached { * * @return array (host => bool status, ...) */ - public function server_status() { - /*$Status = []; - foreach ($this->Servers as $Server) { - $Status["$Server[host]:$Server[port]"] = $this->getServerStatus($Server['host'], $Server['port']); - }*/ + public function server_status(): array { return $this->getStats(); } + + public function elapsed(): float { + return $this->elapsed; + } + + public function deleteList(): array { + $delete = $this->delete ?? []; + sort($delete); + return $delete; + } + + public function deleteListTotal(): int { + return count($this->delete ?? []); + } + + public function hitList(): array { + $hit = $this->hit ?? []; + ksort($hit); + return $hit; + } + + public function hitListTotal(): int { + return count($this->hit ?? []); + } } diff --git a/app/Collage.php b/app/Collage.php index d91a26ca7..4a15cb207 100644 --- a/app/Collage.php +++ b/app/Collage.php @@ -185,7 +185,7 @@ class Collage extends BaseObject { WHERE ID = ? ", $delta, $this->id ); - self::$cache->deleteMulti([ + self::$cache->delete_multi([ sprintf(self::SUBS_KEY, $userId), sprintf(self::SUBS_NEW_KEY, $userId), ]); diff --git a/app/Collage/AbstractCollage.php b/app/Collage/AbstractCollage.php index 2d8950fe7..453f15162 100644 --- a/app/Collage/AbstractCollage.php +++ b/app/Collage/AbstractCollage.php @@ -3,7 +3,6 @@ namespace Gazelle\Collage; abstract class AbstractCollage extends \Gazelle\Base { - protected \Gazelle\Collage $holder; protected int $id; // hold a local copy of our ID to save time @@ -63,7 +62,7 @@ abstract class AbstractCollage extends \Gazelle\Base { if (self::$db->has_results()) { array_push($keys, ...self::$db->collect(0, false)); } - self::$cache->deleteMulti($keys); + self::$cache->delete_multi($keys); $this->holder->flush(); return $this; } diff --git a/app/Collage/TGroup.php b/app/Collage/TGroup.php index dc828f9b3..4f8b272bb 100644 --- a/app/Collage/TGroup.php +++ b/app/Collage/TGroup.php @@ -3,7 +3,6 @@ namespace Gazelle\Collage; class TGroup extends AbstractCollage { - protected array $groupIds = []; protected array $sequence = []; protected array $torrentTags = []; @@ -105,7 +104,7 @@ class TGroup extends AbstractCollage { SELECT GroupID FROM collages_torrents WHERE CollageID = ? ", $this->id ); - self::$cache->deleteMulti(array_merge(...array_map( + self::$cache->delete_multi(array_merge(...array_map( fn ($id) => ["torrents_details_$id", "torrent_collages_$id", "torrent_collages_personal_$id"], self::$db->collect(0, false) ))); diff --git a/app/Comment/AbstractComment.php b/app/Comment/AbstractComment.php index 8e8221ecf..6daae782c 100644 --- a/app/Comment/AbstractComment.php +++ b/app/Comment/AbstractComment.php @@ -264,7 +264,7 @@ abstract class AbstractComment extends \Gazelle\BaseObject { ); // Update the cache - self::$cache->deleteMulti([ + self::$cache->delete_multi([ "edit_{$page}_" . $this->id, "{$page}_comments_" . $this->pageId, sprintf(\Gazelle\Manager\Comment::CATALOG, $page, $this->pageId, @@ -312,7 +312,7 @@ abstract class AbstractComment extends \Gazelle\BaseObject { (new \Gazelle\Manager\Subscription)->flushPage($page, $this->pageId); - self::$cache->deleteMulti([ + self::$cache->delete_multi([ "edit_{$page}_" . $this->id, "{$page}_comments_" . $this->pageId, ]); diff --git a/app/Debug.php b/app/Debug.php index 109c0f573..72c5b5e96 100644 --- a/app/Debug.php +++ b/app/Debug.php @@ -70,19 +70,11 @@ class Debug { self::$db->warnings(); // see comment in MYSQL::query - $CacheStatus = self::$cache->server_status(); - if (in_array(0, $CacheStatus) && !self::$cache->get_value('cache_fail_reported')) { - // Limit to max one report every 15 minutes to avoid massive debug spam - self::$cache->cache_value('cache_fail_reported', true, 900); - $Reason[] = "Cache server error"; - } - if (isset($_REQUEST['profile'])) { $Reason[] = 'Requested by ' . $user->username(); } if (isset($Reason[0])) { - $this->log_var($CacheStatus, 'Cache server status'); $this->analysis(implode(', ', $Reason)); return true; } @@ -113,7 +105,7 @@ class Debug { duration: $duration, memory: memory_get_usage(true), nrQuery: count($this->get_queries()), - nrCache: count($this->get_cache_keys()), + nrCache: self::$cache->hitListTotal(), digest: md5($message, true), trace: $message, request: json_encode($_REQUEST), @@ -136,8 +128,8 @@ class Debug { 'searches_time' => class_exists('Sphinxql') ? \Sphinxql::$Time : 0.0, 'queries' => $this->get_queries(), 'queries_time' => self::$db->Time, - 'cache' => $this->get_cache_keys(), - 'cache_time' => self::$cache->Time, + 'cache' => self::$cache->hitList(), + 'cache_time' => self::$cache->elapsed(), ], 86400 * 2 ); @@ -271,28 +263,19 @@ class Debug { } } - //Shorten the path & we're done - $File = str_replace(SERVER_ROOT . '/', '', $File); - $Error = str_replace(SERVER_ROOT . '/', '', $Error); - if (DEBUG_WARNINGS) { - self::$Errors[] = [$Error, $File.':'.$Line, $Call, $Args]; + self::$Errors[] = [ + str_replace(SERVER_ROOT . '/', '', $Error), + str_replace(SERVER_ROOT . '/', '', $File) . ":$Line", + $Call, + $Args + ]; } return true; } /* Data wrappers */ - public function get_cache_keys() { - $list = []; - $keys = array_keys(self::$cache->hits()); - foreach ($keys as $key) { - $list[$key] = print_r(self::$cache->get_value($key, true), true); - } - ksort($list, SORT_NATURAL); - return $list; - } - public function get_classes() { $Classes = []; foreach (get_declared_classes() as $class) { diff --git a/app/Forum.php b/app/Forum.php index 182a21110..0c5183a40 100644 --- a/app/Forum.php +++ b/app/Forum.php @@ -32,7 +32,7 @@ class Forum extends BaseObject { public function flush(): Forum { $this->info = []; (new Manager\Forum)->flushToc(); - self::$cache->deleteMulti([ + self::$cache->delete_multi([ sprintf(self::CACHE_FORUM, $this->id), sprintf(self::CACHE_TOC_FORUM, $this->id), ]); diff --git a/app/ForumThread.php b/app/ForumThread.php index 5f2e55149..2a07c9740 100644 --- a/app/ForumThread.php +++ b/app/ForumThread.php @@ -16,7 +16,7 @@ class ForumThread extends BaseObject { } public function flushCatalog(int $begin, int $end) { - self::$cache->deleteMulti( + self::$cache->delete_multi( array_map( fn($c) => sprintf(self::CACHE_CATALOG, $this->id, (int)floor((POSTS_PER_PAGE * $c) / THREAD_CATALOGUE)), range($begin, $end) diff --git a/app/Inbox.php b/app/Inbox.php index 727eb622a..22ded4ae8 100644 --- a/app/Inbox.php +++ b/app/Inbox.php @@ -3,7 +3,6 @@ namespace Gazelle; class Inbox extends BaseUser { - protected bool $unreadFirst; protected string $filter; protected string $folder = 'inbox'; @@ -170,7 +169,7 @@ class Inbox extends BaseUser { protected function massFlush(array $ids): void { $userId = $this->user->id(); - self::$cache->deleteMulti(["inbox_new_$userId", ...array_map(fn ($id) => "pm_{$id}_{$userId}", $ids)]); + self::$cache->delete_multi(["inbox_new_$userId", ...array_map(fn ($id) => "pm_{$id}_{$userId}", $ids)]); } public function massRemove(array $ids): int { diff --git a/app/Json/AddLog.php b/app/Json/AddLog.php index e77c29965..29ee2766b 100644 --- a/app/Json/AddLog.php +++ b/app/Json/AddLog.php @@ -76,7 +76,7 @@ class AddLog extends \Gazelle\Json { ); $groupId = $this->torrent->groupId(); - self::$cache->deleteMulti([ + self::$cache->delete_multi([ "torrent_group_{$groupId}", "torrents_details_{$groupId}", sprintf(\Gazelle\TGroup::CACHE_KEY, $groupId), diff --git a/app/Manager/Blog.php b/app/Manager/Blog.php index 842916aa5..6e1c78ffa 100644 --- a/app/Manager/Blog.php +++ b/app/Manager/Blog.php @@ -3,12 +3,11 @@ namespace Gazelle\Manager; class Blog extends \Gazelle\BaseManager { - const CACHE_KEY = 'blog'; const ID_KEY = 'zz_blog_%d'; public function flush(): Blog { - self::$cache->deleteMulti(['feed_blog', self::CACHE_KEY]); + self::$cache->delete_multi(['feed_blog', self::CACHE_KEY]); return $this; } diff --git a/app/Manager/Bonus.php b/app/Manager/Bonus.php index f7959b0bd..b4eefeea8 100644 --- a/app/Manager/Bonus.php +++ b/app/Manager/Bonus.php @@ -71,8 +71,8 @@ class Bonus extends \Gazelle\Base { WHERE user_id in (" . placeholders($ids) . ") ", $points, ...$ids ); - self::$cache->deleteMulti(array_map(fn($k) => "user_stats_$k", $ids)); - self::$cache->deleteMulti(array_map(fn($k) => "u_$k", $ids)); + self::$cache->delete_multi(array_map(fn($k) => "user_stats_$k", $ids)); + self::$cache->delete_multi(array_map(fn($k) => "u_$k", $ids)); return self::$db->affected_rows(); } @@ -198,7 +198,7 @@ class Bonus extends \Gazelle\Base { SELECT concat('u_', bu.user_id) FROM bonus_update bu "); if (self::$db->has_results()) { - self::$cache->deleteMulti(self::$db->collect(0, false)); + self::$cache->delete_multi(self::$db->collect(0, false)); } return $processed; diff --git a/app/Manager/Comment.php b/app/Manager/Comment.php index fa99ccca2..af3c85cd5 100644 --- a/app/Manager/Comment.php +++ b/app/Manager/Comment.php @@ -3,7 +3,6 @@ namespace Gazelle\Manager; class Comment extends \Gazelle\BaseManager { - const CATALOG = '%s_comments_%d_cat_%d'; protected function className(string $page): string { @@ -50,7 +49,7 @@ class Comment extends \Gazelle\BaseManager { WHERE Page = ? AND PageID = ? ", TORRENT_COMMENTS_PER_PAGE, TORRENT_COMMENTS_PER_PAGE, THREAD_CATALOGUE, $page, $pageId ); - self::$cache->deleteMulti([ + self::$cache->delete_multi([ sprintf(self::CATALOG, $page, $pageId, $catalogueId), "{$page}_comments_{$pageId}" ]); diff --git a/app/Manager/Donation.php b/app/Manager/Donation.php index ab38337b0..3314f80be 100644 --- a/app/Manager/Donation.php +++ b/app/Manager/Donation.php @@ -3,7 +3,6 @@ namespace Gazelle\Manager; class Donation extends \Gazelle\Base { - public function moderatorAdjust(\Gazelle\User $user, int $Rank, int $TotalRank, string $Reason, int $who) { $this->donate($user, [ "Source" => "Modify Values", @@ -94,7 +93,7 @@ class Donation extends \Gazelle\Base { // They have been undonored if ($xbtAmount == 0.0 && $Rank == 0 && $TotalRank == 0) { $this->removeDonorStatus($UserID); - self::$cache->deleteMulti(["u_$UserID", "donor_info_$UserID"]); + self::$cache->delete_multi(["u_$UserID", "donor_info_$UserID"]); return; } @@ -152,7 +151,7 @@ class Donation extends \Gazelle\Base { ); // Clear their user cache keys because the users_info values has been modified - self::$cache->deleteMulti(["u_$UserID", "donor_info_$UserID", + self::$cache->delete_multi(["u_$UserID", "donor_info_$UserID", 'donations_month_3', 'donations_month_12']); self::$db->set_query_id($QueryID); } @@ -293,7 +292,7 @@ class Donation extends \Gazelle\Base { "); // 2 hours less than 32 days to account for schedule run times $userIds = []; while ([$id] = self::$db->next_record()) { - self::$cache->deleteMulti(["donor_info_$id", "donor_title_$id", "donor_profile_rewards_$id"]); + self::$cache->delete_multi(["donor_info_$id", "donor_title_$id", "donor_profile_rewards_$id"]); $userIds[] = $id; } if ($userIds) { diff --git a/app/Manager/News.php b/app/Manager/News.php index da592f86f..46bb7045e 100644 --- a/app/Manager/News.php +++ b/app/Manager/News.php @@ -3,7 +3,6 @@ namespace Gazelle\Manager; class News extends \Gazelle\Base { - const CACHE_KEY = 'news'; /** @@ -16,7 +15,7 @@ class News extends \Gazelle\Base { VALUES (?, ?, ?) ", $userId, trim($title), trim($body) ); - self::$cache->deleteMulti(['feed_news', self::CACHE_KEY]); + self::$cache->delete_multi(['feed_news', self::CACHE_KEY]); return self::$db->inserted_id(); } @@ -31,7 +30,7 @@ class News extends \Gazelle\Base { WHERE ID = ? ", trim($title), trim($body), $id ); - self::$cache->deleteMulti(['feed_news', self::CACHE_KEY]); + self::$cache->delete_multi(['feed_news', self::CACHE_KEY]); return self::$db->affected_rows(); } @@ -43,7 +42,7 @@ class News extends \Gazelle\Base { DELETE FROM news WHERE ID = ? ", $id ); - self::$cache->deleteMulti(['feed_news', self::CACHE_KEY]); + self::$cache->delete_multi(['feed_news', self::CACHE_KEY]); return self::$db->affected_rows(); } diff --git a/app/Manager/Payment.php b/app/Manager/Payment.php index 15bc6015b..97235cc96 100644 --- a/app/Manager/Payment.php +++ b/app/Manager/Payment.php @@ -5,13 +5,12 @@ namespace Gazelle\Manager; use \Gazelle\Exception\PaymentFetchForexException; class Payment extends \Gazelle\Base { - const LIST_KEY = 'payment_list'; const RENT_KEY = 'payment_monthly_rental'; const DUE_KEY = 'payment_due'; public function flush(): Payment { - self::$cache->deleteMulti([self::LIST_KEY, self::DUE_KEY, self::RENT_KEY]); + self::$cache->delete_multi([self::LIST_KEY, self::DUE_KEY, self::RENT_KEY]); return $this; } diff --git a/app/Manager/Privilege.php b/app/Manager/Privilege.php index 582849dc9..7a7b39ad5 100644 --- a/app/Manager/Privilege.php +++ b/app/Manager/Privilege.php @@ -44,7 +44,7 @@ class Privilege extends \Gazelle\BaseManager { VALUES (?, ?, ?, ?, ?, ?, ?, ?) ', $name, $level, (int)$secondary, $forums, serialize($values), $staffGroupId, $badge, $displayStaff ? '1' : '0' ); - self::$cache->deleteMulti(['user_class', 'staff_class']); + self::$cache->delete_multi(['user_class', 'staff_class']); return new \Gazelle\Privilege(self::$db->inserted_id()); } diff --git a/app/Manager/Session.php b/app/Manager/Session.php index 48fc6b282..95be14279 100644 --- a/app/Manager/Session.php +++ b/app/Manager/Session.php @@ -3,7 +3,6 @@ namespace Gazelle\Manager; class Session extends \Gazelle\Base { - public function purge(): int { self::$db->prepared_query(" SELECT concat('users_sessions_', UserID) as ck @@ -21,7 +20,7 @@ class Session extends \Gazelle\Base { WHERE (LastUpdate < (now() - INTERVAL 30 DAY) AND KeepLogged = '1') OR (LastUpdate < (now() - INTERVAL 60 MINUTE) AND KeepLogged = '0') "); - self::$cache->deleteMulti($cacheKeys); + self::$cache->delete_multi($cacheKeys); return count($cacheKeys); } } diff --git a/app/Manager/StaffBlog.php b/app/Manager/StaffBlog.php index 649a62908..78cde8946 100644 --- a/app/Manager/StaffBlog.php +++ b/app/Manager/StaffBlog.php @@ -158,7 +158,7 @@ class StaffBlog extends \Gazelle\Base { ); $this->blogId = self::$db->inserted_id(); } - self::$cache->deleteMulti(['staff_feed_blog', self::CACHE_KEY]); + self::$cache->delete_multi(['staff_feed_blog', self::CACHE_KEY]); return self::$db->affected_rows() === 1; } @@ -172,7 +172,7 @@ class StaffBlog extends \Gazelle\Base { DELETE FROM staff_blog WHERE ID = ? ", $blogId ); - self::$cache->deleteMulti(['staff_feed_blog', self::CACHE_KEY]); + self::$cache->delete_multi(['staff_feed_blog', self::CACHE_KEY]); return self::$db->affected_rows() === 1; } } diff --git a/app/Manager/Subscription.php b/app/Manager/Subscription.php index bf07fbc63..7c77f9a42 100644 --- a/app/Manager/Subscription.php +++ b/app/Manager/Subscription.php @@ -3,7 +3,6 @@ namespace Gazelle\Manager; class Subscription extends \Gazelle\Base { - /** * For all subscribers of a forum thread or artist/collage/request/torrent comments, clear * - subscription cache @@ -26,7 +25,7 @@ class Subscription extends \Gazelle\Base { ); } - $affected = count(self::$cache->deleteMulti(array_map( + $affected = count(self::$cache->delete_multi(array_map( fn ($id) => "subscriptions_user_new_$id", self::$db->collect('UserID', false) ))); diff --git a/app/Manager/TGroup.php b/app/Manager/TGroup.php index b55af008c..7b0fff202 100644 --- a/app/Manager/TGroup.php +++ b/app/Manager/TGroup.php @@ -115,7 +115,7 @@ class TGroup extends \Gazelle\BaseManager { WHERE GroupID = ? ", $old->id() ); - self::$cache->deleteMulti(self::$db->collect(0, false)); + self::$cache->delete_multi(self::$db->collect(0, false)); self::$db->begin_transaction(); @@ -167,7 +167,7 @@ class TGroup extends \Gazelle\BaseManager { AND (v2.GroupId NOT IN (?, ?)) ", $old->id(), $new->id(), $old->id(), $new->id() ); - self::$cache->deleteMulti(self::$db->collect(0, false)); + self::$cache->delete_multi(self::$db->collect(0, false)); // GroupIDs self::$db->prepared_query("SELECT ID FROM torrents WHERE GroupID = ?", $old->id()); @@ -176,7 +176,7 @@ class TGroup extends \Gazelle\BaseManager { $cacheKeys[] = 'torrent_download_' . $TorrentID; $cacheKeys[] = 'tid_to_group_' . $TorrentID; } - self::$cache->deleteMulti($cacheKeys); + self::$cache->delete_multi($cacheKeys); unset($cacheKeys); self::$db->prepared_query(" @@ -211,7 +211,7 @@ class TGroup extends \Gazelle\BaseManager { DELETE FROM collages_torrents WHERE GroupID = ? ", $old->id() ); - self::$cache->deleteMulti(array_map( + self::$cache->delete_multi(array_map( fn ($id) => sprintf(\Gazelle\Collage::CACHE_KEY, $id), $collageList )); @@ -220,7 +220,7 @@ class TGroup extends \Gazelle\BaseManager { SELECT concat('request_', ID) FROM requests WHERE GroupID = ? ", $old->id() ); - self::$cache->deleteMulti(self::$db->collect(0, false)); + self::$cache->delete_multi(self::$db->collect(0, false)); self::$db->prepared_query(" UPDATE requests SET GroupID = ? @@ -240,7 +240,7 @@ class TGroup extends \Gazelle\BaseManager { $new->refresh(); - self::$cache->deleteMulti([ + self::$cache->delete_multi([ "requests_group_" . $new->id(), "torrent_collages_" . $new->id(), "torrent_collages_personal_" . $new->id(), diff --git a/app/Manager/User.php b/app/Manager/User.php index d769c7f97..b6d811e2e 100644 --- a/app/Manager/User.php +++ b/app/Manager/User.php @@ -626,7 +626,7 @@ class User extends \Gazelle\BaseManager { ", $toId ) ); - self::$cache->deleteMulti(["pm_{$convId}_{$fromId}", "pm_{$convId}_{$toId}"]); + self::$cache->delete_multi(["pm_{$convId}_{$fromId}", "pm_{$convId}_{$toId}"]); $senderName = self::$db->scalar(" SELECT Username FROM users_main WHERE ID = ? ", $fromId @@ -781,7 +781,7 @@ class User extends \Gazelle\BaseManager { AND UserID IN (" . placeholders($userIds) . ") ", ...$userIds ); - self::$cache->deleteMulti(self::$db->collect('cacheKey')); + self::$cache->delete_multi(self::$db->collect('cacheKey')); self::$db->prepared_query(" DELETE FROM users_sessions WHERE UserID IN (" . placeholders($userIds) . ") ", ...$userIds @@ -1269,7 +1269,7 @@ class User extends \Gazelle\BaseManager { ); self::$db->commit(); - self::$cache->deleteMulti(array_map(fn($id) => "u_$id", $ids)); + self::$cache->delete_multi(array_map(fn($id) => "u_$id", $ids)); return count($ids); } @@ -1302,7 +1302,7 @@ class User extends \Gazelle\BaseManager { ); self::$db->commit(); - self::$cache->deleteMulti(array_map(fn($id) => "u_$id", $ids)); + self::$cache->delete_multi(array_map(fn($id) => "u_$id", $ids)); return count($ids); } @@ -1335,7 +1335,7 @@ class User extends \Gazelle\BaseManager { ", $token['TorrentID'], $token['UserID'] ); } - self::$cache->deleteMulti(array_keys($clear)); + self::$cache->delete_multi(array_keys($clear)); return $processed; } diff --git a/app/Privilege.php b/app/Privilege.php index 7cea2533a..3ac4a3b6f 100644 --- a/app/Privilege.php +++ b/app/Privilege.php @@ -71,7 +71,7 @@ class Privilege extends BaseObject { } protected function userFlush(array $ids): int { - self::$cache->deleteMulti(array_merge( + self::$cache->delete_multi(array_merge( ["perm_" . $this->id], array_map(fn($id) => "u_$id", $ids), )); @@ -89,7 +89,7 @@ class Privilege extends BaseObject { ); $this->userFlush(self::$db->collect(0, false)); } - self::$cache->deleteMulti(['user_class', 'staff_class']); + self::$cache->delete_multi(['user_class', 'staff_class']); return $modified; } diff --git a/app/Request.php b/app/Request.php index 3fafa6b6a..9dbb63559 100644 --- a/app/Request.php +++ b/app/Request.php @@ -11,7 +11,7 @@ class Request extends BaseObject { if ($this->tgroupId()) { self::$cache->delete_value("requests_group_" . $this->tgroupId()); } - self::$cache->deleteMulti([ + self::$cache->delete_multi([ sprintf(self::CACHE_REQUEST, $this->id), sprintf(self::CACHE_ARTIST, $this->id), sprintf(self::CACHE_VOTE, $this->id), @@ -78,7 +78,7 @@ class Request extends BaseObject { SELECT ArtistID FROM requests_artists WHERE RequestID = ? ", $this->id ); - self::$cache->deleteMulti([ + self::$cache->delete_multi([ ...array_map(fn ($id) => "artists_requests_$id", self::$db->collect(0, false)), ]); } diff --git a/app/Schedule/Tasks/ExpireTagSnatchCache.php b/app/Schedule/Tasks/ExpireTagSnatchCache.php index b26494ed6..9f0fe3956 100644 --- a/app/Schedule/Tasks/ExpireTagSnatchCache.php +++ b/app/Schedule/Tasks/ExpireTagSnatchCache.php @@ -11,6 +11,6 @@ class ExpireTagSnatchCache extends \Gazelle\Schedule\Task FROM xbt_snatched WHERE tstamp > unix_timestamp(now() - INTERVAL 90 MINUTE) "); - return count(self::$cache->deleteMulti(self::$db->collect('uid', false))); + return count(self::$cache->delete_multi(self::$db->collect('uid', false))); } } diff --git a/app/StaffPM.php b/app/StaffPM.php index b387245fe..9d647e897 100644 --- a/app/StaffPM.php +++ b/app/StaffPM.php @@ -15,7 +15,7 @@ class StaffPM extends BaseObject { public function tableName(): string { return 'staff_pm_conversations'; } public function flushUser(User $user) { - self::$cache->deleteMulti([ + self::$cache->delete_multi([ "num_staff_pms_" . $user->id(), "staff_pm_new_" . $user->id(), ]); diff --git a/app/Stats/User.php b/app/Stats/User.php index 8070dbd8e..31ec77ddb 100644 --- a/app/Stats/User.php +++ b/app/Stats/User.php @@ -20,7 +20,7 @@ class User extends \Gazelle\BaseObject { protected array $general = []; public function flush(): User { - self::$cache->deleteMulti([ + self::$cache->delete_multi([ sprintf(self::CACHE_COMMENT_TOTAL, $this->id), sprintf(self::CACHE_GENERAL, $this->id), ]); diff --git a/app/TGroup.php b/app/TGroup.php index c2a40126a..33729e569 100644 --- a/app/TGroup.php +++ b/app/TGroup.php @@ -21,7 +21,7 @@ class TGroup extends BaseObject { public function flush(): TGroup { $this->info = []; - self::$cache->deleteMulti([ + self::$cache->delete_multi([ sprintf(self::CACHE_KEY, $this->id), sprintf(self::CACHE_TLIST_KEY, $this->id), sprintf(self::CACHE_COVERART_KEY, $this->id), @@ -75,7 +75,7 @@ class TGroup extends BaseObject { WHERE GroupID = ? ", $this->id ); - self::$cache->deleteMulti(self::$db->collect('cacheKey')); + self::$cache->delete_multi(self::$db->collect('cacheKey')); return $this; } @@ -88,7 +88,7 @@ class TGroup extends BaseObject { ", $this->id ); if (self::$db->has_results()) { - self::$cache->deleteMulti(array_map(fn ($id) => "collagev2_$id", self::$db->collect(0, false))); + self::$cache->delete_multi(array_map(fn ($id) => "collagev2_$id", self::$db->collect(0, false))); } self::$db->prepared_query(" @@ -99,7 +99,7 @@ class TGroup extends BaseObject { ", $this->id ); if (self::$db->has_results()) { - self::$cache->deleteMulti(array_map(fn ($id) => sprintf(self::USER_RECENT_UPLOAD, $id), self::$db->collect(0, false))); + self::$cache->delete_multi(array_map(fn ($id) => sprintf(self::USER_RECENT_UPLOAD, $id), self::$db->collect(0, false))); } self::$db->prepared_query(" @@ -110,7 +110,7 @@ class TGroup extends BaseObject { ", $this->id ); if (self::$db->has_results()) { - self::$cache->deleteMulti(array_map(fn ($id) => sprintf(self::USER_RECENT_SNATCH, $id), self::$db->collect(0, false))); + self::$cache->delete_multi(array_map(fn ($id) => sprintf(self::USER_RECENT_SNATCH, $id), self::$db->collect(0, false))); } return $this; } @@ -1030,7 +1030,7 @@ class TGroup extends BaseObject { return false; } - self::$cache->deleteMulti([ + self::$cache->delete_multi([ "torrents_details_" . $this->id, "torrent_group_" . $this->id, sprintf(\Gazelle\TGroup::CACHE_KEY, " . $this->id), diff --git a/app/Top10/Torrent.php b/app/Top10/Torrent.php index 5d2e4a625..44159cf93 100644 --- a/app/Top10/Torrent.php +++ b/app/Top10/Torrent.php @@ -15,9 +15,10 @@ class Torrent extends \Gazelle\Base { if ($topTorrents !== false) { return $topTorrents; } - if (!self::$cache->get_query_lock($cacheKey)) { + if (self::$cache->get_value("{$cacheKey}_lock")) { return false; } + self::$cache->cache_value("{$cacheKey}_lock", true, 3600); $where = []; $anyTags = isset($getParameters['anyall']) && $getParameters['anyall'] == 'any'; @@ -74,7 +75,7 @@ class Torrent extends \Gazelle\Base { $topTorrents = self::$db->to_array(); self::$cache->cache_value($cacheKey, $topTorrents, 3600 * 6); - self::$cache->clear_query_lock($cacheKey); + self::$cache->delete_value("{$cacheKey}_lock"); return $topTorrents; } diff --git a/app/Torrent.php b/app/Torrent.php index 1e90cb602..29be31666 100644 --- a/app/Torrent.php +++ b/app/Torrent.php @@ -108,7 +108,7 @@ class Torrent extends TorrentAbstract { } public function unlockUpload(): void { - self::$cache->deleteMulti(sprintf(self::CACHE_LOCK, $this->id)); + self::$cache->delete_value(sprintf(self::CACHE_LOCK, $this->id)); } /** @@ -531,7 +531,7 @@ class Torrent extends TorrentAbstract { array_push($deleteKeys, "zz_t_" . $this->id, sprintf(self::CACHE_KEY, $this->id), "torrent_download_" . $this->id, "torrent_group_" . $groupId, "torrents_details_" . $groupId ); - self::$cache->deleteMulti($deleteKeys); + self::$cache->delete_multi($deleteKeys); $this->group()->refresh(); $sizeMB = number_format($this->info()['Size'] / (1024 * 1024), 2) . ' MiB'; diff --git a/app/User.php b/app/User.php index f0ef30244..a6bc9d0fa 100644 --- a/app/User.php +++ b/app/User.php @@ -1340,7 +1340,7 @@ class User extends BaseObject { ); $removed = self::$db->affected_rows(); if ($removed) { - self::$cache->deleteMulti(['u_notify_' . $this->id, 'notify_artists_' . $this->id]); + self::$cache->delete_multi(['u_notify_' . $this->id, 'notify_artists_' . $this->id]); } return $removed; } @@ -1397,7 +1397,7 @@ class User extends BaseObject { $change = self::$db->affected_rows(); } if ($change) { - self::$cache->deleteMulti(['u_notify_' . $this->id, 'notify_artists_' . $this->id]); + self::$cache->delete_multi(['u_notify_' . $this->id, 'notify_artists_' . $this->id]); } return $change; } @@ -1444,7 +1444,7 @@ class User extends BaseObject { $change = self::$db->affected_rows(); } if ($change) { - self::$cache->deleteMulti(['u_notify_' . $this->id, 'notify_artists_' . $this->id]); + self::$cache->delete_multi(['u_notify_' . $this->id, 'notify_artists_' . $this->id]); } return $change; } @@ -2636,6 +2636,6 @@ class User extends BaseObject { ); } self::$db->set_query_id($QueryID); - self::$cache->deleteMulti(["donor_profile_rewards_$UserID", "donor_info_$UserID"]); + self::$cache->delete_multi(["donor_profile_rewards_$UserID", "donor_info_$UserID"]); } } diff --git a/app/User/Bonus.php b/app/User/Bonus.php index dd7b41a4c..2364ad513 100644 --- a/app/User/Bonus.php +++ b/app/User/Bonus.php @@ -10,7 +10,7 @@ class Bonus extends \Gazelle\BaseUser { public function flush(): Bonus { $this->user->flush(); - self::$cache->deleteMulti([ + self::$cache->delete_multi([ sprintf(self::CACHE_HISTORY, $this->user->id(), 0), sprintf(self::CACHE_POOL_HISTORY, $this->user->id()), ]); @@ -383,7 +383,7 @@ class Bonus extends \Gazelle\BaseUser { } private function addPurchaseHistory(int $itemId, int $price, $otherUserId = null): int { - self::$cache->deleteMulti([ + self::$cache->delete_multi([ sprintf(self::CACHE_PURCHASE, $this->user->id()), sprintf(self::CACHE_SUMMARY, $this->user->id()), sprintf(self::CACHE_HISTORY, $this->user->id(), 0) diff --git a/app/User/Bookmark.php b/app/User/Bookmark.php index 895dc2e17..baaa6f97a 100644 --- a/app/User/Bookmark.php +++ b/app/User/Bookmark.php @@ -226,7 +226,7 @@ class Bookmark extends \Gazelle\BaseUser { (1 + coalesce((SELECT max(m.Sort) from bookmarks_torrents m WHERE m.UserID = ?), 0)) )", $id, $this->user->id(), $this->user->id() ); - self::$cache->deleteMulti(["u_book_t_" . $this->user->id(), "bookmarks_{$type}_" . $this->user->id(), "bookmarks_group_ids_" . $this->user->id()]); + self::$cache->delete_multi(["u_book_t_" . $this->user->id(), "bookmarks_{$type}_" . $this->user->id(), "bookmarks_group_ids_" . $this->user->id()]); $torMan = (new \Gazelle\Manager\Torrent)->setViewer($this->user); $tgroup = (new \Gazelle\Manager\TGroup)->findById($id); @@ -285,7 +285,7 @@ class Bookmark extends \Gazelle\BaseUser { DELETE FROM $table WHERE UserID = ? AND $column = ? ", $this->user->id(), $id ); - self::$cache->deleteMulti(["u_book_t_" . $this->user->id(), "bookmarks_{$type}_" . $this->user->id()]); + self::$cache->delete_multi(["u_book_t_" . $this->user->id(), "bookmarks_{$type}_" . $this->user->id()]); if ($type === 'torrent' && self::$db->affected_rows()) { self::$cache->delete_value("bookmarks_group_ids_" . $this->user->id()); diff --git a/app/User/Session.php b/app/User/Session.php index fcffa5f81..143e7c2cf 100644 --- a/app/User/Session.php +++ b/app/User/Session.php @@ -104,7 +104,7 @@ class Session extends \Gazelle\BaseUser { AND SessionID = ? ', $this->user->id(), $sessionId ); - self::$cache->deleteMulti([ + self::$cache->delete_multi([ sprintf(self::CACHE_KEY, $this->user->id()), 'session_' . $sessionId, ]); @@ -118,7 +118,7 @@ class Session extends \Gazelle\BaseUser { WHERE UserID = ? ", $this->user->id() ); - self::$cache->deleteMulti([ + self::$cache->delete_multi([ sprintf(self::CACHE_KEY, $this->user->id()), ...self::$db->collect('ck', false) ]); diff --git a/app/User/Subscription.php b/app/User/Subscription.php index 49de8d17b..d8a11638f 100644 --- a/app/User/Subscription.php +++ b/app/User/Subscription.php @@ -9,7 +9,7 @@ class Subscription extends \Gazelle\BaseUser { public function flush(): Subscription { $this->threadList = []; - self::$cache->deleteMulti([ + self::$cache->delete_multi([ sprintf(self::CACHE_KEY, $this->user->id()), sprintf(self::NEW_KEY, $this->user->id()), ]); @@ -73,7 +73,7 @@ class Subscription extends \Gazelle\BaseUser { ); array_push($subscriptions, [$page, $pageID]); } - self::$cache->replace_value("subscriptions_comments_user_" . $this->user->id(), $subscriptions, 0); + self::$cache->cache_value("subscriptions_comments_user_" . $this->user->id(), $subscriptions, 0); self::$db->set_query_id($qid); } diff --git a/app/User/Vote.php b/app/User/Vote.php index d18260574..bd4c0bc0b 100644 --- a/app/User/Vote.php +++ b/app/User/Vote.php @@ -47,7 +47,7 @@ class Vote extends \Gazelle\BaseUser { } public function flush(): Vote { - self::$cache->deleteMulti([ + self::$cache->delete_multi([ sprintf(self::VOTE_RECENT, $this->user->id()), sprintf(self::VOTE_TOTAL, $this->user->id()), ]); diff --git a/app/Util/CacheMultiFlush.php b/app/Util/CacheMultiFlush.php index b251dfc36..33bf7cbb4 100644 --- a/app/Util/CacheMultiFlush.php +++ b/app/Util/CacheMultiFlush.php @@ -30,7 +30,7 @@ class CacheMultiFlush extends \Gazelle\Base { foreach ($shape as $s) { $flush = array_merge($flush, array_map(function ($id) use ($s) {return sprintf($s, $id);}, $list)); } - self::$cache->deleteMulti($flush); + self::$cache->delete_multi($flush); $flushed += count($flush); $current = end($list); } diff --git a/classes/view.class.php b/classes/view.class.php index 0916182b1..f8ca9a3f7 100644 --- a/classes/view.class.php +++ b/classes/view.class.php @@ -1,6 +1,5 @@ render('index/private-footer.twig', [ - 'cache_time' => $Cache->Time, + 'cache' => $Cache, 'db_time' => $DB->Time, 'debug' => $Debug, 'disclaimer' => isset($Options['disclaimer']), diff --git a/gazelle.php b/gazelle.php index 8aff64b79..0640310d2 100644 --- a/gazelle.php +++ b/gazelle.php @@ -121,11 +121,6 @@ if ($Viewer) { error_reporting(E_ALL); } - // Change necessary triggers in external components - if ($Viewer->permitted('admin_clear_cache')) { - $Cache->enableCacheClear(); - } - // Because we <3 our staff if ($Viewer->permitted('site_disable_ip_history')) { $_SERVER['REMOTE_ADDR'] = '127.0.0.1'; diff --git a/public/static/functions/debug.js b/public/static/functions/debug.js index 580b2bc2b..52716633d 100644 --- a/public/static/functions/debug.js +++ b/public/static/functions/debug.js @@ -1,5 +1,6 @@ $(document).ready(function () { $("#debug-view-cache").click(function() { $(this).parents('.layout').next('#debug_cache').gtoggle(); return false;}); + $("#debug-view-del-cache").click(function() { $(this).parents('.layout').next('#debug_cache').gtoggle(); return false;}); $("#debug-view-class").click(function() { $(this).parents('.layout').next('#debug_class').gtoggle(); return false;}); $("#debug-view-error").click(function() { $(this).parents('.layout').next('#debug_error').gtoggle(); return false;}); $("#debug-view-extension").click(function() { $(this).parents('.layout').next('#debug_extension').gtoggle(); return false;}); diff --git a/scripts/rebuild-votes b/scripts/rebuild-votes index 5e1b14ee6..b105eb5e2 100755 --- a/scripts/rebuild-votes +++ b/scripts/rebuild-votes @@ -52,6 +52,6 @@ while ($id < $max) { break; } $ids = explode(',', $list); - $Cache->deleteMulti($ids); + $Cache->delete_multi($ids); $id = end($ids); } diff --git a/sections/artist/rename.php b/sections/artist/rename.php index 4a1359aaf..098e20016 100644 --- a/sections/artist/rename.php +++ b/sections/artist/rename.php @@ -187,7 +187,7 @@ $DB->prepared_query(" WHERE ArtistID = ? ", $ArtistID ); -$Cache->deleteMulti(array_merge($DB->collect('GroupID'), ["artists_requests_$TargetArtistID", "artists_requests_$ArtistID"])); +$Cache->delete_multi(array_merge($DB->collect('GroupID'), ["artists_requests_$TargetArtistID", "artists_requests_$ArtistID"])); $artist->flushCache(); $artist = new Gazelle\Artist($TargetArtistID); diff --git a/sections/reportsv2/takeresolve.php b/sections/reportsv2/takeresolve.php index fe65d8c03..04bd030f9 100644 --- a/sections/reportsv2/takeresolve.php +++ b/sections/reportsv2/takeresolve.php @@ -52,7 +52,7 @@ if ($fromReportPage && in_array($_POST['resolve_type'], ['manual', 'dismiss'])) } } if ($report->moderatorResolve($Viewer->id(), $comment)) { - $Cache->deleteMulti(['num_torrent_reportsv2', "reports_torrent_$torrentId"]); + $Cache->delete_multi(['num_torrent_reportsv2', "reports_torrent_$torrentId"]); } else { echo $Twig->render('reportsv2/already-resolved.twig', ['report' => $report]); } diff --git a/sections/requests/take_new_edit.php b/sections/requests/take_new_edit.php index ce8679a4b..3ce9232da 100644 --- a/sections/requests/take_new_edit.php +++ b/sections/requests/take_new_edit.php @@ -309,7 +309,7 @@ if ($newRequest) { SELECT concat('artists_requests_', ArtistID) FROM requests_artists WHERE RequestID = ? ", $RequestID ); - $Cache->deleteMulti([ + $Cache->delete_multi([ "request_artists_$RequestID", ...$DB->collect(0, false) ]); diff --git a/sections/tools/development/clear_cache.php b/sections/tools/development/clear_cache.php index 4095f121e..b63b26565 100644 --- a/sections/tools/development/clear_cache.php +++ b/sections/tools/development/clear_cache.php @@ -21,7 +21,7 @@ if (!empty($_REQUEST['key'])) { if (!$Viewer->permitted('admin_clear_cache')) { error(403); } - $delete = $Cache->deleteMulti($Keys); + $delete = $Cache->delete_multi($Keys); foreach ($delete as $key => $response) { $result[$key] = CACHE_RESPONSE[$response] ?? "retcode:$response"; } diff --git a/sections/tools/managers/ocelot.php b/sections/tools/managers/ocelot.php index 21dcd4ffa..e51b13607 100644 --- a/sections/tools/managers/ocelot.php +++ b/sections/tools/managers/ocelot.php @@ -32,7 +32,7 @@ if (isset($_GET['tokens'])) { WHERE " . implode(" OR ", $cond), ...$args ); - $Cache->deleteMulti($ck); + $Cache->delete_multi($ck); } } else { $TorrentID = (int)$_REQUEST['torrentid']; diff --git a/sections/torrents/download.php b/sections/torrents/download.php index be3543ab4..d65199fd6 100644 --- a/sections/torrents/download.php +++ b/sections/torrents/download.php @@ -100,7 +100,7 @@ if (isset($_REQUEST['usetoken']) && $torrent->freeleechStatus() == '0') { ", $userId, $torrentId, $tokenCount, $tokenCount ); $DB->commit(); - $Cache->deleteMulti(["u_$userId", "users_tokens_$userId"]); + $Cache->delete_multi(["u_$userId", "users_tokens_$userId"]); } } diff --git a/sections/torrents/editgroupid.php b/sections/torrents/editgroupid.php index 3e1fa34be..26b1cbe37 100644 --- a/sections/torrents/editgroupid.php +++ b/sections/torrents/editgroupid.php @@ -67,7 +67,7 @@ if ($DB->scalar("SELECT count(*) FROM torrents WHERE GroupID = ?", $old->id())) $new->flush(); $new->refresh(); $torrent->flush(); -$Cache->deleteMulti([ +$Cache->delete_multi([ "torrents_details_" . $oldId, "torrent_download_" . $torrent->id(), ]); diff --git a/sections/torrents/takechangecategory.php b/sections/torrents/takechangecategory.php index 681c07893..163f654a2 100644 --- a/sections/torrents/takechangecategory.php +++ b/sections/torrents/takechangecategory.php @@ -107,7 +107,7 @@ if ($DB->scalar('SELECT ID FROM torrents WHERE GroupID = ?', $oldId)) { $new->flush(); $new->refresh(); -$Cache->deleteMulti([ +$Cache->delete_multi([ "torrents_details_" . $oldId, "torrent_download_" . $torrent->id(), ]); diff --git a/sections/torrents/takenewgroup.php b/sections/torrents/takenewgroup.php index 7282711cf..fb0236ede 100644 --- a/sections/torrents/takenewgroup.php +++ b/sections/torrents/takenewgroup.php @@ -78,7 +78,7 @@ if ($DB->scalar('SELECT 1 FROM torrents WHERE GroupID = ?', $oldId)) { $new->flush(); $new->refresh(); $torrent->flush(); -$Cache->deleteMulti([ +$Cache->delete_multi([ "torrents_details_" . $oldId, "torrent_download_" . $torrent->id(), ]); diff --git a/sections/upload/upload_handle.php b/sections/upload/upload_handle.php index a6b8f8da4..71393c841 100644 --- a/sections/upload/upload_handle.php +++ b/sections/upload/upload_handle.php @@ -719,9 +719,9 @@ $Cache->increment_value('stats_torrent_count', $totalNew); if ($Properties['Image'] != '') { $Cache->delete_value('user_recent_up_' . $Viewer->id()); } -$Cache->deleteMulti(["torrents_details_$GroupID", "torrent_{$TorrentID}_lock"]); +$Cache->delete_multi(["torrents_details_$GroupID", "torrent_{$TorrentID}_lock"]); if (!$IsNewGroup) { - $Cache->deleteMulti([ + $Cache->delete_multi([ "torrent_group_$GroupID", "detail_files_$GroupID", sprintf(\Gazelle\TGroup::CACHE_KEY, $GroupID), diff --git a/sections/user/index.php b/sections/user/index.php index 3414fe152..55f22f13b 100644 --- a/sections/user/index.php +++ b/sections/user/index.php @@ -84,7 +84,7 @@ switch ($_REQUEST['action'] ?? '') { error(403); } $UserID = $_REQUEST['id']; - $Cache->deleteMulti([ + $Cache->delete_multi([ 'u_' . $UserID, 'collage_subs_user_new_' . $UserID, 'donor_info_' . $UserID, diff --git a/sections/user/notify_handle.php b/sections/user/notify_handle.php index 674662c1a..83314c00b 100644 --- a/sections/user/notify_handle.php +++ b/sections/user/notify_handle.php @@ -47,5 +47,5 @@ if ($filterId) { $filter->create($Viewer->id()); } -$Cache->deleteMulti(["u_notify_" . $Viewer->id(), "notify_artists_" . $Viewer->id()]); +$Cache->delete_multi(["u_notify_" . $Viewer->id(), "notify_artists_" . $Viewer->id()]); header('Location: user.php?action=notify'); diff --git a/templates/debug/cache.twig b/templates/debug/cache.twig index 4399c7c75..bc4fd48b8 100644 --- a/templates/debug/cache.twig +++ b/templates/debug/cache.twig @@ -1,24 +1,39 @@ -{% set nr = list|length %} -{% for key, value in list %} +{% set nr = cache.hitList|length %} +{% for key, hit in cache.hitList %} {% if loop.first %} - {%- set name = 'debug_cache_t_' ~ key -%} - {{- dom.click('.view-key', "$(this).parent().next().children().gtoggle(); return false;") -}} + ({{ cache.elapsed|number_format(2) }} ms) (mean: {{ (cache.elapsed/nr)|number_format(5) }} ms):
View {{ nr|number_format }} Cache key{{ nr|plural }} - ({{ time|number_format(2) }} ms) (mean: {{ (time/nr)|number_format(5) }} ms):
{% endif %} - - + + {% if loop.last %} + + {% endif %} +{% endfor %} +{% set nr = cache.deleteList|length %} +{% for key in cache.deleteList %} + {% if loop.first %} + + + + +
View + {{ nr|number_format }} Cache key{{ nr|plural }} deleted
+ + {% endif %} + + {% if loop.last %} diff --git a/templates/index/private-footer.twig b/templates/index/private-footer.twig index a4893b8d0..89353722e 100644 --- a/templates/index/private-footer.twig +++ b/templates/index/private-footer.twig @@ -9,7 +9,7 @@ {%- include 'debug/sphinxql.twig' with {'list': sphinxql.list, 'time': sphinxql.time} only %} {%- endif %} {%- include 'debug/query.twig' with {'list': debug.get_queries_br, 'time': db_time} only %} - {%- include 'debug/cache.twig' with {'list': debug.get_cache_keys, 'time': cache_time} only %} + {%- include 'debug/cache.twig' with {'cache': cache} only %} {%- include 'debug/var.twig' with {'list': debug.get_logged_vars} only %} {%- include 'debug/ocelot.twig' with {'list': debug.requestList} only %} diff --git a/tests/phpunit/CacheTest.php b/tests/phpunit/CacheTest.php new file mode 100644 index 000000000..05768a1af --- /dev/null +++ b/tests/phpunit/CacheTest.php @@ -0,0 +1,55 @@ +assertCount(0, $cache->hitList(), 'cache-hit-list-empty'); + $this->assertCount(0, $cache->deleteList(), 'cache-del-list-empty'); + + $prefix = 'unit-test-' . randomString(10) . '-'; + $key = "$prefix-1"; + $cache->cache_value($key, 'first', 600); + $this->assertEquals('first', $cache->get_value($key), 'cache-get-1'); + $fetch = $cache->get_value($key); + $this->assertCount(1, $cache->hitList(), 'cache-hit-list-1'); + $this->assertEquals([$key => 2], $cache->hitList(), 'cache-hit-list-1'); + + $cache->delete_value($key); + $this->assertFalse($cache->get_value($key), 'cache-delete-1'); + $this->assertCount(1, $cache->hitList(), 'cache-delete-count'); + $this->assertEquals(1, $cache->deleteListTotal(), 'cache-del-list-1'); + + $key2 = "$prefix-2"; + $cache->cache_value($key2, 0, 600); + $this->assertEquals(0, $cache->get_value($key2), 'cache-cache-2'); + $this->assertEquals(1, $cache->increment_value($key2), 'cache-incr-2'); + $this->assertEquals(1, $cache->get_value($key2), 'cache-increment-2'); + + $key3 = "$prefix-3"; + $cache->cache_value($key3, 9, 600); + $this->assertEquals(9, $cache->get_value($key3), 'cache-cache-3'); + $this->assertEquals(8, $cache->decrement_value($key3), 'cache-decr-3'); + $this->assertEquals(8, $cache->get_value($key3), 'cache-decrement-3'); + + $multi = $cache->delete_multi([$key2, $key3]); + $this->assertEquals([$key2 => true, $key3 => true], $multi, 'cache-multi-del'); + + $key4 = "$prefix-4"; + $this->assertFalse($cache->get_value($key4), 'cache-unset-4'); + + $key5 = "$prefix-5"; + $this->assertTrue($cache->setMulti([$key4 => 'k4', $key5 => 'k5']), 'cache-set-multi'); + $this->assertEquals('k4', $cache->get_value($key4), 'cache-get-4'); + $this->assertEquals('k5', $cache->get_value($key5), 'cache-get-5'); + $this->assertEquals([$key4 => 'k4', $key5 => 'k5'], $cache->getMulti([$key4, $key5]), 'cache-get-multi'); + + $this->assertIsArray($cache->server_status(), 'cache-server-status'); + + $html = Gazelle\Util\Twig::factory()->render('debug/cache.twig', ['cache' => $cache]); + $this->assertStringContainsString('', $html, 'cache-debug-render'); + } +}