Skip to content

Commit 8e73a4c

Browse files
committed
wip
1 parent 22895f0 commit 8e73a4c

File tree

6 files changed

+88
-52
lines changed

6 files changed

+88
-52
lines changed

system/CodeIgniter.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -208,11 +208,6 @@ public function resetForWorkerMode(): void
208208
// Reset timing
209209
$this->startTime = null;
210210
$this->totalTime = 0;
211-
212-
// Clean any leftover output buffers (safety measure for errors)
213-
while (ob_get_level() > 0) {
214-
ob_end_clean();
215-
}
216211
}
217212

218213
/**

system/Database/Config.php

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,8 @@ public static function validateForWorkerMode(): void
176176
/**
177177
* Cleanup database connections for worker mode.
178178
*
179-
* If any uncommitted transactions are found, the connection
180-
* is closed and reconnected to ensure a clean state for the next request.
179+
* Rolls back any uncommitted transactions and resets transaction status
180+
* to ensure a clean state for the next request.
181181
*
182182
* Uncommitted transactions at this point indicate a bug in the
183183
* application code (transactions should be completed before request ends).
@@ -188,10 +188,14 @@ public static function cleanupForWorkerMode(): void
188188
{
189189
foreach (static::$instances as $group => $connection) {
190190
if ($connection->transDepth > 0) {
191-
log_message('error', "Uncommitted transaction detected in database group '{$group}'. Transactions must be completed before request ends. Reconnecting to ensure clean state.");
192-
$connection->close();
193-
$connection->initialize();
191+
log_message('error', "Uncommitted transaction detected in database group '{$group}'. Transactions must be completed before request ends.");
192+
193+
while ($connection->transDepth > 0) {
194+
$connection->transRollback();
195+
}
194196
}
197+
198+
$connection->resetTransStatus();
195199
}
196200
}
197201
}

tests/system/CommonSingleServiceTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,12 @@ public static function provideServiceNames(): iterable
9191
'reset',
9292
'resetSingle',
9393
'resetServicesCache',
94+
'resetForWorkerMode',
9495
'injectMock',
96+
'has',
9597
'encrypter', // Encrypter needs a starter key
9698
'session', // Headers already sent
99+
'validateForWorkerMode',
97100
];
98101

99102
if ($services === []) {

tests/system/Database/ConfigTest.php

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -239,31 +239,4 @@ public static function provideConvertDSN(): iterable
239239
],
240240
];
241241
}
242-
243-
#[Group('DatabaseLive')]
244-
public function testResetForWorkerMode(): void
245-
{
246-
$conn = Config::connect();
247-
$this->assertInstanceOf(BaseConnection::class, $conn);
248-
249-
$conn->transStart();
250-
$this->assertGreaterThan(0, $conn->transDepth);
251-
252-
Config::cleanupForWorkerMode();
253-
254-
$this->assertSame(0, $conn->transDepth);
255-
$this->assertNotFalse($this->getPrivateProperty($conn, 'connID'));
256-
}
257-
258-
#[Group('DatabaseLive')]
259-
public function testValidateForWorkerMode(): void
260-
{
261-
$conn = Config::connect();
262-
$this->assertInstanceOf(BaseConnection::class, $conn);
263-
$this->assertNotFalse($this->getPrivateProperty($conn, 'connID'));
264-
265-
Config::validateForWorkerMode();
266-
267-
$this->assertNotFalse($this->getPrivateProperty($conn, 'connID'));
268-
}
269242
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of CodeIgniter 4 framework.
7+
*
8+
* (c) CodeIgniter Foundation <admin@codeigniter.com>
9+
*
10+
* For the full copyright and license information, please view
11+
* the LICENSE file that was distributed with this source code.
12+
*/
13+
14+
namespace CodeIgniter\Database\Live;
15+
16+
use CodeIgniter\Database\BaseConnection;
17+
use CodeIgniter\Database\Config;
18+
use CodeIgniter\Test\CIUnitTestCase;
19+
use CodeIgniter\Test\DatabaseTestTrait;
20+
use PHPUnit\Framework\Attributes\Group;
21+
22+
/**
23+
* @internal
24+
*/
25+
#[Group('DatabaseLive')]
26+
final class WorkerModeTest extends CIUnitTestCase
27+
{
28+
use DatabaseTestTrait;
29+
30+
protected function tearDown(): void
31+
{
32+
parent::tearDown();
33+
34+
$this->setPrivateProperty(Config::class, 'instances', []);
35+
}
36+
37+
public function testCleanupForWorkerMode(): void
38+
{
39+
$conn = Config::connect();
40+
$this->assertInstanceOf(BaseConnection::class, $conn);
41+
42+
$conn->transStart();
43+
$this->assertGreaterThan(0, $conn->transDepth);
44+
45+
Config::cleanupForWorkerMode();
46+
47+
$this->assertSame(0, $conn->transDepth);
48+
$this->assertNotFalse($this->getPrivateProperty($conn, 'connID'));
49+
}
50+
51+
public function testValidateForWorkerMode(): void
52+
{
53+
$conn = Config::connect();
54+
$this->assertInstanceOf(BaseConnection::class, $conn);
55+
$this->assertNotFalse($this->getPrivateProperty($conn, 'connID'));
56+
57+
Config::validateForWorkerMode();
58+
59+
$this->assertNotFalse($this->getPrivateProperty($conn, 'connID'));
60+
}
61+
}

user_guide_src/source/installation/worker_mode.rst

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,8 @@ Option Type Description
184184
======================= ======= ==========================================================================
185185
**$persistentServices** array Services that persist across requests and are not reset. Services not
186186
in this list are destroyed after each request to prevent state leakage.
187-
Default: ``['autoloader', 'locator', 'exceptions', 'logger', 'timer',
188-
'commands', 'codeigniter', 'superglobals', 'routes', 'cache']``
187+
Default: ``['autoloader', 'locator', 'exceptions', 'commands',
188+
'codeigniter', 'superglobals', 'routes', 'cache']``
189189
**$garbageCollection** bool Whether to force garbage collection after each request.
190190
``true`` (default, recommended): Prevents memory leaks.
191191
``false``: Relies on PHP's automatic garbage collection.
@@ -197,18 +197,18 @@ Persistent Services
197197
The ``$persistentServices`` array controls which services survive between requests.
198198
The default configuration includes:
199199

200-
===================== ==========================================================================
201-
Service Purpose
202-
===================== ==========================================================================
203-
``autoloader`` PSR-4 autoloading configuration. Safe to persist as class maps don't change.
204-
``locator`` File locator for finding framework files. Caches file paths for performance.
205-
``exceptions`` Exception handler. Stateless, safe to reuse.
206-
``commands`` CLI commands registry. Only used during worker startup.
207-
``codeigniter`` Main application instance. Orchestrates the request/response cycle.
208-
``superglobals`` Superglobals wrapper. Properly isolated per request internally.
209-
``routes`` Router configuration. Route definitions don't change between requests.
210-
``cache`` Cache service. Maintains connections to cache backends (Redis, Memcached).
211-
===================== ==========================================================================
200+
================ ==========================================================================
201+
Service Purpose
202+
================ ==========================================================================
203+
``autoloader`` PSR-4 autoloading configuration. Safe to persist as class maps don't change.
204+
``locator`` File locator for finding framework files. Caches file paths for performance.
205+
``exceptions`` Exception handler. Stateless, safe to reuse.
206+
``commands`` CLI commands registry. Only used during worker startup.
207+
``codeigniter`` Main application instance. Orchestrates the request/response cycle.
208+
``superglobals`` Superglobals wrapper. Properly isolated per request internally.
209+
``routes`` Router configuration. Route definitions don't change between requests.
210+
``cache`` Cache service. Maintains connections to cache backends (Redis, Memcached).
211+
================ ==========================================================================
212212

213213
.. warning:: Adding services to ``$persistentServices`` without understanding their
214214
state management can cause data leakage between requests. Only persist services
@@ -304,4 +304,4 @@ Database connections are automatically managed:
304304
- Connections persist across requests for performance
305305
- Connections are validated at the start of each request
306306
- Failed connections are automatically re-established
307-
- Uncommitted transactions trigger a warning and reconnection to ensure clean state
307+
- Uncommitted transactions are automatically rolled back with a warning logged

0 commit comments

Comments
 (0)