Skip to content

Commit 0f21fab

Browse files
committed
Spread self-hosting update and telemetry requests over the day
1 parent df00200 commit 0f21fab

File tree

3 files changed

+136
-8
lines changed

3 files changed

+136
-8
lines changed

app/Console/Kernel.php

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,27 @@ protected function schedule(Schedule $schedule): void
2222
->when(fn (): bool => config('scheduling.tasks.auth_send_mails_expiring_api_tokens'))
2323
->everyTenMinutes();
2424

25-
$schedule->command('self-host:check-for-update')
26-
->when(fn (): bool => config('scheduling.tasks.self_hosting_check_for_update'))
27-
->twiceDaily();
28-
29-
$schedule->command('self-host:telemetry')
30-
->when(fn (): bool => config('scheduling.tasks.self_hosting_telemetry'))
31-
->twiceDaily();
25+
if (config('scheduling.tasks.self_hosting_check_for_update') || config('scheduling.tasks.self_hosting_telemetry')) {
26+
// Convert string to a stable integer for seeding
27+
/** @var int $seed Take the first 8 hex chars → 32-bit int */
28+
$seed = hexdec(substr(hash('md5', config('app.key')), 0, 8));
29+
$seed = abs($seed); // Ensure it's positive
30+
mt_srand($seed);
31+
$firstHour = mt_rand(0, 23);
32+
$secondHour = ($firstHour + 12) % 24;
33+
$minuteOffset = mt_rand(0, 59);
34+
mt_srand(null); // Reset the random number generator
35+
36+
if (config('scheduling.tasks.self_hosting_check_for_update')) {
37+
$schedule->command('self-host:check-for-update')
38+
->twiceDailyAt($firstHour, $secondHour, $minuteOffset);
39+
}
40+
41+
if (config('scheduling.tasks.self_hosting_telemetry')) {
42+
$schedule->command('self-host:telemetry')
43+
->twiceDailyAt($firstHour, $secondHour, $minuteOffset);
44+
}
45+
}
3246

3347
$schedule->command('self-host:database-consistency')
3448
->when(fn (): bool => config('scheduling.tasks.self_hosting_database_consistency'))

app/Http/Middleware/HandleInertiaRequests.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public function share(Request $request): array
4242
$hasBilling = Module::has('Billing') && Module::isEnabled('Billing');
4343
$hasInvoicing = Module::has('Invoicing') && Module::isEnabled('Invoicing');
4444
$hasServices = Module::has('Services') && Module::isEnabled('Services');
45-
45+
4646
/** @var BillingContract $billing */
4747
$billing = app(BillingContract::class);
4848

tests/Unit/Console/KernelTest.php

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Unit\Console;
6+
7+
use App\Console\Kernel;
8+
use PHPUnit\Framework\Attributes\CoversClass;
9+
use Tests\TestCase;
10+
11+
#[CoversClass(Kernel::class)]
12+
class KernelTest extends TestCase
13+
{
14+
public function test_self_host_commands_schedule_time_is_consistent_with_app_key(): void
15+
{
16+
// Arrange
17+
config([
18+
'app.key' => 'base64:cOXN4GLMXYjcdG0fKosnFogofXw1pNoXkLAViRH+a5Y=',
19+
]);
20+
21+
// Act
22+
$schedule1 = app()->make(Kernel::class)->resolveConsoleSchedule();
23+
$firstRunEvents = collect($schedule1->events())->filter(fn ($event) => str_contains($event->command, 'self-host:check-for-update') ||
24+
str_contains($event->command, 'self-host:telemetry')
25+
);
26+
27+
$schedule2 = app()->make(Kernel::class)->resolveConsoleSchedule();
28+
$secondRunEvents = collect($schedule2->events())->filter(fn ($event) => str_contains($event->command, 'self-host:check-for-update') ||
29+
str_contains($event->command, 'self-host:telemetry')
30+
);
31+
config([
32+
'app.key' => 'base64:eP58hkQ8l3guqf8wvWJR7pB0weVQtnpjMdYpaVwX4Jw=',
33+
]);
34+
$schedule3 = app()->make(Kernel::class)->resolveConsoleSchedule();
35+
$thirdRunEvents = collect($schedule3->events())->filter(fn ($event) => str_contains($event->command, 'self-host:check-for-update') ||
36+
str_contains($event->command, 'self-host:telemetry')
37+
);
38+
39+
// Assert
40+
$this->assertCount(2, $firstRunEvents);
41+
$this->assertCount(2, $secondRunEvents);
42+
$this->assertCount(2, $thirdRunEvents);
43+
44+
foreach ($firstRunEvents as $index => $event) {
45+
$this->assertSame('52 9,21 * * *', $firstRunEvents[$index]->expression);
46+
$this->assertSame('52 9,21 * * *', $secondRunEvents[$index]->expression);
47+
$this->assertSame('48 13,1 * * *', $thirdRunEvents[$index]->expression);
48+
}
49+
}
50+
51+
public function test_self_hosting_telemetry_can_be_activated(): void
52+
{
53+
// Arrange
54+
config([
55+
'scheduling.tasks.self_hosting_telemetry' => true,
56+
]);
57+
58+
// Act
59+
$schedule = app()->make(Kernel::class)->resolveConsoleSchedule();
60+
$events = collect($schedule->events())->filter(fn ($event) => str_contains($event->command, 'self-host:telemetry')
61+
);
62+
63+
// Assert
64+
$this->assertCount(1, $events);
65+
}
66+
67+
public function test_self_hosting_telemetry_can_be_deactivated(): void
68+
{
69+
// Arrange
70+
config([
71+
'scheduling.tasks.self_hosting_telemetry' => false,
72+
]);
73+
74+
// Act
75+
$schedule = app()->make(Kernel::class)->resolveConsoleSchedule();
76+
$events = collect($schedule->events())->filter(fn ($event) => str_contains($event->command, 'self-host:telemetry')
77+
);
78+
79+
// Assert
80+
$this->assertCount(0, $events);
81+
}
82+
83+
public function test_self_hosting_check_for_update_can_be_activated(): void
84+
{
85+
// Arrange
86+
config([
87+
'scheduling.tasks.self_hosting_check_for_update' => true,
88+
]);
89+
90+
// Act
91+
$schedule = app()->make(Kernel::class)->resolveConsoleSchedule();
92+
$events = collect($schedule->events())->filter(fn ($event) => str_contains($event->command, 'self-host:check-for-update')
93+
);
94+
95+
// Assert
96+
$this->assertCount(1, $events);
97+
}
98+
99+
public function test_self_hosting_check_for_update_can_be_deactivated(): void
100+
{
101+
// Arrange
102+
config([
103+
'scheduling.tasks.self_hosting_check_for_update' => false,
104+
]);
105+
106+
// Act
107+
$schedule = app()->make(Kernel::class)->resolveConsoleSchedule();
108+
$events = collect($schedule->events())->filter(fn ($event) => str_contains($event->command, 'self-host:check-for-update')
109+
);
110+
111+
// Assert
112+
$this->assertCount(0, $events);
113+
}
114+
}

0 commit comments

Comments
 (0)