option('dry-run'); $started = 0; /** @var array reason => count */ $skipped = []; $query = Instance::query()->where('status', 'active'); if ($uuid = $this->option('instance')) { $query->where('uuid', $uuid); } foreach ($query->with('host')->get() as $instance) { $reason = $this->reasonToSkip($instance); if ($reason !== null) { $skipped[$reason] = ($skipped[$reason] ?? 0) + 1; continue; } $started++; if ($dryRun) { $this->line("{$instance->uuid}: würde nachgetragen"); continue; } $run = ProvisioningRun::create([ 'pipeline' => 'instance-mail', 'subject_type' => Instance::class, 'subject_id' => $instance->id, 'status' => ProvisioningRun::STATUS_PENDING, 'current_step' => 0, 'context' => [ 'instance_id' => $instance->id, 'node' => $instance->host->node ?? 'pve', 'vmid' => (int) $instance->vmid, ], ]); AdvanceRunJob::dispatch($run->uuid); $this->info("{$instance->uuid}: Lauf {$run->id} gestartet"); $started++; } foreach ($skipped as $reason => $count) { $this->line("übersprungen ({$reason}): {$count}"); } $this->info($dryRun ? "Probelauf: {$started} Instanz(en) bekämen den Mailversand, ".array_sum($skipped).' übersprungen. Nichts wurde geändert.' : "{$started} Lauf/Läufe gestartet, ".array_sum($skipped).' übersprungen.'); return self::SUCCESS; } /** * Warum diese Instanz uebergangen wird, oder null. * * Der Grund IST der Bericht: „2 uebergangen" allein ist keine Auskunft, * mit der jemand etwas anfangen kann — „2 haben keinen Host" und „2 laufen * bereits" sehen von hier aus gleich aus, sind aber völlig verschiedene * Reparaturen. */ private function reasonToSkip(Instance $instance): ?string { if ($instance->host === null) { return 'kein Host'; } if (blank($instance->vmid)) { return 'keine VMID'; } if ($this->hasRunInFlight($instance)) { return 'anderer Lauf aktiv'; } return null; } /** * JEDER Lauf gegen diese Instanz, absichtlich weit gefasst: das hier ist ein * Reparatur-Durchgang. Er läuft wieder, und eine heute übergangene Instanz ist * beim nächsten Aufruf dran. Nichts geht durch Warten verloren. */ private function hasRunInFlight(Instance $instance): bool { return ProvisioningRun::query() ->where('subject_type', Instance::class) ->where('subject_id', $instance->id) ->inFlight() ->exists(); } }