Skip to content

Commit a3aa9b3

Browse files
authored
Merge pull request #8979 from ProcessMaker/epic/FOUR-30918-octane
FOUR-30918: [PHASE1] With Octane
2 parents 0e0a60b + 741db29 commit a3aa9b3

11 files changed

Lines changed: 583 additions & 11 deletions

File tree

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,7 @@ devhub/pm-font/dist
5151
test-db-snapshot.db
5252
snapshot_*.db
5353
storage/transitions
54-
.envrc
54+
.envrc
55+
**/caddy
56+
frankenphp
57+
frankenphp-worker.php

ProcessMaker/Http/Middleware/ServerTimingMiddleware.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ public function handle(Request $request, Closure $next): Response
2828
return $next($request);
2929
}
3030

31+
ProcessMakerServiceProvider::beginRequestTiming();
32+
3133
// Start time for controller execution
3234
$startController = microtime(true);
3335

ProcessMaker/Listeners/HandleRedirectListener.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,17 @@ protected function setRedirectTo(ProcessRequest $processRequest, string $method,
2020
self::$redirectionParams = $params;
2121
}
2222

23+
/**
24+
* Reset the static state for Octane compatibility.
25+
* This prevents data leaks between requests in long-running workers.
26+
*/
27+
public static function reset(): void
28+
{
29+
self::$processRequest = null;
30+
self::$redirectionMethod = '';
31+
self::$redirectionParams = [];
32+
}
33+
2334
public static function sendRedirectToEvent()
2435
{
2536
$method = self::$redirectionMethod;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace ProcessMaker\Octane;
6+
7+
use ProcessMaker\Listeners\HandleRedirectListener;
8+
use ProcessMaker\Providers\ProcessMakerServiceProvider;
9+
10+
final class ResetRequestState
11+
{
12+
public function handle(): void
13+
{
14+
ProcessMakerServiceProvider::beginRequestTiming();
15+
HandleRedirectListener::reset();
16+
}
17+
}

ProcessMaker/Providers/ProcessMakerServiceProvider.php

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@
1717
use Illuminate\Support\Facades\Artisan;
1818
use Illuminate\Support\Facades\Context;
1919
use Illuminate\Support\Facades\DB;
20+
use Illuminate\Support\Facades\Event;
2021
use Illuminate\Support\Facades\Log;
2122
use Illuminate\Support\Facades\Route;
2223
use Illuminate\Support\Facades\URL;
2324
use Laravel\Horizon\Horizon;
2425
use Laravel\Horizon\SystemProcessCounter;
2526
use Laravel\Horizon\WorkerCommandString;
27+
use Laravel\Octane\Events\RequestTerminated;
2628
use Laravel\Passport\Client as PassportClient;
2729
use Lavary\Menu\Menu;
2830
use OpenApi\Analysers\AttributeAnnotationFactory;
@@ -49,6 +51,7 @@
4951
use ProcessMaker\Models;
5052
use ProcessMaker\Multitenancy\Tenant;
5153
use ProcessMaker\Observers;
54+
use ProcessMaker\Octane\ResetRequestState;
5255
use ProcessMaker\PolicyExtension;
5356
use ProcessMaker\Providers\PermissionServiceProvider;
5457
use ProcessMaker\Repositories\SettingsConfigRepository;
@@ -107,6 +110,9 @@ public function boot(): void
107110

108111
$this->checkConfigCache();
109112

113+
// Register Octane listeners if Octane is enabled
114+
$this->registerOctaneListeners();
115+
110116
// Hook after service providers boot
111117
self::$bootTime = (microtime(true) - self::$bootStart) * 1000; // Convert to milliseconds
112118
}
@@ -260,7 +266,7 @@ protected static function registerEvents(): void
260266
{
261267
// Listen to the events for our core screen
262268
// types and add our javascript
263-
Facades\Event::listen(ScreenBuilderStarting::class, function ($event) {
269+
Event::listen(ScreenBuilderStarting::class, function ($event) {
264270
// Add any extensions to form builder
265271
// and renderer from packages
266272
$event->manager->addPackageScripts($event->type);
@@ -279,7 +285,7 @@ protected static function registerEvents(): void
279285
});
280286

281287
// Log Notifications
282-
Facades\Event::listen(NotificationSent::class, function ($event) {
288+
Event::listen(NotificationSent::class, function ($event) {
283289
$id = $event->notifiable->id;
284290
$notifiable = get_class($event->notifiable);
285291
$notification = get_class($event->notification);
@@ -288,24 +294,24 @@ protected static function registerEvents(): void
288294
});
289295

290296
// Log Broadcasts (messages sent to laravel-echo-server and redis)
291-
Facades\Event::listen(BroadcastNotificationCreated::class, function ($event) {
297+
Event::listen(BroadcastNotificationCreated::class, function ($event) {
292298
$channels = implode(', ', $event->broadcastOn());
293299

294300
Log::debug('Broadcasting Notification ' . $event->broadcastType() . 'on channel(s) ' . $channels);
295301
});
296302

297303
// Fire job when task is assigned to a user
298-
Facades\Event::listen(ActivityAssigned::class, function ($event) {
304+
Event::listen(ActivityAssigned::class, function ($event) {
299305
$task_id = $event->getProcessRequestToken()->id;
300306
// Dispatch the SmartInbox job with the processRequestToken as parameter
301307
SmartInbox::dispatch($task_id);
302308
});
303309

304-
Facades\Event::listen(MadeTenantCurrentEvent::class, function ($event) {
310+
Event::listen(MadeTenantCurrentEvent::class, function ($event) {
305311
event(new TenantResolved($event->tenant));
306312
});
307313

308-
Facades\Event::listen(TenantNotFoundForRequestEvent::class, function ($event) {
314+
Event::listen(TenantNotFoundForRequestEvent::class, function ($event) {
309315
if (config('app.multitenancy') === false || self::actuallyRunningInConsole()) {
310316
// This is expected if multitenancy is disabled.
311317
// We also need to check if we are running in a console command because
@@ -330,7 +336,7 @@ protected static function registerEvents(): void
330336
}
331337
});
332338

333-
Facades\Event::listen(function (CommandStarting $event) {
339+
Event::listen(function (CommandStarting $event) {
334340
if ($event->command === 'l5-swagger:generate') {
335341
// Set the analyser to use the legacy DocBlockAnnotationFactory. This must
336342
// be set here because this config value is not serializable and cannot be cached.
@@ -511,6 +517,14 @@ public static function getBootTime(): ?float
511517
return self::$bootTime;
512518
}
513519

520+
/**
521+
* Reset per-request query timing metrics.
522+
*/
523+
public static function beginRequestTiming(): void
524+
{
525+
self::$queryTime = 0;
526+
}
527+
514528
/**
515529
* Get the query time for the request.
516530
*
@@ -568,6 +582,23 @@ public static function getPackageBootTiming(): array
568582
return self::$packageBootTiming;
569583
}
570584

585+
/**
586+
* Reset per-request static state between Octane requests.
587+
*
588+
* Octane workers stay alive across requests, so static properties must be
589+
* cleared to avoid leaking data from one request into the next. Singletons
590+
* holding mutable state are handled by the 'flush' list in config/octane.php,
591+
* which Octane applies on its own.
592+
*/
593+
private function registerOctaneListeners(): void
594+
{
595+
if (!class_exists(RequestTerminated::class)) {
596+
return;
597+
}
598+
599+
Event::listen(RequestTerminated::class, ResetRequestState::class);
600+
}
601+
571602
/**
572603
* Find the tenant based on the environment variable
573604
*/

ProcessMaker/Repositories/SettingsConfigRepository.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public function get($key, $default = null)
3939
if ($key === 'session.lifetime') {
4040
$settingValue = $this->getFromSettings($key);
4141

42-
return $settingValue ?? $default;
42+
return $settingValue ?: Arr::get($this->items, $key) ?: $default ?: 120;
4343
}
4444

4545
if (Arr::has($this->items, $key)) {

composer.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@
2525
"guzzlehttp/psr7": "^2.12.3",
2626
"igaster/laravel-theme": "^2.0",
2727
"jenssegers/agent": "^2.6",
28-
"laravel/framework": "^13.13",
29-
"laravel/horizon": "^5.47",
28+
"laravel/framework": "^13.0",
29+
"laravel/horizon": "^5.45",
30+
"laravel/octane": "^2.17",
3031
"laravel/pail": "^1.2",
3132
"laravel/passport": "^13.7",
3233
"laravel/scout": "^11.1",

composer.lock

Lines changed: 177 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)