Skip to content

Commit fc45198

Browse files
gr8manmichalsn
andauthored
fix: use dynamic lockMaxRetries limit in RedisHandler (#10295)
* fix: use dynamic lockMaxRetries limit in RedisHandler * fix: read correct config property names in RedisHandler lockSession * fix: add lockMaxRetries test and remove stale PHPStan baseline entries * fix: add setLogger to RedisHandlerTest to prevent null logger error * Update system/Session/Handlers/RedisHandler.php Co-authored-by: Michal Sniatala <michal@sniatala.pl> * Fix PHPStan warnings for RedisHandler and update changelog * Update user_guide_src/source/changelogs/v4.7.4.rst Co-authored-by: Michal Sniatala <michal@sniatala.pl> * docs: alphabetize changelog entries and properties in v4.7.4.rst --------- Co-authored-by: Michal Sniatala <michal@sniatala.pl>
1 parent 56bace9 commit fc45198

4 files changed

Lines changed: 34 additions & 16 deletions

File tree

system/Session/Handlers/RedisHandler.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ public function __construct(SessionConfig $config, string $ipAddress)
9898
$this->keyPrefix .= $this->ipAddress . ':';
9999
}
100100

101-
$this->lockRetryInterval = $config->lockWait ?? $this->lockRetryInterval;
102-
$this->lockMaxRetries = $config->lockAttempts ?? $this->lockMaxRetries;
101+
$this->lockRetryInterval = $config->lockRetryInterval ?? $this->lockRetryInterval; // @phpstan-ignore nullCoalesce.property
102+
$this->lockMaxRetries = $config->lockMaxRetries ?? $this->lockMaxRetries; // @phpstan-ignore nullCoalesce.property
103103
}
104104

105105
protected function setSavePath(): void
@@ -386,10 +386,10 @@ protected function lockSession(string $sessionID): bool
386386
break;
387387
} while (++$attempt < $this->lockMaxRetries);
388388

389-
if ($attempt === 300) {
389+
if ($attempt === $this->lockMaxRetries) {
390390
$this->logger->error(
391391
'Session: Unable to obtain lock for ' . $this->keyPrefix . $sessionID
392-
. ' after 300 attempts, aborting.',
392+
. ' after ' . $this->lockMaxRetries . ' attempts, aborting.',
393393
);
394394

395395
return false;

tests/system/Session/Handlers/Database/RedisHandlerTest.php

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616
use CodeIgniter\Session\Handlers\RedisHandler;
1717
use CodeIgniter\Test\CIUnitTestCase;
18+
use CodeIgniter\Test\TestLogger;
19+
use Config\Logger as LoggerConfig;
1820
use Config\Session as SessionConfig;
1921
use PHPUnit\Framework\Attributes\DataProvider;
2022
use PHPUnit\Framework\Attributes\Group;
@@ -54,7 +56,10 @@ protected function getInstance($options = []): RedisHandler
5456
$sessionConfig->{$key} = $value;
5557
}
5658

57-
return new RedisHandler($sessionConfig, $this->userIpAddress);
59+
$handler = new RedisHandler($sessionConfig, $this->userIpAddress);
60+
$handler->setLogger(new TestLogger(new LoggerConfig()));
61+
62+
return $handler;
5863
}
5964

6065
protected function tearDown(): void
@@ -359,4 +364,26 @@ public function testResetPersistentConnections(): void
359364
$handler1->close();
360365
$handler2->close();
361366
}
367+
368+
public function testLockMaxRetries(): void
369+
{
370+
$options = [
371+
'lockRetryInterval' => 10_000, // 10ms
372+
'lockMaxRetries' => 3,
373+
];
374+
375+
$handler1 = $this->getInstance($options);
376+
$handler1->open($this->sessionSavePath, $this->sessionName);
377+
$handler1->read('lock_test_session'); // Acquires lock
378+
379+
$handler2 = $this->getInstance($options);
380+
$handler2->open($this->sessionSavePath, $this->sessionName);
381+
382+
// Before the fix, this would incorrectly return true (since $attempt === 3 !== 300).
383+
// With the fix, it should return false after 3 attempts.
384+
$this->assertFalse($handler2->read('lock_test_session'));
385+
386+
$handler1->close();
387+
$handler2->close();
388+
}
362389
}

user_guide_src/source/changelogs/v4.7.4.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ Bugs Fixed
3636
- **Filters:** Fixed a bug in ``InvalidChars`` filter where invalid UTF-8 or control characters in array keys were not checked.
3737
- **HTTP:** Fixed a bug where the User Agent library reported Safari's WebKit version instead of the browser version from the ``Version`` token.
3838
- **Model:** Fixed a bug in ``Model::objectToRawArray()`` where the ``$recursive`` parameter was ignored.
39+
- **Session:** Fixed a bug in ``RedisHandler`` where the configured ``$lockMaxRetries`` and ``$lockRetryInterval`` values were not respected when acquiring session locks.
3940
- **Testing:** Fixed a bug where using ``MockInputOutput`` within a test that also uses ``StreamFilterTrait`` tore down the trait's stream filters, so CLI output produced after the ``MockInputOutput`` interaction (such as in ``tearDown()``) was no longer captured and leaked to the console.
4041

4142
See the repo's

utils/phpstan-baseline/property.notFound.neon

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# total 49 errors
1+
# total 47 errors
22

33
parameters:
44
ignoreErrors:
@@ -17,16 +17,6 @@ parameters:
1717
count: 14
1818
path: ../../system/Database/SQLSRV/Forge.php
1919

20-
-
21-
message: '#^Access to an undefined property Config\\Session\:\:\$lockAttempts\.$#'
22-
count: 1
23-
path: ../../system/Session/Handlers/RedisHandler.php
24-
25-
-
26-
message: '#^Access to an undefined property Config\\Session\:\:\$lockWait\.$#'
27-
count: 1
28-
path: ../../system/Session/Handlers/RedisHandler.php
29-
3020
-
3121
message: '#^Access to an undefined property CodeIgniter\\Database\\BaseConnection\:\:\$mysqli\.$#'
3222
count: 1

0 commit comments

Comments
 (0)