Skip to content

Fehlerbehandlung & Randfälle ​

Eine robuste Fehlerbehandlung ist für eine zuverlässige Integration unerlässlich. Dieses Kapitel behandelt die HTTP-Statuscodes, auf die Sie stoßen werden, die Fehlerantwortformate und Hinweise zur Behandlung von Randfällen.

HTTP-Statuscode-Referenz ​

StatusBedeutungTypische Ursachen
200ErfolgAnfrage erfolgreich verarbeitet
400Ungültige AnfrageUngültiger Zustandsname, fehlerhafte Nutzlast, fehlende Pflichtfelder
401Nicht autorisiertFehlender, ungültiger oder abgelaufener API-Schlüssel
404Nicht gefundenRessource (Bestellung, Befehl) nicht vorhanden
409KonfliktOptimistischer Sperrkonflikt (gleichzeitige Änderung)
429Zu viele AnfragenRatenbegrenzung überschritten (derzeit nicht implementiert, aber einplanen)
500Interner ServerfehlerUnerwarteter Serverfehler
503Dienst nicht verfügbarVorübergehende Server-Nichtverfügbarkeit

Fehlerantwortformate ​

Die API verwendet zwei verschiedene Fehlerantwortformate.

ProblemDetail (RFC 7807) ​

Die meisten Fehler vom GlobalExceptionHandler verwenden das standardisierte ProblemDetail-Format:

json
{
  "type": "about:blank",
  "title": "Bad Request",
  "status": 400,
  "detail": "Invalid order state name",
  "instance": "/orders/12345/statusupdate"
}

Das Feld type ist typischerweise "about:blank". Der title ist eine kurze Klassifizierung. Der detail enthält eine menschenlesbare Erklärung. Der instance ist der Request-URI, der den Fehler verursacht hat.

Häufige ProblemDetail-Antworten:

SzenarioStatusTitelDetail
Ungültiger Zustandsname400Illegal argumentNo enum constant ...
Fehlendes Pflichtfeld400Illegal argumentLocation name is required.
Ungültige Bestell-ID (Bestellung nicht vorhanden)400Illegal argumentOrder does not exist
Validierungsfehler400Validation error(Validierungsmeldung)
Datenbank-Constraint-Verletzung400Constraint violationAllgemeine Constraint-Meldung
Lizenzfehler401License error(lizenzbezogene Meldung)
Datenbankoperationsfehler400Something went wrong during database operation.(Fehlerdetails)
Interner Serverfehler500Internal server error{uuid}: {message}

Jede 500-Antwort enthält eine UUID für die Rückverfolgung. Protokollieren Sie diese UUID bei der Fehlerbehebung.

Legacy-401-Antworten ​

Authentifizierungsfehler geben zwei mögliche Formate zurück:

Vom AuthorizationInterceptor (fehlender/ungültiger Schlüssel):

http
HTTP/1.1 401 Unauthorized
Content-Type: text/plain

{"error" : "Session not valid."}

Hinweis: Diese Antwort hat Content-Type: text/plain, nicht application/json, auch wenn der Body JSON ist. Die Antwort enthält eine zufällige Verzögerung von 500-1499 ms.

Vom UnAuthorizedException-Handler (abgelaufene Sitzung):

json
{
  "message": "Unauthorized",
  "uid": null
}

Beide bedeuten dasselbe: Der API-Schlüssel ist nicht gültig. Authentifizieren Sie sich neu oder besorgen Sie einen neuen Schlüssel.

Randfälle ​

SSE-Wiederverbindung mit Offset-Parametern ​

Wenn die SSE-Verbindung abbricht:

  1. Erkennen Sie den Abbruch über den onerror-Callback (EventSource) oder Verbindungs-Timeout.
  2. Implementieren Sie exponentiellen Backoff: 1s, 2s, 4s, 8s, gedeckelt bei 60s.
  3. Übergeben Sie bei der Wiederverbindung die zuletzt verarbeitete Bestellnummer und Befehls-ID: /notifications/service/stream?orderNumber=12345&commandNumber=42
  4. Fragen Sie nach der Wiederverbindung offene Vorgänge ab. Prüfen Sie einen vorhandenen Schlüssel vor dem Ersatz; das Schließen des Streams belegt keinen ungültigen Schlüssel.

Verwenden Sie die Anleitung zum Verbindungsaufbau und erneuten Verbinden.

Netzwerkpartitionierung ​

Warten Sie zur Erkennung einer unterbrochenen Verbindung nicht auf das konfigurierte Emitter-Zeitlimit des Servers. Überwachen Sie eingehende Ereignisse mit einer lokalen Lese-/Leerlaufschwelle. Fehlende Keepalives garantieren keinen sofortigen Transportfehler.

Verwenden Sie bei erreichbarem Server begrenztes Fallback-Polling und verbinden Sie SSE mit Backoff erneut. Bei unerreichbarem Server begrenzen Sie beide Vorgänge. Fragen Sie nach der Wiederherstellung offene Vorgänge ab und gleichen Sie dauerhafte Verarbeitungsstände ab, bevor Sie erneut an die Kasse senden.

Duplikaterkennung ​

Verwenden Sie getrennte dauerhafte Verarbeitungsstände für Bestellungen und Befehle, zugeordnet zu Installation und Standort. Ihre number-Felder gehören zu unterschiedlichen Kennungsfolgen. Ein Satz im Arbeitsspeicher schützt nach einem Neustart nicht vor Duplikaten.

Koordinieren Sie Worker vor der externen Übergabe. Speichern Sie externes Ergebnis und Bestätigung getrennt. Klären Sie unbekannte Ergebnisse mit der Kasse vor einem erneuten Versuch. Richten Sie die Aufbewahrung nach dem Wiederherstellungsbedarf aus; ein pauschaler Ablauf nach einer Stunde verhindert Duplikate nicht zuverlässig.

Teilweise Daten — Nullable-Felder ​

Felder ohne Wert werden aus der Antwort weggelassen — die API serialisiert null nicht. Ihr Client darf nicht davon ausgehen, dass ein Feld immer vorhanden ist:

  • tableNumber — Kann bei Mitnahmebestellungen fehlen. Behandeln Sie es als "kein Tisch zugewiesen."
  • userNumber — Kann fehlen, wenn die Bestellung ohne Benutzersitzung erstellt wurde.
  • state — Immer vorhanden. Befehle melden immer PLACED.
  • rows — Nur bei Bestellungen vorhanden. Befehle haben keine Zeilen.
  • guestCount — Bei Bestellungen vorhanden (aktuell immer 1).
  • readTableState — Nur bei Tischstatus-lesen-Befehlen vorhanden (true).
  • paymentNumber — Nur bei Rechnung-anfordern-Befehlen vorhanden (immer 1).
  • exportMainData — Nur bei Daten-exportieren-/Remote-Menü-abrufen-Befehlen vorhanden (true).

Das DTO definiert außerdem togo, moveTableTo, receipt, paymentDiscount und customer, aber das aktuelle Backend füllt sie nie aus, daher erscheinen sie nie in Antworten.

Sicherer Zugriffsansatz:

javascript
// Optionale Verkettung und Nullish Coalescing verwenden
const table = order.tableNumber ?? "unbekannt";
const state = order.state ?? "PLACED";
const rows = order.rows ?? [];
const paymentDiscounts = order.paymentDiscount ?? [];

Bestellstatus-Maschine ​

text
                           +---> COMPLETED
                           |
   SELECTING --> NEW --> PLACED ----> ABORTED
                           |
                           +---> FAILED ---> PLACED (Wiederholung)
  • SELECTING: Kunde fügt Artikel hinzu. Für Service-Clients über den Standort-Endpunkt nicht sichtbar.
  • NEW: Bestellung von einer Client-App erstellt. Noch nicht aufgegeben.
  • PLACED: Kunde hat die Bestellung aufgegeben. Dies ist der Status, den Ihr Service-Client beim Polling sieht.
  • COMPLETED: Bestellung erfüllt. Von Ihrem Service-Client über die Statusaktualisierung gesetzt.
  • ABORTED: Bestellung storniert. Von Ihrem Client gesetzt oder wenn eine Sitzung geschlossen wird.
  • FAILED: Verarbeitungsfehler. Unterhalb der konfigurierten Fehlergrenze wird die Bestellung bei einer Fehlermeldung wieder auf PLACED gesetzt; an der Grenze ist eine Wiederherstellung durch den Betreiber nötig. Siehe Fehlerbehandlung.

Wenn Sie den Status einer Bestellung aktualisieren, zeichnet der Server Zeitstempel auf:

  • orderTime — Wird gesetzt, wenn die Bestellung in PLACED übergeht
  • completeTime — Wird gesetzt, wenn die Bestellung in COMPLETED oder ABORTED übergeht
  • failedTime — Wird gesetzt, wenn die Bestellung in FAILED übergeht

Gleichzeitigkeit — Integrationsworker koordinieren ​

Mehrere Polling-Clients können dieselben Bestellungen erhalten. Koordinieren Sie Worker und speichern Sie Verarbeitungskennungen vor der externen Übergabe. Eine zweite Statusänderung muss nicht wegen der ersten fehlschlagen. Der Endpunkt reserviert keine Arbeit; setzen Sie keine transparente Konfliktwiederholung voraus. Klären Sie unbekannte Ergebnisse vor erneuter externer Verarbeitung.

Umgang mit Timeouts ​

Unterscheiden Sie Verbindungsaufbau, Zeitgrenzen normaler Anfragen und SSE-Lese-/Leerlaufüberwachung. Beispielsweise können Sie normale Anfragen auf 30 Sekunden begrenzen und 60 Sekunden ohne Streamereignis untersuchen. Dies sind Vorschläge für die Clientkonfiguration, keine garantierten Serverantwortzeiten.

Klären Sie nach einem Schreib-Timeout das Ergebnis vor einer Wiederholung. Siehe Sicherheit und bewährte Verfahren.

Curl: Fehlerszenarien simulieren ​

Ungültiger API-Schlüssel ​

bash
curl -i -H "api_key: invalid-key" "https://{host}/orders/location"

Nicht vorhandene Bestellung ​

bash
curl -i -X PUT \
  -H "api_key: abc123-def456-ghi789" \
  -H "Content-Type: application/json" \
  -d '{"newState": "COMPLETED"}' \
  "https://{host}/orders/99999/statusupdate"

Ungültige JSON-Payload ​

bash
curl -i -X PUT \
  -H "api_key: abc123-def456-ghi789" \
  -H "Content-Type: application/json" \
  -d 'not-json' \
  "https://{host}/orders/12345/statusupdate"

Nächste Schritte ​