feat(docker): implement Docker cleanup processing in ScheduledJobManager; refactor server task scheduling to streamline cleanup job dispatching

This commit is contained in:
Andras Bacsai
2025-08-26 14:43:57 +02:00
parent c2e3487745
commit ed93031a39
2 changed files with 84 additions and 10 deletions

View File

@@ -4,6 +4,8 @@ namespace App\Jobs;
use App\Models\ScheduledDatabaseBackup; use App\Models\ScheduledDatabaseBackup;
use App\Models\ScheduledTask; use App\Models\ScheduledTask;
use App\Models\Server;
use App\Models\Team;
use Cron\CronExpression; use Cron\CronExpression;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
@@ -12,6 +14,7 @@ use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\Middleware\WithoutOverlapping; use Illuminate\Queue\Middleware\WithoutOverlapping;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
class ScheduledJobManager implements ShouldQueue class ScheduledJobManager implements ShouldQueue
@@ -77,6 +80,16 @@ class ScheduledJobManager implements ShouldQueue
'trace' => $e->getTraceAsString(), 'trace' => $e->getTraceAsString(),
]); ]);
} }
// Process Docker cleanups - don't let failures stop the job manager
try {
$this->processDockerCleanups();
} catch (\Exception $e) {
Log::channel('scheduled-errors')->error('Failed to process docker cleanups', [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
]);
}
} }
private function processScheduledBackups(): void private function processScheduledBackups(): void
@@ -226,4 +239,75 @@ class ScheduledJobManager implements ShouldQueue
return $cron->isDue($executionTime); return $cron->isDue($executionTime);
} }
private function processDockerCleanups(): void
{
// Get all servers that need cleanup checks
$servers = $this->getServersForCleanup();
foreach ($servers as $server) {
try {
if (! $this->shouldProcessDockerCleanup($server)) {
continue;
}
$serverTimezone = data_get($server->settings, 'server_timezone', config('app.timezone'));
if (validate_timezone($serverTimezone) === false) {
$serverTimezone = config('app.timezone');
}
$frequency = data_get($server->settings, 'docker_cleanup_frequency', '0 * * * *');
if (isset(VALID_CRON_STRINGS[$frequency])) {
$frequency = VALID_CRON_STRINGS[$frequency];
}
// Use the frozen execution time for consistent evaluation
if ($this->shouldRunNow($frequency, $serverTimezone)) {
DockerCleanupJob::dispatch(
$server,
false,
$server->settings->delete_unused_volumes,
$server->settings->delete_unused_networks
);
}
} catch (\Exception $e) {
Log::channel('scheduled-errors')->error('Error processing docker cleanup', [
'server_id' => $server->id,
'server_name' => $server->name,
'error' => $e->getMessage(),
]);
}
}
}
private function getServersForCleanup(): Collection
{
$query = Server::with('settings')
->where('ip', '!=', '1.2.3.4');
if (isCloud()) {
$servers = $query->whereRelation('team.subscription', 'stripe_invoice_paid', true)->get();
$own = Team::find(0)->servers()->with('settings')->get();
return $servers->merge($own);
}
return $query->get();
}
private function shouldProcessDockerCleanup(Server $server): bool
{
if (! $server->isFunctional()) {
return false;
}
// In cloud, check subscription status (except team 0)
if (isCloud() && $server->team_id !== 0) {
if (data_get($server->team->subscription, 'stripe_invoice_paid', false) === false) {
return false;
}
}
return true;
}
} }

View File

@@ -138,16 +138,6 @@ class ServerManagerJob implements ShouldQueue
if (validate_timezone($serverTimezone) === false) { if (validate_timezone($serverTimezone) === false) {
$serverTimezone = config('app.timezone'); $serverTimezone = config('app.timezone');
} }
// Dispatch DockerCleanupJob if due
$dockerCleanupFrequency = data_get($server->settings, 'docker_cleanup_frequency', '0 * * * *');
if (isset(VALID_CRON_STRINGS[$dockerCleanupFrequency])) {
$dockerCleanupFrequency = VALID_CRON_STRINGS[$dockerCleanupFrequency];
}
$shouldRunDockerCleanup = $this->shouldRunNow($dockerCleanupFrequency, $serverTimezone);
if ($shouldRunDockerCleanup) {
DockerCleanupJob::dispatch($server, false, $server->settings->delete_unused_volumes, $server->settings->delete_unused_networks);
}
// Dispatch ServerPatchCheckJob if due (weekly) // Dispatch ServerPatchCheckJob if due (weekly)
$shouldRunPatchCheck = $this->shouldRunNow('0 0 * * 0', $serverTimezone); $shouldRunPatchCheck = $this->shouldRunNow('0 0 * * 0', $serverTimezone);