Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
1ea6e8f
Basic eager cache implementation
Cyperghost Feb 20, 2025
2dde79e
Remove unnecessary `IEagerCache`
Cyperghost Feb 20, 2025
7378ebc
Implement the core object cache as an eager cache
Cyperghost Feb 20, 2025
86d2c0c
Implement the language cache as an eager cache
Cyperghost Feb 20, 2025
7b111be
Rename function `getCategoryByID()` to `getLanguageCategoryByID()`
Cyperghost Feb 20, 2025
4f1c295
Remove old `LanguageCacheBuilder`
Cyperghost Feb 20, 2025
e471fae
Use more unique function names in `AbstractEagerCache`
Cyperghost Feb 20, 2025
867b722
Always use the current language cache
Cyperghost Feb 20, 2025
b3f827b
Disabled flag must be reset beforehand, otherwise the default languag…
Cyperghost Feb 20, 2025
09a81d3
Do not use the members that have not been set(`null`).
Cyperghost Feb 20, 2025
fa8d284
Prevent access to uninitialized members or static variables
Cyperghost Feb 20, 2025
eeafaec
Clean up code
Cyperghost Feb 21, 2025
3313287
Use the cache data directly instead of always fetching the current ca…
Cyperghost Feb 21, 2025
5ebecc0
Use helper functions of `LanguageCacheData`
Cyperghost Feb 21, 2025
a81e06a
Change default value to `null`
Cyperghost Feb 21, 2025
1992e18
Implementation of a legacy cache builder for the migrated caches to t…
Cyperghost Feb 21, 2025
67589a1
`MaxLifetime` is no longer needed and mapped to zero(`0`)
Cyperghost Feb 21, 2025
9e645ac
simplify the code
Cyperghost Feb 21, 2025
5b956a2
simplify the code
Cyperghost Feb 21, 2025
b7d0b6e
Ensure that Eager caches are only created once at runtime for the sam…
Cyperghost Feb 21, 2025
0c572ae
Apply suggestions from code review
Cyperghost Feb 21, 2025
d0732ff
Implement `ICacheSource::getCacheLifetime()``
Cyperghost Feb 21, 2025
4cacf60
Implement `AbstractTolerantCache` and the background job for it
Cyperghost Feb 21, 2025
b4c1de2
Remove indentation in copyright block
Cyperghost Feb 21, 2025
422f572
Add php doc for `AbstractLegacyCacheBuilder::$cache`
Cyperghost Feb 21, 2025
77919e3
Use `\RuntimeException` instead of `SystemException`
Cyperghost Feb 21, 2025
1837afe
Remove the `Language` from all functions that are used for the langua…
Cyperghost Feb 21, 2025
9ba8815
Use the code only when in WCFSetup
Cyperghost Feb 21, 2025
29b3e3f
Implement `WhoWasOnlineCache` as tolerant cache
Cyperghost Feb 21, 2025
3cad83b
Implement `UserBirthdayCache` as tolerant cache
Cyperghost Feb 21, 2025
71418e8
Add php doc for `getLifetime()`
Cyperghost Feb 21, 2025
c54c483
Update wcfsetup/install/files/lib/system/cache/builder/AbstractLegacy…
Cyperghost Feb 21, 2025
a2b73f8
Let the cache go stale more often and queue the refresh only when nec…
Cyperghost Feb 21, 2025
c8193e5
Use the default retry value of 60 seconds, not the long lifetime of t…
Cyperghost Feb 21, 2025
017fa57
`ICacheSource::getCacheLifetime()` requires a second parameter to cal…
Cyperghost Feb 21, 2025
0f563ea
Remove whitespaces from union types
Cyperghost Feb 21, 2025
2877423
Merge branch 'refs/heads/6.2-overhaul-caching' into 6.2-tolerant-cache
Cyperghost Feb 21, 2025
08d3da9
Remove whitespaces from union types
Cyperghost Feb 21, 2025
5da722a
We cannot determine for sure the expiration date of the cache, theref…
Cyperghost Feb 21, 2025
95bf441
Merge branch '6.2' into 6.2-tolerant-cache
Cyperghost Mar 17, 2025
91165bc
Use probabilistic early expiration for tolerant cache
Cyperghost Mar 17, 2025
dc43423
Fix phpstan type
Cyperghost Mar 18, 2025
e1d71a8
Add php class docs
Cyperghost Mar 18, 2025
f1f9028
Make sure that $lifetime is `>= 300`
Cyperghost Mar 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion wcfsetup/install/files/lib/acp/form/BoxAddForm.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,7 @@ public function save()
'cssClassName' => $this->cssClassName,
'showHeader' => $this->showHeader,
'isDisabled' => $this->isDisabled ? 1 : 0,
'linkPageID' => $this->linkPageID,
'linkPageID' => $this->linkPageID ?: null,
'linkPageObjectID' => $this->linkPageObjectID ?: 0,
'externalURL' => $this->externalURL,
'identifier' => '',
Expand Down
2 changes: 1 addition & 1 deletion wcfsetup/install/files/lib/acp/form/BoxEditForm.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ public function save()
'cssClassName' => $this->cssClassName,
'showHeader' => $this->showHeader,
'isDisabled' => $this->isDisabled ? 1 : 0,
'linkPageID' => $this->linkPageID,
'linkPageID' => $this->linkPageID ?: null,
'linkPageObjectID' => $this->linkPageObjectID ?: 0,
'externalURL' => $this->externalURL,
'invertPermissions' => $this->invertPermissions,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use wcf\data\language\Language;
use wcf\data\language\LanguageEditor;
use wcf\form\AbstractForm;
use wcf\system\cache\builder\LanguageCacheBuilder;
use wcf\system\cache\eager\LanguageCache;
use wcf\system\exception\UserInputException;
use wcf\system\language\LanguageFactory;
use wcf\system\WCF;
Expand Down Expand Up @@ -116,7 +116,7 @@ public function save()
LanguageEditor::enableMultilingualism(($this->enable == 1 ? $this->languageIDs : []));

// clear cache
LanguageCacheBuilder::getInstance()->reset();
(new LanguageCache())->rebuild();
$this->saved();

// show success message
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
use wcf\data\language\item\LanguageItemList;
use wcf\data\page\PageEditor;
use wcf\event\language\LanguageContentCopying;
use wcf\system\cache\builder\LanguageCacheBuilder;
use wcf\system\cache\eager\LanguageCache;
use wcf\system\database\util\PreparedStatementConditionBuilder;
use wcf\system\event\EventHandler;
use wcf\system\exception\SystemException;
Expand Down Expand Up @@ -932,7 +932,7 @@ public function setAsDefault()
$statement->execute([0]);

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

$this->clearCache();
}
Expand All @@ -944,7 +944,7 @@ public function setAsDefault()
*/
public function clearCache()
{
LanguageCacheBuilder::getInstance()->reset();
(new LanguageCache())->rebuild();
}

/**
Expand Down
16 changes: 6 additions & 10 deletions wcfsetup/install/files/lib/system/WCF.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,12 @@
use wcf\system\application\IApplication;
use wcf\system\benchmark\Benchmark;
use wcf\system\box\BoxHandler;
use wcf\system\cache\builder\CoreObjectCacheBuilder;
use wcf\system\cache\builder\PackageUpdateCacheBuilder;
use wcf\system\cache\eager\CoreObjectCache;
use wcf\system\database\MySQLDatabase;
use wcf\system\event\EventHandler;
use wcf\system\exception\ErrorException;
use wcf\system\exception\IPrintableException;
use wcf\system\exception\ParentClassException;
use wcf\system\exception\SystemException;
use wcf\system\language\LanguageFactory;
use wcf\system\package\command\RebuildBootstrapper;
Expand Down Expand Up @@ -140,9 +139,10 @@ class WCF

/**
* list of cached core objects
* @var string[]
*
* @var array<string, class-string<SingletonFactory>>
*/
protected static $coreObjectCache = [];
protected static array $coreObjectCache;

/**
* database object
Expand Down Expand Up @@ -752,7 +752,7 @@ protected function initCoreObjects(): void
return;
}

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

/**
Expand Down Expand Up @@ -919,10 +919,6 @@ final public static function __callStatic(string $name, array $arguments)
}

if (\class_exists($objectName)) {
if (!\is_subclass_of($objectName, SingletonFactory::class)) {
throw new ParentClassException($objectName, SingletonFactory::class);
}

self::$coreObject[$className] = \call_user_func([$objectName, 'getInstance']);

return self::$coreObject[$className];
Expand All @@ -934,7 +930,7 @@ final public static function __callStatic(string $name, array $arguments)
/**
* Searches for cached core object definition.
*
* @return string|null
* @return class-string<SingletonFactory>|null
*/
final protected static function getCoreObject(string $className)
{
Expand Down
4 changes: 2 additions & 2 deletions wcfsetup/install/files/lib/system/WCFSetup.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
use wcf\data\package\installation\queue\PackageInstallationQueueEditor;
use wcf\data\user\User;
use wcf\data\user\UserAction;
use wcf\system\cache\builder\LanguageCacheBuilder;
use wcf\system\cache\eager\LanguageCache;
use wcf\system\database\Database;
use wcf\system\database\exception\DatabaseException;
use wcf\system\database\MySQLDatabase;
Expand Down Expand Up @@ -779,7 +779,7 @@ protected function installLanguage(): ResponseInterface
LanguageFactory::getInstance()->makeDefault($language->languageID);

// rebuild language cache
LanguageCacheBuilder::getInstance()->reset();
(new LanguageCache())->rebuild();

return $this->gotoNextStep('createUser');
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

namespace wcf\system\background\job;

use wcf\system\cache\CacheHandler;
use wcf\system\cache\tolerant\AbstractTolerantCache;

/**
* Rebuilds the cache data of a tolerant cache.
*
* @author Olaf Braun
* @copyright 2001-2025 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @since 6.2
*/
final class TolerantCacheRebuildBackgroundJob extends AbstractUniqueBackgroundJob
{
public function __construct(
/** @var class-string<AbstractTolerantCache<array|object> */
public readonly string $cacheClass,
/** @var array<string, mixed> */
public readonly array $parameters = []
) {
}

public function identifier(): string
{
$identifier = $this->cacheClass;
if (!empty($this->parameters)) {
$identifier .= '-' . CacheHandler::getInstance()->getCacheIndex($this->parameters);
}

return $identifier;
}

#[\Override]
public function newInstance(): static
{
return new TolerantCacheRebuildBackgroundJob($this->cacheClass, $this->parameters);
}

#[\Override]
public function queueAgain(): bool
{
return false;
}

#[\Override]
public function perform()
{
if (!\class_exists($this->cacheClass)) {
return;
}

$asyncCache = new $this->cacheClass(...$this->parameters);
\assert($asyncCache instanceof AbstractTolerantCache);

$asyncCache->rebuild();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
use wcf\data\user\online\UserOnline;
use wcf\data\user\online\UsersOnlineList;
use wcf\data\user\UserProfile;
use wcf\system\cache\builder\WhoWasOnlineCacheBuilder;
use wcf\system\cache\runtime\UserProfileRuntimeCache;
use wcf\system\cache\tolerant\WhoWasOnlineCache;
use wcf\system\event\EventHandler;
use wcf\system\WCF;
use wcf\util\DateUtil;
Expand Down Expand Up @@ -100,14 +100,9 @@ protected function readObjects()
{
EventHandler::getInstance()->fireAction($this, 'readObjects');

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

if (!empty($userIDs)) {
if (WCF::getUser()->userID && !\in_array(WCF::getUser()->userID, $userIDs)) {
// current user is missing in cache -> reset cache
WhoWasOnlineCacheBuilder::getInstance()->reset();
}

$this->users = \array_filter(
UserProfileRuntimeCache::getInstance()->getObjects($userIDs),
static function ($user) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

namespace wcf\system\cache\builder;

use wcf\system\cache\CacheHandler;
use wcf\system\exception\SystemException;
use wcf\system\SingletonFactory;

/**
* Provides a backwards compatible interface for ICacheBuilder classes that have been migrated to the eager or tolerant cache implementations.
*
* @author Olaf Braun
* @copyright 2001-2025 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
*
* @since 6.2
* @deprecated 6.2
*/
abstract class AbstractLegacyCacheBuilder extends SingletonFactory implements ICacheBuilder
{
/**
* @var array<string, array<string|int, mixed>>
*/
private array $cache = [];

#[\Override]
public function getData(array $parameters = [], $arrayIndex = '')
{
$index = CacheHandler::getInstance()->getCacheIndex($parameters);
if (isset($this->cache[$index])) {
$cache = $this->cache[$index];
} else {
$cache = $this->rebuild($parameters);
$this->cache[$index] = $cache;
}

if (!empty($arrayIndex)) {
if (!\array_key_exists($arrayIndex, $cache)) {
throw new SystemException("array index '" . $arrayIndex . "' does not exist in cache resource");
}

return $cache[$arrayIndex];
}

return $cache;
}

/**
* Rebuilds cache for current resource.
*/
abstract protected function rebuild(array $parameters): array;

#[\Override]
final public function getMaxLifetime()
{
return 0;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,28 @@

namespace wcf\system\cache\builder;

use wcf\data\core\object\CoreObjectList;
use wcf\system\cache\eager\CoreObjectCache;

/**
* Caches the core objects.
*
* @author Alexander Ebert
* @copyright 2001-2019 WoltLab GmbH
* @author Olaf Braun, Alexander Ebert
* @copyright 2001-2025 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
*
* @deprecated 6.2 use `CoreObjectCache` instead
*/
class CoreObjectCacheBuilder extends AbstractCacheBuilder
class CoreObjectCacheBuilder extends AbstractLegacyCacheBuilder
{
/**
* @inheritDoc
*/
public function rebuild(array $parameters)
#[\Override]
public function reset(array $parameters = [])
{
$data = [];

$coreObjectList = new CoreObjectList();
$coreObjectList->readObjects();
$coreObjects = $coreObjectList->getObjects();

foreach ($coreObjects as $coreObject) {
$tmp = \explode('\\', $coreObject->objectName);
$className = \array_pop($tmp);
$data[$className] = $coreObject->objectName;
}
(new CoreObjectCache())->rebuild();
}

return $data;
#[\Override]
public function rebuild(array $parameters): array
{
return (new CoreObjectCache())->getCache();
}
}
Loading