Skip to content

Commit c171a6e

Browse files
Merge remote-tracking branch 'origin/develop' into FOUR-33159
2 parents 2d4f89b + 5a1a1cb commit c171a6e

248 files changed

Lines changed: 10156 additions & 47427 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.example

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ TELESCOPE_ENABLED=false
3333
REDIS_CLIENT=predis
3434
REDIS_PREFIX=
3535
HORIZON_PREFIX=horizon:
36+
PM4_HORIZON_SUPERVISOR_BPMN_MAX_JOBS=10
37+
PM4_HORIZON_SUPERVISOR_1_MAX_JOBS=100
3638
DOCKER_SHARED_MEMORY=256m
3739
PROXIES=*
3840
LOGOUT_OTHER_DEVICES=false
@@ -67,7 +69,7 @@ SCRIPT_MICROSERVICE_PUSHER_PORT=
6769

6870
# FrankenPHP workers ignore CLI php.ini. Use Caddyfile + --caddyfile=Caddyfile.
6971
# OCTANE_MEMORY_LIMIT=512M
70-
# OCTANE_MAX_EXECUTION_TIME=90
72+
# OCTANE_MAX_EXECUTION_TIME=120
7173
# OCTANE_POST_MAX_SIZE=200M
7274
# OCTANE_UPLOAD_MAX_FILESIZE=200M
7375
# OCTANE_MAX_INPUT_VARS=9000

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ yarn-error.log
2020
/public/img
2121
/public/fonts
2222
/public/mix-manifest.json
23+
/public/build
24+
/public/hot
2325
/public/stats.json
2426
tests/js/coverage
2527
tests/coverage-report

Caddyfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
frankenphp {
55
# FrankenPHP workers ignore CLI php.ini / PHPRC. Set PHP limits here.
6-
php_ini memory_limit {$OCTANE_MEMORY_LIMIT:3072M}
7-
php_ini max_execution_time {$OCTANE_MAX_EXECUTION_TIME:90}
6+
php_ini memory_limit {$OCTANE_MEMORY_LIMIT:512M}
7+
php_ini max_execution_time {$OCTANE_MAX_EXECUTION_TIME:120}
88
php_ini post_max_size {$OCTANE_POST_MAX_SIZE:200M}
99
php_ini upload_max_filesize {$OCTANE_UPLOAD_MAX_FILESIZE:200M}
1010
php_ini max_input_vars {$OCTANE_MAX_INPUT_VARS:9000}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace ProcessMaker\Console\Commands;
6+
7+
use Illuminate\Console\Command;
8+
use ProcessMaker\Health\OctaneHeartbeat;
9+
use ProcessMaker\Health\OctaneHeartbeatOutput;
10+
11+
class OctaneHeartbeatCommand extends Command
12+
{
13+
protected $signature = 'octane:heartbeat
14+
{--ready : Verify database (and Redis when required) before reporting healthy}
15+
{--php-ini : Show CLI PHP vs FrankenPHP worker php.ini comparison}';
16+
17+
protected $description = 'Fast Octane liveness/readiness probe and worker php.ini inspection';
18+
19+
public function handle(OctaneHeartbeat $heartbeat): int
20+
{
21+
$showPhpIni = (bool) $this->option('php-ini');
22+
$result = $heartbeat->probe((bool) $this->option('ready'), $showPhpIni);
23+
24+
(new OctaneHeartbeatOutput($this))->render($result, $showPhpIni);
25+
26+
return $result->exitCode($showPhpIni);
27+
}
28+
}
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace ProcessMaker\Health;
6+
7+
class CaddyPhpIni
8+
{
9+
/** @var array<string, string> */
10+
private const ENV_TO_INI = [
11+
'OCTANE_MEMORY_LIMIT' => 'memory_limit',
12+
'OCTANE_MAX_EXECUTION_TIME' => 'max_execution_time',
13+
'OCTANE_POST_MAX_SIZE' => 'post_max_size',
14+
'OCTANE_UPLOAD_MAX_FILESIZE' => 'upload_max_filesize',
15+
'OCTANE_MAX_INPUT_VARS' => 'max_input_vars',
16+
'OCTANE_MAX_INPUT_TIME' => 'max_input_time',
17+
];
18+
19+
public static function caddyfilePath(): string
20+
{
21+
return base_path('Caddyfile');
22+
}
23+
24+
/**
25+
* Values from config/octane.php → caddy.env (what the Caddyfile should apply).
26+
*
27+
* @return array<string, string>
28+
*/
29+
public static function configured(): array
30+
{
31+
/** @var array<string, mixed> $env */
32+
$env = config('octane.caddy.env', []);
33+
$php = [];
34+
35+
foreach (self::ENV_TO_INI as $envKey => $iniKey) {
36+
if (isset($env[$envKey]) && $env[$envKey] !== '') {
37+
$php[$iniKey] = (string) $env[$envKey];
38+
}
39+
}
40+
41+
return $php;
42+
}
43+
44+
/**
45+
* @return array<string, string>
46+
*/
47+
public static function fromWorker(): array
48+
{
49+
$php = [];
50+
51+
foreach (self::configured() as $directive => $_expected) {
52+
$actual = ini_get($directive);
53+
$php[$directive] = $actual !== false && $actual !== '' ? (string) $actual : '';
54+
}
55+
56+
return $php;
57+
}
58+
59+
/**
60+
* @param array<string, string> $worker
61+
*
62+
* @return array<int, array{directive: string, expected: string, actual: string, matches: bool}>
63+
*/
64+
public static function verify(array $worker): array
65+
{
66+
$results = [];
67+
68+
foreach (self::configured() as $directive => $expected) {
69+
$actual = $worker[$directive] ?? '';
70+
$results[] = [
71+
'directive' => $directive,
72+
'expected' => $expected,
73+
'actual' => $actual !== '' ? $actual : '(missing)',
74+
'matches' => self::valuesMatch($directive, $expected, $actual),
75+
];
76+
}
77+
78+
return $results;
79+
}
80+
81+
/**
82+
* @param array<string, string> $worker
83+
*/
84+
public static function allMatch(array $worker): bool
85+
{
86+
foreach (self::verify($worker) as $entry) {
87+
if (!$entry['matches']) {
88+
return false;
89+
}
90+
}
91+
92+
return $worker !== [];
93+
}
94+
95+
public static function directiveMatches(string $directive, string $expected, string $actual): bool
96+
{
97+
return self::valuesMatch($directive, $expected, $actual);
98+
}
99+
100+
public static function directivesEquivalent(string $directive, string $left, string $right): bool
101+
{
102+
if ($left === '' && $right === '') {
103+
return true;
104+
}
105+
106+
if ($left === '' || $right === '') {
107+
return false;
108+
}
109+
110+
return self::normalizeValue($directive, $left) === self::normalizeValue($directive, $right);
111+
}
112+
113+
private static function valuesMatch(string $directive, string $expected, string $actual): bool
114+
{
115+
if ($actual === '') {
116+
return false;
117+
}
118+
119+
$normalizedExpected = self::normalizeValue($directive, $expected);
120+
$normalizedActual = self::normalizeValue($directive, $actual);
121+
122+
if ($normalizedExpected === $normalizedActual) {
123+
return true;
124+
}
125+
126+
if ($directive === 'max_execution_time' && $normalizedActual === '0' && (int) $normalizedExpected > 0) {
127+
return true;
128+
}
129+
130+
if ($directive === 'max_input_time' && $normalizedActual === '-1' && (int) $normalizedExpected > 0) {
131+
return true;
132+
}
133+
134+
return false;
135+
}
136+
137+
private static function normalizeValue(string $directive, string $value): string
138+
{
139+
$value = trim(strtolower($value));
140+
141+
if (is_numeric($value)) {
142+
return (string) (int) (float) $value;
143+
}
144+
145+
return $value;
146+
}
147+
148+
/**
149+
* @return array{0: ?array<string, string>, 1: ?string, 2: ?string, 3: ?array<string, bool>}
150+
*/
151+
public static function workerSnapshot(bool $includePhpIni): array
152+
{
153+
if (!$includePhpIni) {
154+
return [null, null, null, null];
155+
}
156+
157+
return [
158+
self::fromWorker(),
159+
self::caddyfilePath(),
160+
PHP_VERSION,
161+
CliPhpIni::extensionsLoaded(),
162+
];
163+
}
164+
}

0 commit comments

Comments
 (0)