Skip to content

Commit

Permalink
feat(cache): CLI should not fail if APCu is not available
Browse files Browse the repository at this point in the history
but fallback to NullCache. This can be the case if APCu is used without apc.enable_cli=1. APCu however runs within the PHP instance and hence cannot be shared between CLI and web or used as distributed cache. The CLI call can hence only create or invalidate entries for itself. For short-living CLI calls, this is theoretically a downsides regarding performance and resource usage, and Nextcloud must not have any issues using the dummy NullCache instead of an isolated freshly created and destroyed APCu instance.

This partly reverts #25770. The fallback was removed, because CLI calls started to hang after #25440. The reason however was not that a cache is generally required for CLI calls, but because the previously logged warning invoked the user backend, which invoked again the caching backend, causing a loop.

This commit re-adds the fallback without logging a warning, and for APCu only. For mentioned reasons, it is okay to fallback to NullCache silently. If Redis or memcached are configured but not available, then the web UI would fail as well, and it makes sense to abort and inform CLI calls as well then.

The motivation is to make apc.enable_cli=1 optional, and that hence the documentation about it can be removed. We should not enforce admins to enable APCu for CLI calls, which is reasonably disabled by default. This also reduces requirements for hosting providers to support Nextcloud.

Signed-off-by: MichaIng <micha@dietpi.com>
  • Loading branch information
MichaIng committed Jun 30, 2024
1 parent b77c151 commit 8e2df5e
Showing 1 changed file with 20 additions and 6 deletions.
26 changes: 20 additions & 6 deletions lib/private/Memcache/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,28 @@ public function __construct(string $globalPrefix, LoggerInterface $logger, IProf
$missingCacheMessage = 'Memcache {class} not available for {use} cache';
$missingCacheHint = 'Is the matching PHP module installed and enabled?';
if (!class_exists($localCacheClass) || !$localCacheClass::isAvailable()) {
throw new \OCP\HintException(strtr($missingCacheMessage, [
'{class}' => $localCacheClass, '{use}' => 'local'
]), $missingCacheHint);
if (\OC::$CLI && !defined('PHPUNIT_RUN') && $localCacheClass === APCu::class) {
// CLI should not fail if APCu is not available but fallback to NullCache.
// This can be the case if APCu is used without apc.enable_cli=1.
// APCu however cannot be shared between Nextcloud (PHP) instances anyway.
$localCacheClass = self::NULL_CACHE;
} else {
throw new \OCP\HintException(strtr($missingCacheMessage, [
'{class}' => $localCacheClass, '{use}' => 'local'
]), $missingCacheHint);
}
}
if (!class_exists($distributedCacheClass) || !$distributedCacheClass::isAvailable()) {
throw new \OCP\HintException(strtr($missingCacheMessage, [
'{class}' => $distributedCacheClass, '{use}' => 'distributed'
]), $missingCacheHint);
if (\OC::$CLI && !defined('PHPUNIT_RUN') && $distributedCacheClass === APCu::class) {
// CLI should not fail if APCu is not available but fallback to NullCache.
// This can be the case if APCu is used without apc.enable_cli=1.
// APCu however cannot be shared between Nextcloud (PHP) instances anyway.
$distributedCacheClass = self::NULL_CACHE;
} else {
throw new \OCP\HintException(strtr($missingCacheMessage, [
'{class}' => $distributedCacheClass, '{use}' => 'distributed'
]), $missingCacheHint);
}
}
if (!($lockingCacheClass && class_exists($lockingCacheClass) && $lockingCacheClass::isAvailable())) {
// don't fall back since the fallback might not be suitable for storing lock
Expand Down

0 comments on commit 8e2df5e

Please sign in to comment.