Git-Deploy per Tag, Betriebsüberwachung und Release-Seeder für den Livegang
- dev/betrieb/deploy.sh: Deploy nur per Tag, mit --seed (Seeder im Wartungsmodus) und --initial (Vorschau/Live einmalig an Ort und Stelle auf Git umstellen) - dev/betrieb/vorschau-auffrischen.sh: Live-DB und Live-Medien in die Vorschau (Generalprobe) - InteriorReleaseSeeder: alle Inhaltsschritte des Relaunchs in einem Lauf, idempotent; Displays, Playlists und Mediathek bleiben unberührt - DisplayInteriorBrandingSeeder überschreibt keinen inzwischen gepflegten Claim mehr - Monitoring: GlitchTip (Server + Browser), /health mit Token, Scheduler-Herzschlag, Alarme per Mail und ntfy, Version in about und /health - public/build versioniert; .gitignore: macOS-Muster Icon traf resources/views/flux/icon/ - Runbook: dev/betrieb/README.md Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
fcb10be120
commit
b5ed756d67
98 changed files with 3947 additions and 82 deletions
25
app/Console/Commands/MonitoringHeartbeat.php
Normal file
25
app/Console/Commands/MonitoringHeartbeat.php
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Services\Monitoring\HealthProbe;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
/**
|
||||
* Minütlicher Herzschlag des Schedulers. Bleibt er aus,
|
||||
* melden `/health` und der Systemstatus den Scheduler als ausgefallen —
|
||||
* `onFailure` der einzelnen Tasks greift in diesem Fall nicht mehr.
|
||||
*/
|
||||
class MonitoringHeartbeat extends Command
|
||||
{
|
||||
protected $signature = 'monitoring:heartbeat';
|
||||
|
||||
protected $description = 'Schreibt den Herzschlag des Schedulers (Grundlage für /health und den Systemstatus).';
|
||||
|
||||
public function handle(HealthProbe $probe): int
|
||||
{
|
||||
$probe->recordHeartbeat();
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
||||
50
app/Console/Commands/MonitoringQueueProbe.php
Normal file
50
app/Console/Commands/MonitoringQueueProbe.php
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Jobs\Monitoring\QueueProbe;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Sleep;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* Prüft, ob ein Queue-Worker läuft: stellt einen Test-Job ein und wartet,
|
||||
* bis er abgeholt ist (Aufruf am Ende von dev/betrieb/deploy.sh).
|
||||
*
|
||||
* Hintergrund: `queue:restart` beendet den Worker, neu starten muss ihn
|
||||
* Supervisor. Läuft Supervisor nicht, bleibt die Queue still stehen.
|
||||
*/
|
||||
class MonitoringQueueProbe extends Command
|
||||
{
|
||||
protected $signature = 'monitoring:queue-probe
|
||||
{--wait=60 : Sekunden, die auf den Worker gewartet wird}';
|
||||
|
||||
protected $description = 'Prüft mit einem Test-Job, ob ein Queue-Worker läuft.';
|
||||
|
||||
public function handle(): int
|
||||
{
|
||||
$token = Str::random(16);
|
||||
$wait = max(0, (int) $this->option('wait'));
|
||||
|
||||
QueueProbe::dispatch($token);
|
||||
|
||||
for ($second = 0; $second <= $wait; $second++) {
|
||||
if (Cache::has(QueueProbe::cacheKey($token))) {
|
||||
Cache::forget(QueueProbe::cacheKey($token));
|
||||
$this->info(sprintf('Queue-Worker läuft (Test-Job nach %d s abgeholt).', $second));
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
if ($second < $wait) {
|
||||
Sleep::for(1)->second();
|
||||
}
|
||||
}
|
||||
|
||||
$this->error(sprintf('Kein Queue-Worker hat den Test-Job innerhalb von %d s abgeholt.', $wait));
|
||||
$this->line('Worker prüfen: läuft Supervisor (bzw. der Worker im Server-Panel)? Notfalls: nohup php artisan queue:work --tries=3 --max-time=3600 &');
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue