Workers P3-Endprüfung W1: createJWT sperrt nur bei echter Ablehnung durch Appwrite

Nur ein HTTP-Code ab 400 von Appwrite startet die 2-Minuten-Sperre. Übertragungsfehler
(TypeError, SDK-Fehler mit code 0, Fehler ohne Code), auch wenn sie erst nach der
Zeitgrenze eintreffen, geben die Dienst-Meldung (status 0) und sperren nichts: nach dem
Aufwachen aus dem Ruhezustand erholt sich das Hochhaus mit dem nächsten Takt. Eine späte
echte Ablehnung (etwa 429) sperrt weiter.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-10-18 10:40:10 +00:00
1 parent e3c7a22ae2
commit 2b2b45a0c7
2 files changed
+144 -11

No files matched your search

+16 -8
View File
@@ -12,7 +12,7 @@ export const INVALID_ID_TEXT = 'Ungültige Kennung.'
// Netzwechsel) minutenlang offen und der Feed (ein Abruf je Schleife) stünde still, ohne Fehlermeldung.
export const REQUEST_TIMEOUT_MS = 20000
// Nach einer 401-Folge (frisches JWT wird ebenfalls abgelehnt oder lässt sich nicht erzeugen) wird so lange kein frisches JWT mehr
// erzwungen, und scheitert createJWT selbst (z. B. Appwrite 429), wird so lange gar kein JWT mehr geholt: Appwrite begrenzt
// erzwungen, und lehnt Appwrite createJWT ab (HTTP-Code ab 400, z. B. 429; kein Übertragungsfehler), wird so lange gar kein JWT mehr geholt: Appwrite begrenzt
// createJWT je Nutzer, und die Schleifen (5 s / 15 s) würden das Limit binnen Minuten aufbrauchen und damit auch Serverpuls,
// Finanzen und Vorschauen sperren. 2 Minuten ergeben höchstens 30 Versuche je Stunde und Tab.
export const AUTH_COOLDOWN_MS = 120000
@@ -71,7 +71,7 @@ export function createWorkersApi({
now = Date.now,
}) {
let freshBlockedUntil = 0 // bis dahin wird nach einer 401-Folge kein frisches JWT erzeugt und nach einem gescheiterten createJWT gar keins (AUTH_COOLDOWN_MS)
let mintFailed = false // getJwt (createJWT) ist gescheitert: bis zum Ende der Sperre wird getJwt nicht mehr gerufen, auch nicht bei leerem Cache
let mintFailed = false // Appwrite hat createJWT abgelehnt (HTTP-Code ab 400, kein Übertragungsfehler): bis zum Ende der Sperre wird getJwt nicht mehr gerufen, auch nicht bei leerem Cache
// Führt fn(signal) mit Zeitgrenze aus: nach timeoutMs scheitert der Aufruf mit DOWN_TEXT (status 0) und das Signal wird
// abgebrochen. Das gilt auch, wenn fn das Signal nicht beachtet (hängendes createJWT, fetchImpl ohne Abbruch-Unterstützung).
@@ -105,12 +105,20 @@ export function createWorkersApi({
}
try {
return await getJwt(options)
} catch {
// createJWT selbst scheitert (z. B. Appwrite 429, Sitzung weg): dieselbe Sperre wie nach der zweiten 401.
// Ein hängendes getJwt zählt nicht dazu: es endet in withDeadline mit der Dienst-Meldung, bevor dieser Zweig erreicht wird.
mintFailed = true
freshBlockedUntil = now() + authCooldownMs
throw statusError(SESSION_TEXT, 401)
} catch (e) {
// Gesperrt wird nur, wenn Appwrite geantwortet und abgelehnt hat (HTTP-Code ab 400: 401/403 Sitzung, 429 Begrenzung, 5xx):
// dieselbe Sperre wie nach der zweiten 401. Auch eine späte Ablehnung nach der Zeitgrenze mit echtem Code (etwa ein 429)
// sperrt weiter, denn sie zählt gegen die Begrenzung von createJWT.
if (Number.isInteger(e?.code) && e.code >= 400) {
mintFailed = true
freshBlockedUntil = now() + authCooldownMs
throw statusError(SESSION_TEXT, 401)
}
// Alles andere ist ein Übertragungsfehler (Netz weg, Rechner gerade aus dem Ruhezustand erwacht): Die Anfrage hat Appwrite nicht
// erreicht und verbraucht keine createJWT-Begrenzung. Das Appwrite-SDK meldet das als Fehler mit code 0, der Browser als TypeError.
// Keine Sperre: der nächste Takt (5-15 s) versucht es wieder und fängt sich, sobald das Netz zurück ist. Auch ein solcher Fehler,
// der erst nach der Zeitgrenze eintrifft, sperrt nichts. Ein JWT-Abruf, der nie endet, endet in withDeadline mit derselben Meldung.
throw statusError(DOWN_TEXT, 0)
}
}