Skip to content

Commit 327dc36

Browse files
committed
wip
1 parent d22f365 commit 327dc36

File tree

15 files changed

+236
-188
lines changed

15 files changed

+236
-188
lines changed

app/Config/WorkerMode.php

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class WorkerMode
2626
* - `commands`: CLI commands registry
2727
* - `codeigniter`: Main application instance
2828
* - `superglobals`: Superglobals wrapper
29+
* - `routes`: Router configuration
2930
*
3031
* @var list<string>
3132
*/
@@ -38,36 +39,10 @@ class WorkerMode
3839
'commands',
3940
'codeigniter',
4041
'superglobals',
42+
'routes',
43+
'cache',
4144
];
4245

43-
/**
44-
* Database connection strategy
45-
*
46-
* Determines how database connections are handled between requests:
47-
*
48-
* - 'keep-alive' (recommended):
49-
* Keeps connections alive across requests for best performance
50-
* - 'disconnect':
51-
* Closes all connections after each request
52-
*
53-
* @var 'disconnect'|'keep-alive'
54-
*/
55-
public string $databaseStrategy = 'keep-alive';
56-
57-
/**
58-
* Cache handler strategy
59-
*
60-
* Determines how cache handlers are managed between requests:
61-
*
62-
* - 'keep-alive' (recommended):
63-
* Keeps cache handler alive across requests for best performance
64-
* - 'disconnect':
65-
* Closes the handler after each request
66-
*
67-
* @var 'disconnect'|'keep-alive'
68-
*/
69-
public string $cacheStrategy = 'keep-alive';
70-
7146
/**
7247
* Reset Factories
7348
*

system/Cache/Handlers/RedisHandler.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ public function ping(): bool
229229
try {
230230
$result = $this->redis->ping();
231231

232-
return in_array($result, [true, '+PONG', 'PONG'], true);
232+
return in_array($result, [true, '+PONG'], true);
233233
} catch (RedisException) {
234234
return false;
235235
}

system/Commands/Worker/Views/Caddyfile.tpl

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@
3333
3434
# Route all PHP requests through the worker
3535
php_server {
36-
# Use frankenphp-worker.php as the entry point
37-
index frankenphp-worker.php
3836
# Route all requests through the worker
3937
try_files {path} frankenphp-worker.php
4038
}

system/Commands/Worker/Views/frankenphp-worker.php.tpl

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,11 @@ $workerConfig = config('WorkerMode');
6969
*/
7070

7171
$handler = function () use ($app, $workerConfig) {
72-
// Validate database connections
73-
DatabaseConfig::validateForWorkerMode($workerConfig);
72+
// Validate database connections before handling request
73+
DatabaseConfig::validateForWorkerMode();
74+
75+
// Validate cache connection before handling request
76+
Services::validateForWorkerMode();
7477
7578
// Reset request-specific state
7679
$app->resetForWorkerMode();
@@ -105,8 +108,8 @@ while (frankenphp_handle_request($handler)) {
105108
Services::session()->close();
106109
}
107110

108-
// Reset database connections based on strategy (keep-alive or disconnect)
109-
DatabaseConfig::resetForWorkerMode($workerConfig);
111+
// Cleanup connections with uncommitted transactions
112+
DatabaseConfig::cleanupForWorkerMode();
110113

111114
// Reset model/entity instances (if enabled)
112115
if ($workerConfig->resetFactories) {
@@ -117,7 +120,7 @@ while (frankenphp_handle_request($handler)) {
117120
Services::resetForWorkerMode($workerConfig);
118121

119122
// Reset performance
120-
Events::resetForWorkerMode();
123+
Events::cleanupForWorkerMode();
121124

122125
// Reset persistent services that accumulate state
123126
if (Services::has('timer')) {

system/Commands/Worker/WorkerInstall.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
* For the full copyright and license information, please view
1111
* the LICENSE file that was distributed with this source code.
1212
*/
13+
1314
namespace CodeIgniter\Commands\Worker;
1415

1516
use CodeIgniter\CLI\BaseCommand;

system/Commands/Worker/WorkerUninstall.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
* For the full copyright and license information, please view
1111
* the LICENSE file that was distributed with this source code.
1212
*/
13+
1314
namespace CodeIgniter\Commands\Worker;
1415

1516
use CodeIgniter\CLI\BaseCommand;

system/Config/BaseService.php

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -381,9 +381,9 @@ public static function reset(bool $initAutoloader = true)
381381
* This should be called at the beginning of each request in worker mode,
382382
* before the application runs.
383383
*/
384-
public static function validateForWorkerMode(WorkerMode $config): void
384+
public static function validateForWorkerMode(): void
385385
{
386-
if ($config->cacheStrategy !== 'keep-alive' || ! isset(static::$instances['cache'])) {
386+
if (! isset(static::$instances['cache'])) {
387387
return;
388388
}
389389

@@ -412,15 +412,6 @@ public static function resetForWorkerMode(WorkerMode $config): void
412412
$persistentInstances = [];
413413

414414
foreach (static::$instances as $serviceName => $service) {
415-
if ($serviceName === 'cache') {
416-
if ($config->cacheStrategy === 'keep-alive') {
417-
// Persist cache instance in keep-alive mode
418-
$persistentInstances[$serviceName] = $service;
419-
}
420-
421-
continue;
422-
}
423-
424415
// Persist services in the persistent list
425416
if (in_array($serviceName, $config->persistentServices, true)) {
426417
$persistentInstances[$serviceName] = $service;

system/Database/Config.php

Lines changed: 13 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -161,9 +161,9 @@ protected static function ensureFactory()
161161
* This should be called at the beginning of each request in worker mode,
162162
* before the application runs.
163163
*/
164-
public static function validateForWorkerMode(WorkerMode $config): void
164+
public static function validateForWorkerMode(): void
165165
{
166-
if ($config->databaseStrategy !== 'keep-alive') {
166+
if (static::$instances === []) {
167167
return;
168168
}
169169

@@ -175,44 +175,24 @@ public static function validateForWorkerMode(WorkerMode $config): void
175175
}
176176

177177
/**
178-
* Reset database connections for worker mode.
178+
* Cleanup database connections for worker mode.
179179
*
180-
* This method handles connection state management between requests
181-
* in long-running worker processes.
180+
* If any uncommitted transactions are found, the connection
181+
* is closed and reconnected to ensure a clean state for the next request.
182+
*
183+
* Uncommitted transactions at this point indicate a bug in the
184+
* application code (transactions should be completed before request ends).
182185
*
183186
* Called at the END of each request to clean up state.
184187
*/
185-
public static function resetForWorkerMode(WorkerMode $config): void
188+
public static function cleanupForWorkerMode(): void
186189
{
187190
foreach (static::$instances as $group => $connection) {
188-
switch ($config->databaseStrategy) {
189-
case 'disconnect':
190-
$connection->close();
191-
break;
192-
193-
case 'keep-alive':
194-
$maxAttempts = 10; // Prevent infinite loop
195-
$attempts = 0;
196-
197-
while ($connection->transDepth > 0 && $attempts < $maxAttempts) {
198-
if (! $connection->transRollback()) {
199-
log_message('error', "Database transaction rollback failed for group: {$group}");
200-
break;
201-
}
202-
$attempts++;
203-
}
204-
205-
if ($connection->transDepth > 0) {
206-
log_message('warning', "Database connection has uncommitted transactions after cleanup: {$group}");
207-
}
208-
break;
191+
if ($connection->transDepth > 0) {
192+
log_message('error', "Uncommitted transaction detected in database group '{$group}'. Transactions must be completed before request ends. Reconnecting to ensure clean state.");
193+
$connection->close();
194+
$connection->initialize();
209195
}
210196
}
211-
212-
// If using the disconnect strategy, clear the instances array
213-
if ($config->databaseStrategy === 'disconnect') {
214-
static::$instances = [];
215-
static::$factory = null;
216-
}
217197
}
218198
}

system/Events/Events.php

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -286,15 +286,11 @@ public static function getPerformanceLogs()
286286
}
287287

288288
/**
289-
* Reset events for worker mode.
289+
* Cleanup performance log for worker mode.
290290
*
291-
* Uses WorkerMode config to determine behavior.
292-
* Clears performance logs and re-initializes event listeners from config files.
293-
*
294-
* Note: This clears dynamically registered listeners. If your application
295-
* registers listeners at runtime, they will need to be re-registered for each request.
291+
* Called at the END of each request to clean up state.
296292
*/
297-
public static function resetForWorkerMode(): void
293+
public static function cleanupForWorkerMode(): void
298294
{
299295
static::$performanceLog = [];
300296
}

system/Session/Handlers/MemcachedHandler.php

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
use CodeIgniter\I18n\Time;
1717
use CodeIgniter\Session\Exceptions\SessionException;
18+
use CodeIgniter\Session\PersistsConnection;
1819
use Config\Session as SessionConfig;
1920
use Memcached;
2021
use ReturnTypeWillChange;
@@ -24,6 +25,8 @@
2425
*/
2526
class MemcachedHandler extends BaseHandler
2627
{
28+
use PersistsConnection;
29+
2730
/**
2831
* Memcached instance.
2932
*
@@ -83,6 +86,23 @@ public function __construct(SessionConfig $config, string $ipAddress)
8386
*/
8487
public function open($path, $name): bool
8588
{
89+
if ($this->hasPersistentConnection()) {
90+
$memcached = $this->getPersistentConnection();
91+
$version = $memcached->getVersion();
92+
93+
if (is_array($version)) {
94+
foreach ($version as $serverVersion) {
95+
if ($serverVersion !== false) {
96+
$this->memcached = $memcached;
97+
98+
return true;
99+
}
100+
}
101+
}
102+
103+
$this->setPersistentConnection(null);
104+
}
105+
86106
$this->memcached = new Memcached();
87107
$this->memcached->setOption(Memcached::OPT_BINARY_PROTOCOL, true); // required for touch() usage
88108

@@ -131,6 +151,8 @@ public function open($path, $name): bool
131151
return false;
132152
}
133153

154+
$this->setPersistentConnection($this->memcached);
155+
134156
return true;
135157
}
136158

@@ -210,12 +232,6 @@ public function close(): bool
210232
$this->memcached->delete($this->lockKey);
211233
}
212234

213-
if (! $this->memcached->quit()) {
214-
return false;
215-
}
216-
217-
$this->memcached = null;
218-
219235
return true;
220236
}
221237

0 commit comments

Comments
 (0)