mirror of
https://github.com/coollabsio/coolify.git
synced 2026-06-14 03:19:51 +00:00
1c5d5676ef
Interleave due backups and tasks so one schedule type cannot starve the other, and defer task job context loading until execution.
151 lines
5.2 KiB
PHP
151 lines
5.2 KiB
PHP
<?php
|
|
|
|
use App\Jobs\ScheduledJobManager;
|
|
use App\Jobs\ScheduledTaskJob;
|
|
use App\Models\Application;
|
|
use App\Models\Environment;
|
|
use App\Models\PrivateKey;
|
|
use App\Models\Project;
|
|
use App\Models\ScheduledTask;
|
|
use App\Models\Server;
|
|
use App\Models\StandaloneDocker;
|
|
use App\Models\Team;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Carbon;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Queue;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
it('dispatches scheduled tasks across chunks', function () {
|
|
config(['constants.coolify.self_hosted' => true]);
|
|
Carbon::setTestNow(Carbon::create(2026, 5, 27, 0, 1, 0, 'UTC'));
|
|
Queue::fake();
|
|
|
|
$team = Team::factory()->create();
|
|
$privateKey = PrivateKey::create([
|
|
'name' => 'Test Key',
|
|
'private_key' => '-----BEGIN OPENSSH PRIVATE KEY-----
|
|
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
|
|
QyNTUxOQAAACBbhpqHhqv6aI67Mj9abM3DVbmcfYhZAhC7ca4d9UCevAAAAJi/QySHv0Mk
|
|
hwAAAAtzc2gtZWQyNTUxOQAAACBbhpqHhqv6aI67Mj9abM3DVbmcfYhZAhC7ca4d9UCevA
|
|
AAAECBQw4jg1WRT2IGHMncCiZhURCts2s24HoDS0thHnnRKVuGmoeGq/pojrsyP1pszcNV
|
|
uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
|
|
-----END OPENSSH PRIVATE KEY-----',
|
|
'team_id' => $team->id,
|
|
]);
|
|
$server = Server::factory()->create([
|
|
'team_id' => $team->id,
|
|
'private_key_id' => $privateKey->id,
|
|
]);
|
|
$server->settings()->update([
|
|
'is_reachable' => true,
|
|
'is_usable' => true,
|
|
'force_disabled' => false,
|
|
'docker_cleanup_frequency' => '0 * * * *',
|
|
]);
|
|
|
|
$destination = StandaloneDocker::where('server_id', $server->id)->first()
|
|
?? StandaloneDocker::factory()->create(['server_id' => $server->id]);
|
|
$project = Project::factory()->create(['team_id' => $team->id]);
|
|
$environment = Environment::factory()->create(['project_id' => $project->id]);
|
|
$application = Application::factory()->create([
|
|
'environment_id' => $environment->id,
|
|
'destination_id' => $destination->id,
|
|
'destination_type' => StandaloneDocker::class,
|
|
'status' => 'running',
|
|
]);
|
|
|
|
ScheduledTask::factory()
|
|
->count(101)
|
|
->create([
|
|
'team_id' => $team->id,
|
|
'application_id' => $application->id,
|
|
'frequency' => '* * * * *',
|
|
'enabled' => true,
|
|
]);
|
|
|
|
(new ScheduledJobManager)->handle();
|
|
|
|
Queue::assertPushed(ScheduledTaskJob::class, 101);
|
|
});
|
|
|
|
it('skips expensive dispatch for non-due schedules while seeding dedup cache', function () {
|
|
config(['constants.coolify.self_hosted' => true]);
|
|
Carbon::setTestNow(Carbon::create(2026, 5, 27, 0, 1, 0, 'UTC'));
|
|
Queue::fake();
|
|
|
|
$application = createScheduledTaskApplication();
|
|
|
|
$task = ScheduledTask::factory()->create([
|
|
'team_id' => $application->environment->project->team_id,
|
|
'application_id' => $application->id,
|
|
'frequency' => '0 2 * * *',
|
|
'enabled' => true,
|
|
]);
|
|
|
|
(new ScheduledJobManager)->handle();
|
|
|
|
Queue::assertNotPushed(ScheduledTaskJob::class);
|
|
expect(Cache::get("scheduled-task:{$task->id}"))->not->toBeNull();
|
|
});
|
|
|
|
it('does not query relationships when constructing scheduled task jobs', function () {
|
|
$application = createScheduledTaskApplication();
|
|
|
|
$task = ScheduledTask::factory()->create([
|
|
'team_id' => $application->environment->project->team_id,
|
|
'application_id' => $application->id,
|
|
'frequency' => '* * * * *',
|
|
'enabled' => true,
|
|
])->fresh();
|
|
|
|
DB::flushQueryLog();
|
|
DB::enableQueryLog();
|
|
|
|
$job = new ScheduledTaskJob($task);
|
|
|
|
expect(DB::getQueryLog())->toBeEmpty()
|
|
->and($job->queue)->toBe(crons_queue())
|
|
->and($job->timeout)->toBe(300);
|
|
});
|
|
|
|
function createScheduledTaskApplication(): Application
|
|
{
|
|
$team = Team::factory()->create();
|
|
$privateKey = PrivateKey::create([
|
|
'name' => 'Test Key',
|
|
'private_key' => '-----BEGIN OPENSSH PRIVATE KEY-----
|
|
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
|
|
QyNTUxOQAAACBbhpqHhqv6aI67Mj9abM3DVbmcfYhZAhC7ca4d9UCevAAAAJi/QySHv0Mk
|
|
hwAAAAtzc2gtZWQyNTUxOQAAACBbhpqHhqv6aI67Mj9abM3DVbmcfYhZAhC7ca4d9UCevA
|
|
AAAECBQw4jg1WRT2IGHMncCiZhURCts2s24HoDS0thHnnRKVuGmoeGq/pojrsyP1pszcNV
|
|
uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
|
|
-----END OPENSSH PRIVATE KEY-----',
|
|
'team_id' => $team->id,
|
|
]);
|
|
$server = Server::factory()->create([
|
|
'team_id' => $team->id,
|
|
'private_key_id' => $privateKey->id,
|
|
]);
|
|
$server->settings()->update([
|
|
'is_reachable' => true,
|
|
'is_usable' => true,
|
|
'force_disabled' => false,
|
|
'docker_cleanup_frequency' => '0 * * * *',
|
|
]);
|
|
|
|
$destination = StandaloneDocker::where('server_id', $server->id)->first()
|
|
?? StandaloneDocker::factory()->create(['server_id' => $server->id]);
|
|
$project = Project::factory()->create(['team_id' => $team->id]);
|
|
$environment = Environment::factory()->create(['project_id' => $project->id]);
|
|
|
|
return Application::factory()->create([
|
|
'environment_id' => $environment->id,
|
|
'destination_id' => $destination->id,
|
|
'destination_type' => StandaloneDocker::class,
|
|
'status' => 'running',
|
|
]);
|
|
}
|