From 2970232790a24c07fb0154f901b4864d54a9d027 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 6 Nov 2025 20:08:44 +0100 Subject: [PATCH] fix: make failed availability check apply in the same request Signed-off-by: Robin Appelman --- .../Files/Storage/Wrapper/Availability.php | 13 +++++++--- .../Storage/Wrapper/AvailabilityTest.php | 26 +++++++++++++++++++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/lib/private/Files/Storage/Wrapper/Availability.php b/lib/private/Files/Storage/Wrapper/Availability.php index 32c51a1b25e..dc2f9a2e6ac 100644 --- a/lib/private/Files/Storage/Wrapper/Availability.php +++ b/lib/private/Files/Storage/Wrapper/Availability.php @@ -22,6 +22,7 @@ class Availability extends Wrapper { /** @var IConfig */ protected $config; + protected ?bool $available = null; public function __construct(array $parameters) { $this->config = $parameters['config'] ?? \OCP\Server::get(IConfig::class); @@ -54,11 +55,14 @@ class Availability extends Wrapper { } private function isAvailable(): bool { - $availability = $this->getAvailability(); - if (self::shouldRecheck($availability)) { - return $this->updateAvailability(); + if (is_null($this->available)) { + $availability = $this->getAvailability(); + if (self::shouldRecheck($availability)) { + return $this->updateAvailability(); + } + $this->available = $availability['available']; } - return $availability['available']; + return $this->available; } /** @@ -257,6 +261,7 @@ class Availability extends Wrapper { self::RECHECK_TTL_SEC ); } + $this->available = false; $this->getStorageCache()->setAvailability(false, $delay); if ($e !== null) { throw $e; diff --git a/tests/lib/Files/Storage/Wrapper/AvailabilityTest.php b/tests/lib/Files/Storage/Wrapper/AvailabilityTest.php index d890081cbb6..bc388a0a32b 100644 --- a/tests/lib/Files/Storage/Wrapper/AvailabilityTest.php +++ b/tests/lib/Files/Storage/Wrapper/AvailabilityTest.php @@ -155,4 +155,30 @@ class AvailabilityTest extends \Test\TestCase { $this->wrapper->mkdir('foobar'); } + + public function testUnavailableMultiple(): void { + $this->storage->expects($this->once()) + ->method('getAvailability') + ->willReturn(['available' => true, 'last_checked' => 0]); + $this->storage->expects($this->never()) + ->method('test'); + $this->storage + ->expects($this->once()) // load-bearing `once` + ->method('mkdir') + ->willThrowException(new StorageNotAvailableException()); + + try { + $this->wrapper->mkdir('foobar'); + $this->fail(); + } catch (StorageNotAvailableException) { + } + + $this->storage->expects($this->never())->method('file_exists'); + + try { + $this->wrapper->mkdir('foobar'); + $this->fail(); + } catch (StorageNotAvailableException) { + } + } }