Skip to content

Commit be4ab56

Browse files
authored
Merge pull request #9050 from ProcessMaker/FOUR-33043
feat(FOUR-33043): Define a maxJobs and memory limit for BPMN and default
2 parents f3c8204 + 0f19b1f commit be4ab56

3 files changed

Lines changed: 123 additions & 0 deletions

File tree

.env.example

Lines changed: 2 additions & 0 deletions
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

config/horizon.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@
152152
'minProcesses' => env('PM4_HORIZON_SUPERVISOR_BPMN_MIN_PROCESSES', 1),
153153
'maxProcesses' => env('PM4_HORIZON_SUPERVISOR_BPMN_MAX_PROCESSES', 1),
154154
'memory' => env('PM4_HORIZON_WORKER_MEMORY_LIMIT', 512),
155+
'maxJobs' => (int) env('PM4_HORIZON_SUPERVISOR_BPMN_MAX_JOBS', 10),
155156
],
156157
'supervisor-1' => [
157158
'connection' => 'redis',
@@ -162,6 +163,7 @@
162163
'minProcesses' => env('PM4_HORIZON_SUPERVISOR_1_MIN_PROCESSES', 1),
163164
'maxProcesses' => env('PM4_HORIZON_SUPERVISOR_1_MAX_PROCESSES', 1),
164165
'memory' => env('PM4_HORIZON_WORKER_MEMORY_LIMIT', 512),
166+
'maxJobs' => (int) env('PM4_HORIZON_SUPERVISOR_1_MAX_JOBS', 100),
165167
],
166168
],
167169

@@ -176,6 +178,7 @@
176178
'minProcesses' => env('PM4_HORIZON_SUPERVISOR_BPMN_MIN_PROCESSES', 1),
177179
'maxProcesses' => env('PM4_HORIZON_SUPERVISOR_BPMN_MAX_PROCESSES', 1),
178180
'memory' => env('PM4_HORIZON_WORKER_MEMORY_LIMIT', 512),
181+
'maxJobs' => (int) env('PM4_HORIZON_SUPERVISOR_BPMN_MAX_JOBS', 10),
179182
],
180183
'supervisor-1' => [
181184
'connection' => 'redis',
@@ -186,6 +189,7 @@
186189
'minProcesses' => env('PM4_HORIZON_SUPERVISOR_1_MIN_PROCESSES', 1),
187190
'maxProcesses' => env('PM4_HORIZON_SUPERVISOR_1_MAX_PROCESSES', 1),
188191
'memory' => env('PM4_HORIZON_WORKER_MEMORY_LIMIT', 512),
192+
'maxJobs' => (int) env('PM4_HORIZON_SUPERVISOR_1_MAX_JOBS', 100),
189193
],
190194
],
191195

@@ -200,6 +204,7 @@
200204
'minProcesses' => env('PM4_HORIZON_SUPERVISOR_BPMN_MIN_PROCESSES', 1),
201205
'maxProcesses' => env('PM4_HORIZON_SUPERVISOR_BPMN_MAX_PROCESSES', 1),
202206
'memory' => env('PM4_HORIZON_WORKER_MEMORY_LIMIT', 512),
207+
'maxJobs' => (int) env('PM4_HORIZON_SUPERVISOR_BPMN_MAX_JOBS', 10),
203208
],
204209
'supervisor-1' => [
205210
'connection' => 'redis',
@@ -210,6 +215,7 @@
210215
'minProcesses' => env('PM4_HORIZON_SUPERVISOR_1_MIN_PROCESSES', 1),
211216
'maxProcesses' => env('PM4_HORIZON_SUPERVISOR_1_MAX_PROCESSES', 1),
212217
'memory' => env('PM4_HORIZON_WORKER_MEMORY_LIMIT', 512),
218+
'maxJobs' => (int) env('PM4_HORIZON_SUPERVISOR_1_MAX_JOBS', 100),
213219
],
214220
],
215221
],
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Unit\Config;
6+
7+
use Illuminate\Support\Facades\Artisan;
8+
use Illuminate\Support\Facades\Config;
9+
use Illuminate\Support\Facades\DB;
10+
use ProcessMaker\Jobs\TestStatusJob;
11+
use Tests\TestCase;
12+
13+
class HorizonConfigTest extends TestCase
14+
{
15+
private const ENVIRONMENTS = ['production', 'local', 'staging'];
16+
17+
private const SUPERVISORS = ['supervisor-bpmn', 'supervisor-1'];
18+
19+
protected function tearDown(): void
20+
{
21+
$this->unsetMaxJobsEnvironmentVariables();
22+
23+
parent::tearDown();
24+
}
25+
26+
public function testMaxJobsUsesRecommendedDefaultsForAllSupervisors(): void
27+
{
28+
$this->unsetMaxJobsEnvironmentVariables();
29+
30+
$configuration = include base_path('config/horizon.php'); // NOSONAR: load fresh config after changing environment variables.
31+
32+
foreach (self::ENVIRONMENTS as $environment) {
33+
$this->assertSame(10, $configuration['environments'][$environment]['supervisor-bpmn']['maxJobs']);
34+
$this->assertSame(100, $configuration['environments'][$environment]['supervisor-1']['maxJobs']);
35+
}
36+
}
37+
38+
public function testMaxJobsCanBeDisabledWithZero(): void
39+
{
40+
putenv('PM4_HORIZON_SUPERVISOR_BPMN_MAX_JOBS=0');
41+
putenv('PM4_HORIZON_SUPERVISOR_1_MAX_JOBS=0');
42+
43+
$configuration = include base_path('config/horizon.php'); // NOSONAR: load fresh config after changing environment variables.
44+
45+
foreach (self::ENVIRONMENTS as $environment) {
46+
foreach (self::SUPERVISORS as $supervisor) {
47+
$this->assertSame(
48+
0,
49+
$configuration['environments'][$environment][$supervisor]['maxJobs'],
50+
"{$environment}.{$supervisor} should allow maxJobs to be disabled"
51+
);
52+
}
53+
}
54+
}
55+
56+
public function testMaxJobsCanBeConfiguredAsTwoForBpmnAndDefaultSupervisors(): void
57+
{
58+
putenv('PM4_HORIZON_SUPERVISOR_BPMN_MAX_JOBS=2');
59+
putenv('PM4_HORIZON_SUPERVISOR_1_MAX_JOBS=2');
60+
61+
$configuration = include base_path('config/horizon.php'); // NOSONAR: load fresh config after changing environment variables.
62+
63+
foreach (self::ENVIRONMENTS as $environment) {
64+
foreach (self::SUPERVISORS as $supervisor) {
65+
$this->assertSame(
66+
2,
67+
$configuration['environments'][$environment][$supervisor]['maxJobs'],
68+
"{$environment}.{$supervisor} should use the configured maxJobs value"
69+
);
70+
}
71+
}
72+
}
73+
74+
public function testFiveJobsContinueProcessingAcrossWorkersWithMaxJobsTwo(): void
75+
{
76+
$queue = 'maxjobs-test-' . bin2hex(random_bytes(4));
77+
$jobPrefix = 'maxjobs-test-' . bin2hex(random_bytes(4));
78+
$maxJobs = 2;
79+
80+
Config::set('queue.default', 'redis');
81+
Config::set('horizon.environments.local.supervisor-bpmn.maxJobs', $maxJobs);
82+
83+
foreach (range(1, 5) as $number) {
84+
TestStatusJob::dispatch(
85+
"{$jobPrefix}-{$number}",
86+
'Horizon maxJobs integration test'
87+
)->onQueue($queue);
88+
}
89+
90+
foreach ([2, 4, 5] as $expectedCount) {
91+
$exitCode = Artisan::call('queue:work', [
92+
'connection' => 'redis',
93+
'--queue' => $queue,
94+
'--max-jobs' => $maxJobs,
95+
'--stop-when-empty' => true,
96+
'--tries' => 1,
97+
'--memory' => 1024,
98+
]);
99+
100+
$this->assertSame(0, $exitCode);
101+
$this->assertSame(
102+
$expectedCount,
103+
DB::table('test_status')
104+
->where('name', 'like', "{$jobPrefix}-%")
105+
->count()
106+
);
107+
}
108+
}
109+
110+
private function unsetMaxJobsEnvironmentVariables(): void
111+
{
112+
putenv('PM4_HORIZON_SUPERVISOR_BPMN_MAX_JOBS');
113+
putenv('PM4_HORIZON_SUPERVISOR_1_MAX_JOBS');
114+
}
115+
}

0 commit comments

Comments
 (0)