From 53d48d6f294e2a5971667b2882c58ccfc673c68f Mon Sep 17 00:00:00 2001 From: Salvatore Martire <4652631+salmart-dev@users.noreply.github.com> Date: Thu, 23 Apr 2026 10:50:18 +0200 Subject: [PATCH] fix: track time spent in recursive markOrRun calls Signed-off-by: Salvatore Martire <4652631+salmart-dev@users.noreply.github.com> --- .../lib/Listener/SharesUpdatedListener.php | 15 ++++---- .../tests/SharesUpdatedListenerTest.php | 34 ++++++++++++++++++- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/apps/files_sharing/lib/Listener/SharesUpdatedListener.php b/apps/files_sharing/lib/Listener/SharesUpdatedListener.php index 5f1ece48b9999..800e223c8e9b3 100644 --- a/apps/files_sharing/lib/Listener/SharesUpdatedListener.php +++ b/apps/files_sharing/lib/Listener/SharesUpdatedListener.php @@ -43,9 +43,11 @@ class SharesUpdatedListener implements IEventListener { private float $cutOffMarkTime; /** - * The total amount of time we've spent so far processing updates + * Timestamp marking the first time this listener was triggered, used to + * determine if we should update the share date immediately or just mark the + * users for refresh. */ - private float $updatedTime = 0.0; + private ?float $firstRun = null; public function __construct( private readonly IManager $shareManager, @@ -128,14 +130,15 @@ public function handle(Event $event): void { } private function markOrRun(IUser $user, callable $callback): void { - $start = floatval($this->clock->now()->format('U.u')); - if ($this->cutOffMarkTime === -1.0 || $this->updatedTime < $this->cutOffMarkTime) { + $now = (float)$this->clock->now()->format('U.u'); + $this->firstRun ??= $now; + $elapsed = $now - $this->firstRun; + + if ($this->cutOffMarkTime === -1.0 || $elapsed < $this->cutOffMarkTime) { $callback(); } else { $this->markUserForRefresh($user); } - $end = floatval($this->clock->now()->format('U.u')); - $this->updatedTime += $end - $start; } private function updateOrMarkUser(IUser $user): void { diff --git a/apps/files_sharing/tests/SharesUpdatedListenerTest.php b/apps/files_sharing/tests/SharesUpdatedListenerTest.php index ec27bfdb08b75..74347e3382d69 100644 --- a/apps/files_sharing/tests/SharesUpdatedListenerTest.php +++ b/apps/files_sharing/tests/SharesUpdatedListenerTest.php @@ -39,6 +39,8 @@ class SharesUpdatedListenerTest extends \Test\TestCase { private LoggerInterface&MockObject $logger; private $clockFn; + private int $time = 0; + protected function setUp(): void { parent::setUp(); @@ -50,7 +52,7 @@ protected function setUp(): void { $this->userConfig = new MockUserConfig(); $this->clock = $this->createMock(ClockInterface::class); $this->clockFn = function () { - return new \DateTimeImmutable('@0'); + return new \DateTimeImmutable("@{$this->time}"); }; $this->clock->method('now') ->willReturnCallback(function () { @@ -161,6 +163,36 @@ public static function shareMarkAfterTimeProvider(): array { ]; } + public function testCutoffSpansMultipleHandleInvocations(): void { + $share = $this->createMock(IShare::class); + $user1 = $this->createUser('user1', ''); + + $this->manager->method('getUsersForShare') + ->willReturn([$user1]); + + $event = new ShareCreatedEvent($share); + $this->sharesUpdatedListener->setCutOffMarkTime(4); + + // First handle at t=0: firstRun=0, elapsed=0 < 0.5 → callback runs + $this->shareRecipientUpdater + ->expects($this->exactly(2)) + ->method('updateForAddedShare'); + + $this->assertFalse( + $this->userConfig->getValueBool($user1->getUID(), 'files_sharing', ConfigLexicon::USER_NEEDS_SHARE_REFRESH) + ); + + $this->sharesUpdatedListener->handle($event); + $this->time = 1; + $this->sharesUpdatedListener->handle($event); + $this->time = 4; + $this->sharesUpdatedListener->handle($event); + + $this->assertTrue( + $this->userConfig->getValueBool($user1->getUID(), 'files_sharing', ConfigLexicon::USER_NEEDS_SHARE_REFRESH) + ); + } + #[DataProvider('shareMarkAfterTimeProvider')] public function testShareMarkAfterTime(float $cutOff, int $expectedCount) { $share = $this->createMock(IShare::class);