Skip to content

Commit 90dcf18

Browse files
alcaeusjmikola
andauthored
PHPLIB-1531: Replace FailPointObserver with different logic (#1427)
* Extract fail point management to a trait used by Context * Ensure event listeners are still unregistered after an operation fails This change was prompted by the addition of a finally block after executing operations. It may address a memory leak whereby listeners (and the Context they reference) would remain in PHPC's global registry until RSHUTDOWN. --------- Co-authored-by: Jeremy Mikola <[email protected]>
1 parent 50d1db7 commit 90dcf18

File tree

5 files changed

+55
-81
lines changed

5 files changed

+55
-81
lines changed

tests/UnifiedSpecTests/Context.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
*/
3939
final class Context
4040
{
41+
use ManagesFailPointsTrait;
42+
4143
private ?string $activeClient = null;
4244

4345
private EntityMap $entityMap;

tests/UnifiedSpecTests/FailPointObserver.php

Lines changed: 0 additions & 63 deletions
This file was deleted.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
namespace MongoDB\Tests\UnifiedSpecTests;
4+
5+
use MongoDB\Driver\Server;
6+
use MongoDB\Operation\DatabaseCommand;
7+
use stdClass;
8+
9+
use function PHPUnit\Framework\assertIsString;
10+
use function PHPUnit\Framework\assertObjectHasAttribute;
11+
12+
trait ManagesFailPointsTrait
13+
{
14+
/** @var list<list{string, Server}> */
15+
private array $failPointsAndServers = [];
16+
17+
public function configureFailPoint(stdClass $failPoint, Server $server): void
18+
{
19+
assertObjectHasAttribute('configureFailPoint', $failPoint);
20+
assertIsString($failPoint->configureFailPoint);
21+
assertObjectHasAttribute('mode', $failPoint);
22+
23+
$operation = new DatabaseCommand('admin', $failPoint);
24+
$operation->execute($server);
25+
26+
if ($failPoint->mode !== 'off') {
27+
$this->failPointsAndServers[] = [$failPoint->configureFailPoint, $server];
28+
}
29+
}
30+
31+
public function disableFailPoints(): void
32+
{
33+
foreach ($this->failPointsAndServers as [$failPoint, $server]) {
34+
$operation = new DatabaseCommand('admin', ['configureFailPoint' => $failPoint, 'mode' => 'off']);
35+
$operation->execute($server);
36+
}
37+
38+
$this->failPointsAndServers = [];
39+
}
40+
}

tests/UnifiedSpecTests/Operation.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
use MongoDB\Model\CollectionInfo;
1717
use MongoDB\Model\DatabaseInfo;
1818
use MongoDB\Model\IndexInfo;
19-
use MongoDB\Operation\DatabaseCommand;
2019
use MongoDB\Operation\FindOneAndReplace;
2120
use MongoDB\Operation\FindOneAndUpdate;
2221
use PHPUnit\Framework\Assert;
@@ -909,16 +908,17 @@ private function executeForTestRunner()
909908
assertArrayHasKey('failPoint', $args);
910909
assertInstanceOf(Client::class, $args['client']);
911910
assertInstanceOf(stdClass::class, $args['failPoint']);
912-
$args['client']->selectDatabase('admin')->command($args['failPoint']);
911+
// Configure the fail point via the Context so it can later be disabled
912+
$this->context->configureFailPoint($args['failPoint'], $args['client']->getManager()->selectServer());
913913
break;
914914
case 'targetedFailPoint':
915915
assertArrayHasKey('session', $args);
916916
assertArrayHasKey('failPoint', $args);
917917
assertInstanceOf(Session::class, $args['session']);
918918
assertInstanceOf(stdClass::class, $args['failPoint']);
919919
assertNotNull($args['session']->getServer(), 'Session is pinned');
920-
$operation = new DatabaseCommand('admin', $args['failPoint']);
921-
$operation->execute($args['session']->getServer());
920+
// Configure the fail point via the Context so it can later be disabled
921+
$this->context->configureFailPoint($args['failPoint'], $args['session']->getServer());
922922
break;
923923
case 'loop':
924924
assertArrayHasKey('operations', $args);

tests/UnifiedSpecTests/UnifiedTestRunner.php

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,6 @@ final class UnifiedTestRunner
7777
/** @var callable(EntityMap):void */
7878
private $entityMapObserver;
7979

80-
private ?FailPointObserver $failPointObserver = null;
81-
8280
private ServerParameterHelper $serverParameterHelper;
8381

8482
public function __construct(string $internalClientUri)
@@ -150,9 +148,6 @@ private function doSetUp(): void
150148
* after transient error within a transaction" pinning test causes the
151149
* subsequent transaction test to block. */
152150
$this->killAllSessions();
153-
154-
$this->failPointObserver = new FailPointObserver();
155-
$this->failPointObserver->start();
156151
}
157152

158153
private function doTearDown(bool $hasFailed): void
@@ -163,9 +158,6 @@ private function doTearDown(bool $hasFailed): void
163158
$this->killAllSessions();
164159
}
165160

166-
$this->failPointObserver->stop();
167-
$this->failPointObserver->disableFailPoints();
168-
169161
/* Manually invoking garbage collection since each test is prone to
170162
* create cycles (perhaps due to EntityMap), which can leak and prevent
171163
* sessions from being released back into the pool. */
@@ -216,14 +208,17 @@ private function doTestCase(stdClass $test, string $schemaVersion, ?array $runOn
216208
$context->startEventObservers();
217209
$context->startEventCollectors();
218210

219-
foreach ($test->operations as $o) {
220-
$operation = new Operation($o, $context);
221-
$operation->assert();
211+
try {
212+
foreach ($test->operations as $o) {
213+
$operation = new Operation($o, $context);
214+
$operation->assert();
215+
}
216+
} finally {
217+
$context->stopEventObservers();
218+
$context->stopEventCollectors();
219+
$context->disableFailPoints();
222220
}
223221

224-
$context->stopEventObservers();
225-
$context->stopEventCollectors();
226-
227222
if (isset($test->expectEvents)) {
228223
assertIsArray($test->expectEvents);
229224
$context->assertExpectedEventsForClients($test->expectEvents);

0 commit comments

Comments
 (0)