Skip to content

Commit b08bb88

Browse files
authored
Merge pull request #6237 from WoltLab/6.2-tolerant-cache
Eager and Tolerant Caching
2 parents b4ce062 + f1f9028 commit b08bb88

28 files changed

+882
-317
lines changed

wcfsetup/install/files/lib/acp/form/BoxAddForm.class.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,7 @@ public function save()
630630
'cssClassName' => $this->cssClassName,
631631
'showHeader' => $this->showHeader,
632632
'isDisabled' => $this->isDisabled ? 1 : 0,
633-
'linkPageID' => $this->linkPageID,
633+
'linkPageID' => $this->linkPageID ?: null,
634634
'linkPageObjectID' => $this->linkPageObjectID ?: 0,
635635
'externalURL' => $this->externalURL,
636636
'identifier' => '',

wcfsetup/install/files/lib/acp/form/BoxEditForm.class.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ public function save()
119119
'cssClassName' => $this->cssClassName,
120120
'showHeader' => $this->showHeader,
121121
'isDisabled' => $this->isDisabled ? 1 : 0,
122-
'linkPageID' => $this->linkPageID,
122+
'linkPageID' => $this->linkPageID ?: null,
123123
'linkPageObjectID' => $this->linkPageObjectID ?: 0,
124124
'externalURL' => $this->externalURL,
125125
'invertPermissions' => $this->invertPermissions,

wcfsetup/install/files/lib/acp/form/LanguageMultilingualismForm.class.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
use wcf\data\language\Language;
66
use wcf\data\language\LanguageEditor;
77
use wcf\form\AbstractForm;
8-
use wcf\system\cache\builder\LanguageCacheBuilder;
8+
use wcf\system\cache\eager\LanguageCache;
99
use wcf\system\exception\UserInputException;
1010
use wcf\system\language\LanguageFactory;
1111
use wcf\system\WCF;
@@ -116,7 +116,7 @@ public function save()
116116
LanguageEditor::enableMultilingualism(($this->enable == 1 ? $this->languageIDs : []));
117117

118118
// clear cache
119-
LanguageCacheBuilder::getInstance()->reset();
119+
(new LanguageCache())->rebuild();
120120
$this->saved();
121121

122122
// show success message

wcfsetup/install/files/lib/data/language/LanguageEditor.class.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
use wcf\data\language\item\LanguageItemList;
1111
use wcf\data\page\PageEditor;
1212
use wcf\event\language\LanguageContentCopying;
13-
use wcf\system\cache\builder\LanguageCacheBuilder;
13+
use wcf\system\cache\eager\LanguageCache;
1414
use wcf\system\database\util\PreparedStatementConditionBuilder;
1515
use wcf\system\event\EventHandler;
1616
use wcf\system\exception\SystemException;
@@ -932,7 +932,7 @@ public function setAsDefault()
932932
$statement->execute([0]);
933933

934934
// set current language as default language
935-
$this->update(['isDefault' => 1]);
935+
$this->update(['isDefault' => 1, 'isDisabled' => 0]);
936936

937937
$this->clearCache();
938938
}
@@ -944,7 +944,7 @@ public function setAsDefault()
944944
*/
945945
public function clearCache()
946946
{
947-
LanguageCacheBuilder::getInstance()->reset();
947+
(new LanguageCache())->rebuild();
948948
}
949949

950950
/**

wcfsetup/install/files/lib/system/WCF.class.php

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,12 @@
1212
use wcf\system\application\IApplication;
1313
use wcf\system\benchmark\Benchmark;
1414
use wcf\system\box\BoxHandler;
15-
use wcf\system\cache\builder\CoreObjectCacheBuilder;
1615
use wcf\system\cache\builder\PackageUpdateCacheBuilder;
16+
use wcf\system\cache\eager\CoreObjectCache;
1717
use wcf\system\database\MySQLDatabase;
1818
use wcf\system\event\EventHandler;
1919
use wcf\system\exception\ErrorException;
2020
use wcf\system\exception\IPrintableException;
21-
use wcf\system\exception\ParentClassException;
2221
use wcf\system\exception\SystemException;
2322
use wcf\system\language\LanguageFactory;
2423
use wcf\system\package\command\RebuildBootstrapper;
@@ -140,9 +139,10 @@ class WCF
140139

141140
/**
142141
* list of cached core objects
143-
* @var string[]
142+
*
143+
* @var array<string, class-string<SingletonFactory>>
144144
*/
145-
protected static $coreObjectCache = [];
145+
protected static array $coreObjectCache;
146146

147147
/**
148148
* database object
@@ -752,7 +752,7 @@ protected function initCoreObjects(): void
752752
return;
753753
}
754754

755-
self::$coreObjectCache = CoreObjectCacheBuilder::getInstance()->getData();
755+
self::$coreObjectCache = (new CoreObjectCache())->getCache();
756756
}
757757

758758
/**
@@ -919,10 +919,6 @@ final public static function __callStatic(string $name, array $arguments)
919919
}
920920

921921
if (\class_exists($objectName)) {
922-
if (!\is_subclass_of($objectName, SingletonFactory::class)) {
923-
throw new ParentClassException($objectName, SingletonFactory::class);
924-
}
925-
926922
self::$coreObject[$className] = \call_user_func([$objectName, 'getInstance']);
927923

928924
return self::$coreObject[$className];
@@ -934,7 +930,7 @@ final public static function __callStatic(string $name, array $arguments)
934930
/**
935931
* Searches for cached core object definition.
936932
*
937-
* @return string|null
933+
* @return class-string<SingletonFactory>|null
938934
*/
939935
final protected static function getCoreObject(string $className)
940936
{

wcfsetup/install/files/lib/system/WCFSetup.class.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
use wcf\data\package\installation\queue\PackageInstallationQueueEditor;
1111
use wcf\data\user\User;
1212
use wcf\data\user\UserAction;
13-
use wcf\system\cache\builder\LanguageCacheBuilder;
13+
use wcf\system\cache\eager\LanguageCache;
1414
use wcf\system\database\Database;
1515
use wcf\system\database\exception\DatabaseException;
1616
use wcf\system\database\MySQLDatabase;
@@ -779,7 +779,7 @@ protected function installLanguage(): ResponseInterface
779779
LanguageFactory::getInstance()->makeDefault($language->languageID);
780780

781781
// rebuild language cache
782-
LanguageCacheBuilder::getInstance()->reset();
782+
(new LanguageCache())->rebuild();
783783

784784
return $this->gotoNextStep('createUser');
785785
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
namespace wcf\system\background\job;
4+
5+
use wcf\system\cache\CacheHandler;
6+
use wcf\system\cache\tolerant\AbstractTolerantCache;
7+
8+
/**
9+
* Rebuilds the cache data of a tolerant cache.
10+
*
11+
* @author Olaf Braun
12+
* @copyright 2001-2025 WoltLab GmbH
13+
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
14+
* @since 6.2
15+
*/
16+
final class TolerantCacheRebuildBackgroundJob extends AbstractUniqueBackgroundJob
17+
{
18+
public function __construct(
19+
/** @var class-string<AbstractTolerantCache<array|object> */
20+
public readonly string $cacheClass,
21+
/** @var array<string, mixed> */
22+
public readonly array $parameters = []
23+
) {
24+
}
25+
26+
public function identifier(): string
27+
{
28+
$identifier = $this->cacheClass;
29+
if (!empty($this->parameters)) {
30+
$identifier .= '-' . CacheHandler::getInstance()->getCacheIndex($this->parameters);
31+
}
32+
33+
return $identifier;
34+
}
35+
36+
#[\Override]
37+
public function newInstance(): static
38+
{
39+
return new TolerantCacheRebuildBackgroundJob($this->cacheClass, $this->parameters);
40+
}
41+
42+
#[\Override]
43+
public function queueAgain(): bool
44+
{
45+
return false;
46+
}
47+
48+
#[\Override]
49+
public function perform()
50+
{
51+
if (!\class_exists($this->cacheClass)) {
52+
return;
53+
}
54+
55+
$asyncCache = new $this->cacheClass(...$this->parameters);
56+
\assert($asyncCache instanceof AbstractTolerantCache);
57+
58+
$asyncCache->rebuild();
59+
}
60+
}

wcfsetup/install/files/lib/system/box/WhoWasOnlineBoxController.class.php

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
use wcf\data\user\online\UserOnline;
88
use wcf\data\user\online\UsersOnlineList;
99
use wcf\data\user\UserProfile;
10-
use wcf\system\cache\builder\WhoWasOnlineCacheBuilder;
1110
use wcf\system\cache\runtime\UserProfileRuntimeCache;
11+
use wcf\system\cache\tolerant\WhoWasOnlineCache;
1212
use wcf\system\event\EventHandler;
1313
use wcf\system\WCF;
1414
use wcf\util\DateUtil;
@@ -100,14 +100,9 @@ protected function readObjects()
100100
{
101101
EventHandler::getInstance()->fireAction($this, 'readObjects');
102102

103-
$userIDs = WhoWasOnlineCacheBuilder::getInstance()->getData();
103+
$userIDs = (new WhoWasOnlineCache())->getCache();
104104

105105
if (!empty($userIDs)) {
106-
if (WCF::getUser()->userID && !\in_array(WCF::getUser()->userID, $userIDs)) {
107-
// current user is missing in cache -> reset cache
108-
WhoWasOnlineCacheBuilder::getInstance()->reset();
109-
}
110-
111106
$this->users = \array_filter(
112107
UserProfileRuntimeCache::getInstance()->getObjects($userIDs),
113108
static function ($user) {
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
namespace wcf\system\cache\builder;
4+
5+
use wcf\system\cache\CacheHandler;
6+
use wcf\system\exception\SystemException;
7+
use wcf\system\SingletonFactory;
8+
9+
/**
10+
* Provides a backwards compatible interface for ICacheBuilder classes that have been migrated to the eager or tolerant cache implementations.
11+
*
12+
* @author Olaf Braun
13+
* @copyright 2001-2025 WoltLab GmbH
14+
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
15+
*
16+
* @since 6.2
17+
* @deprecated 6.2
18+
*/
19+
abstract class AbstractLegacyCacheBuilder extends SingletonFactory implements ICacheBuilder
20+
{
21+
/**
22+
* @var array<string, array<string|int, mixed>>
23+
*/
24+
private array $cache = [];
25+
26+
#[\Override]
27+
public function getData(array $parameters = [], $arrayIndex = '')
28+
{
29+
$index = CacheHandler::getInstance()->getCacheIndex($parameters);
30+
if (isset($this->cache[$index])) {
31+
$cache = $this->cache[$index];
32+
} else {
33+
$cache = $this->rebuild($parameters);
34+
$this->cache[$index] = $cache;
35+
}
36+
37+
if (!empty($arrayIndex)) {
38+
if (!\array_key_exists($arrayIndex, $cache)) {
39+
throw new SystemException("array index '" . $arrayIndex . "' does not exist in cache resource");
40+
}
41+
42+
return $cache[$arrayIndex];
43+
}
44+
45+
return $cache;
46+
}
47+
48+
/**
49+
* Rebuilds cache for current resource.
50+
*/
51+
abstract protected function rebuild(array $parameters): array;
52+
53+
#[\Override]
54+
final public function getMaxLifetime()
55+
{
56+
return 0;
57+
}
58+
}

wcfsetup/install/files/lib/system/cache/builder/CoreObjectCacheBuilder.class.php

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,28 @@
22

33
namespace wcf\system\cache\builder;
44

5-
use wcf\data\core\object\CoreObjectList;
5+
use wcf\system\cache\eager\CoreObjectCache;
66

77
/**
88
* Caches the core objects.
99
*
10-
* @author Alexander Ebert
11-
* @copyright 2001-2019 WoltLab GmbH
10+
* @author Olaf Braun, Alexander Ebert
11+
* @copyright 2001-2025 WoltLab GmbH
1212
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
13+
*
14+
* @deprecated 6.2 use `CoreObjectCache` instead
1315
*/
14-
class CoreObjectCacheBuilder extends AbstractCacheBuilder
16+
class CoreObjectCacheBuilder extends AbstractLegacyCacheBuilder
1517
{
16-
/**
17-
* @inheritDoc
18-
*/
19-
public function rebuild(array $parameters)
18+
#[\Override]
19+
public function reset(array $parameters = [])
2020
{
21-
$data = [];
22-
23-
$coreObjectList = new CoreObjectList();
24-
$coreObjectList->readObjects();
25-
$coreObjects = $coreObjectList->getObjects();
26-
27-
foreach ($coreObjects as $coreObject) {
28-
$tmp = \explode('\\', $coreObject->objectName);
29-
$className = \array_pop($tmp);
30-
$data[$className] = $coreObject->objectName;
31-
}
21+
(new CoreObjectCache())->rebuild();
22+
}
3223

33-
return $data;
24+
#[\Override]
25+
public function rebuild(array $parameters): array
26+
{
27+
return (new CoreObjectCache())->getCache();
3428
}
3529
}

0 commit comments

Comments
 (0)