fix(sync): Teil-Abrufe verschlucken ihre Fehler nicht mehr
CI / pruefen (pull_request) Canceled after 0s

Behebt florian.wilde/nebula#19 und florian.wilde/nebula#20.

getJsonSafe machte aus jedem Fehlschlag eine leere Liste. Damit war ein
403 nicht mehr von "das Repository hat keine Branches" zu unterscheiden:
Der Abgleich lief durch, meldete "Snapshot aktualisiert: 0 Branches,
0 Tags", setzte kein syncError - und ueberschrieb dabei den letzten guten
Stand mit Nullen. Ein Repository mit 65 Commits sah danach aus wie ein
leeres, und die Ursache war nicht zu ermitteln, weil die Auskunft, die
sie benannt haette, gerade weggeworfen worden war.

Teilabrufe sammelt jetzt je Feld, was schiefging - mit HTTP-Status, denn
daran haengt die Ursache: 403 heisst Scopes, 429 Rate-Limit, 408
Zeitueberschreitung, 0 nicht erreicht. Der Fallback bleibt, ein einzelner
Fehlschlag darf den ganzen Abgleich nicht abbrechen.

Daraus folgt der zweite Teil: persistSnapshot laesst stehen, was nicht
geholt werden konnte. Der Snapshot ist ein Zwischenspeicher - ein alter
Stand mit sichtbarem Datum ist immer brauchbarer als eine leere Liste,
die aussieht wie eine Aussage. Die abgeleiteten Felder gehen mit ihrer
Liste: lastCommit* haengt an commits, latestTag an tags UND releases,
sonst waeren sie in sich widerspruechlich.

Bewusst kein Fehlschlag: syncError bleibt leer und der Zaehler fuers
Zurueckhalten steigt nicht. Der Rest des Standes ist frisch, und ein
Repository deswegen stundenlang auszusetzen waere die falsche Antwort.

GIT_API_TIMEOUT_MS wird geprueft. Number("") ist 0 und Number("abc") ist
NaN; setTimeout loest bei beidem sofort aus, und dann bricht jeder Aufruf
ab, bevor er beginnt. Eine verrutschte Zeile in der .env legte damit den
ganzen Abgleich still - lautlos, versteht sich.

NACHGEWIESEN, NICHT BEHAUPTET

Gegen einen nachgebauten Gitea-Server, der genau den beobachteten Fall
erzeugt - Basis-Aufruf antwortet, Teillisten geben 403 - und eine
Wegwerf-Datenbank:

  gesund      branchCount=2 tagCount=3 commits=2 releases=1 missing={}
  kaputt      branchCount=2 tagCount=3 commits=2 releases=1
              missing={8 Felder mit HTTP 403}, completeAt unveraendert
  wieder gut  missing={} , completeAt fortgeschrieben

Nichts verloren, die Luecke steht in der Meldung und am Repository, und
nach dem naechsten gesunden Durchlauf raeumt sie sich von selbst weg.
axe-core 0 Verstoesse auf 1280 und 375 px, kein seitlicher Ueberlauf.

Der eigentliche Grund der Ausfaelle auf der Instanz ist damit noch nicht
gefunden - aber ab jetzt steht er auf der Projektseite.

Refs #19
Refs #20
This commit is contained in:
2026-09-01 18:09:01 +02:00
parent 4ce26e1e8d
commit b062eb36a1
14 changed files with 1002 additions and 199 deletions
+27
View File
@@ -553,6 +553,33 @@ deshalb ohne Risiko.
| Releases | bis zu 10, inklusive Pre-Release- und Draft-Kennzeichnung |
| Sprachen | Verteilung als Balken mit Prozentwerten |
#### Wenn ein Teil nicht ankommt
Diese Listen werden gleichzeitig geholt, und einzelne davon können scheitern, während
der Rest durchgeht — ein 403 wegen fehlender Scopes, ein Rate-Limit, eine
Zeitüberschreitung.
**Ein gescheiterter Abruf ist keine leere Liste.** Der Unterschied steht am Snapshot: zu
jedem Feld, das nicht geholt werden konnte, wird der Grund samt HTTP-Status festgehalten.
Daraus folgt dreierlei:
- Die vorhandenen Daten **bleiben stehen**. Ein Abgleich, der die Tags nicht holen konnte,
ersetzt die gespeicherten nicht durch eine leere Liste. Angezeigt wird dann der letzte
vollständige Stand, mit Datum.
- Die Meldung heißt „Teilweise aktualisiert – nicht geholt: …" statt „Snapshot
aktualisiert: 0 Branches, 0 Tags".
- Auf der Projektseite steht ein Hinweis am Repository, der jedes fehlende Feld mit
seinem Grund nennt.
Das gilt ausdrücklich **nicht** als Fehlschlag: `syncError` bleibt leer, der Zähler für
das Zurückhalten wird nicht erhöht, und der nächste Durchlauf versucht es normal wieder.
Der Rest des Standes ist ja frisch.
> Vor v1.10.2 wurde jeder Fehlschlag in eine leere Liste verwandelt. Ein Repository mit
> 65 Commits meldete „Snapshot aktualisiert: 0 Branches, 0 Tags", überschrieb dabei den
> letzten guten Stand, und aus der Oberfläche war nicht zu erkennen, dass überhaupt etwas
> schiefgegangen war.
Woher der CI-Status kommt:
| System | Quelle |