#!/usr/bin/env php dbPath()); $service = new CodebergSyncService( new CurlCodebergClient($config->codebergApiBase(), $config->codebergToken()), new TicketRepository($db), new RepoConfigRepository($db), ); // Ohne --watch bleibt das Skript ein einmaliger Lauf (manueller Aufruf, siehe README). if (!in_array('--watch', $argv, true)) { $service->sync(); fwrite(STDOUT, "Codeberg-Sync abgeschlossen.\n"); return; } $trigger = new SyncTrigger($config->syncTriggerPath()); $interval = $config->syncIntervalSeconds(); $schedule = new SyncSchedule($interval); fwrite(STDOUT, sprintf("[sync] Watch-Modus, periodischer Lauf alle %ds, Webhook-Trigger sofort.\n", $interval)); $lastRun = 0; $failures = 0; while (true) { $triggered = $trigger->consume(); $due = (time() - $lastRun) >= $schedule->secondsUntilNextRun($failures); if ($triggered || $due) { $lastRun = time(); try { $service->sync(); $failures = 0; fwrite(STDOUT, sprintf("[sync] Lauf beendet (%s).\n", $triggered ? 'Webhook' : 'periodisch')); } catch (Throwable $e) { // Ein fehlgeschlagener Lauf (Codeberg nicht erreichbar, Rate-Limit) darf die // Schleife nicht beenden, sonst landet der Container in einer Restart-Schleife. // Stattdessen wird der naechste Versuch vorgezogen (siehe SyncSchedule) - eine // per Webhook angeforderte Aktualisierung ist sonst verloren, weil die // Anforderung vor dem Lauf quittiert wurde. $failures++; fwrite(STDERR, sprintf( "[sync] Lauf fehlgeschlagen (%dx in Folge, naechster Versuch in %ds): %s\n", $failures, $schedule->secondsUntilNextRun($failures), $e->getMessage() )); } } // Sekundentakt: bestimmt, wie schnell ein Webhook-Trigger bemerkt wird. Der Check ist // ein file_exists() auf einem lokalen Volume, kostet also praktisch nichts - im // Gegensatz zum Codeberg-Request, der weiterhin nur bei Bedarf laeuft. sleep(1); }