GH GambleHub

Obsługa błędów i kody stanu

1) Dlaczego ujednolicić błędy

Pojedyncza umowa o błąd przyspiesza debugowanie klienta, zmniejsza fałszywe przekłady i sprawia, że RCA jest odtwarzalne. Dobry system:
  • przewidywalnie koduje typ problemu,
  • daje klientowi ważne wiersze (co zrobić dalej),
  • chroni przed wyciekiem części wewnętrznych,
  • kompatybilny z retrasami i idempotencją.

2) Zasady projektowania

1. Jeden system błędów dla wszystkich usług (REST/GraphQL/gRPC/webhooks).
2. Jasne semantyki retras: które kody do wycofania, które nie.
3. Nieudane operacje pisania: lepsze 4xx/5xx niż cicha niespójność.
4. Brak przecieków: nie ujawniać SQL, stosy, konfiguracje, wewnętrzne identyfikatory.
5. Trace - Zawsze zwracaj 'trace _ id'/' correlation _ id'.
6. Lokalizacja wiadomości jest opcjonalna, ale kody i 'resason' pozostają stabilne.


3) Jednolity format (Szczegóły problemu/JSON)

Zalecany format podstawowy (zgodny z RFC 7807):
json
{
"type": "https://errors.example.com/auth/invalid-token",
"title": "Invalid access token",
"status": 401,
"code": "AUTH_INVALID_TOKEN",
"detail": "Token expired or signature invalid.",
"instance": "/api/v1/payments/12345",
"trace_id": "01HX3...ABC",
"hint": "Obtain a new token via OAuth2 refresh.",
"meta": {
"scope": "payments:write",
"policy": "deny-by-default"
}
}
Wyjaśnienia:
  • 'type' to stabilny adres URL klasy błędów.
  • „kod” - krótki kod maszyny domeny (stabilny między wydaniami).
  • „wskazówka” - co zrobić dla klienta (powtórzyć, zaktualizować token, zmienić parametry).
  • „meta” - części zabezpieczone (bez tajemnic i PII).

4) Mapa kodu statusu (minimalny zestaw)

Uwierzytelnianie/autoryzacja

400 Bad Request - zatwierdzenie strukturalne/program.
401 Nieautoryzowany - nie/nieprawidłowy token. Dodaj 'WWW-Authenticate'.
403 Zakazane - uwierzytelnione, ale pozbawione praw/polityk.
404 Nie znaleziono - maska istnienie zasobu bez praw.
409 Konflikt - wersja/konflikt państwa (optymistyczny zamek, idempotencja).
451 Niedostępne ze względów prawnych - zgodność/blok jurysdykcyjny.

Granice i ochrona

408 Żądanie Timeout - Klient przesyła ciało zbyt powoli.
409/425 Zbyt wcześnie - zakaz wczesnego powtarzania w 0-RTT/TLS 1. 3.
429 Zbyt wiele żądań - z „Retry-After” i ograniczyć politykę.
499 Klient zamknięte żądanie - (na obwodzie/NGINX) klient odłączył połączenie.

Zasady dotyczące danych i działalności gospodarczej

422 Nieprzetworzona treść - walidacja firmy przeszła program, ale znaczenie jest nieprawidłowe.
423 Zablokowany - zablokowany zasób (przegląd KYC, zamrożenie AML).
409 Konflikt - podwójne zgłoszenie, wyścig, limit statusu (na przykład „już w toku”).
410 Zniknął - usunięty punkt końcowy/zasób (zakończony).

Serwer

Błąd serwera wewnętrznego 500 - nieznany błąd; nie ujawniają szczegółów.
502 Bad Gateway - zwracany błąd/serwer proxy.
503 Serwis niedostępny - degradacja/planowane prace; Dodaj 'Retry-After'.
504 Brama Timeout.

💡 Zasada: pisać operacje na wątpliwość → 409 (konflikt) lub 503 (powtórzyć później), nie 200.

5) Przekaźnik i semantyka idempotencji

Nie można wycofać 400/ 401/403/404/422 (chyba że klient zmienił żądanie).
Można wycofać: 408/429/5xx/ 425/499/504 (z backoff + jitter).
Idempotencja: Dla 'POST', włącz 'Idempotence-Key' (UUIDv4).

W przypadku powtórnego konfliktu należy zwrócić 409 z napisem: "Użyj tego samego Idempotence-Key lub GET status" ".
Dodaj 'Idempotence-Replay: true' when zwracając zapisany wynik.

Przykład nagłówków na 429:

HTTP/1.1 429 Too Many Requests
Retry-After: 3
RateLimit-Limit: 50
RateLimit-Remaining: 0
RateLimit-Reset: 1730641030

6) Walidacja wejściowa: struktura błędu pola

W przypadku 400/422 należy użyć tablicy błędów w polu:
json
{
"type": "https://errors.example.com/validation",
"title": "Validation failed",
"status": 422,
"code": "VALIDATION_ERROR",
"trace_id": "01HX4...XYZ",
"errors": [
{"field": "amount", "rule": "min", "message": "Must be >= 10"},
{"field": "currency", "rule": "enum", "message": "Unsupported currency"}
]
}

7) Częściowe awarie (partia/częściowa awaria)

W punktach końcowych partii nie ukrywać błędów wewnątrz 200 bez struktury. Powrót 207 Multi-Status lub 200 z tablicą wyników, gdzie każde zadanie ma swój własny status:
json
{
"status": "partial",
"succeeded": 8,
"failed": 2,
"results": [
{"id": "op1", "status": 201},
{"id": "op2", "status": 422, "error": {"code":"VALIDATION_ERROR","detail":"..."}}
]
}

8) Paginacja i „puste” odpowiedzi

Pusta kolekcja - 200 s „pozycji: []”, nie 404.
Koniec strony - brakuje 'next _ page _ token'.
Nieprawidłowy token - kod 400 s: PAGINATION_CURSOR_INVALID'.


9) Haki internetowe: niezawodna dostawa

Podpisz zdarzenia (HMAC) i sprawdź przed przetworzeniem.
Odpowiedź na udane przetwarzanie wynosi 2xx (najlepiej 204).
Tymczasowe awarie odbiornika - 5xx; nadawca powtarza (wykładnicze backoff, jitter).
Deduplikowanie przez 'event _ id' i zapisywanie wyniku (konsument idempotent).
Nieprawidłowy ładunek - 400/422 nie próbuje ponownie.


10) Zgodność protokołu (gRPC/GraphQL)

gRPC → HTTP:
  • „NIEPRAWIDŁOWY ARGUMENT” → 400
  • „NIEAUTORYZOWANE” → 401
  • „POZWOLENIE _ ODMÓWIONE” → 403
  • „NIE ZNALEZIONO” → 404
  • „JUŻ _ ISTNIEJE” → 409
  • „NIEUDANY _ WARUNEK WSTĘPNY” → 412/422
  • „ZASOBY _ WYCZERPANE” → 429
  • „ABORTED” → 409
  • „NIEDOSTĘPNY” → 503
  • „TERMIN _ PRZEKROCZONY” → 504
GraphQL: zawsze 200 na warstwie transportowej jest ważne, ale umieścić błędy w 'błędach []' i duplikat w nagłówkach/rozszerzeniach:
json
{
"data": { "createPayment": null },
"errors": [{
"message": "Forbidden",
"extensions": { "code": "FORBIDDEN", "status": 403, "trace_id": "..." },
"path": ["createPayment"]
}]
}

Zaleca się użycie odpowiedniego kodu HTTP zamiast 200 dla błędów krytycznych.


11) Tytuły i wskazówki dla klientów

„Retry-After” - sekundy/data HTTP (429/503/425/408).
„Ostrzeżenie” - miękka degradacja lub deprekacja („199 - cecha X jest przygnębiona”).
"Deprecacja", "Zachód słońca", "Link: <...>; rel = „deprecation” - dla kontrolowanego wyłączenia.
'Problem-Type' (custom) - szybki błąd routingu na kliencie.
'X-Trace-Id'/' Correlation-Id' - łączy kłody/ślady.


12) Bezpieczeństwo wiadomości

Nie należy powtarzać tajemnic wejściowych (żetonów/podpisów) w organizmie odpowiedzi.
Maska PAN/PII („1234”).
Dla 401/403 - nie ujawniaj, który atrybut nie powiódł się.
Dla 404, zamiast „zasoby istnieją, ale nie twoje” - tylko 404.


13) Obserwowalność błędów

Metryka:
  • „http _ errors _ total {status, route, najemca}”
  • 'error _ classes _ total {code}' (przez 'code' z ciała)
  • udział 429, 5xx; „p95 ”/„ p99” opóźnienie dla błędnych odpowiedzi oddzielnie
  • „retry _ after _ seconds _ bucket” - histogram końcówek powtarzalności
Kłody/szlaki:
  • skojarzyć odpowiedź z 'trace _ id',' store code ',' type ',' status ',' trasa ',' lokator ', no PII.
Wpisy:
  • spike '5xx _ rate> X%' przy RPS> N;
  • wzrost o 429 na trasach krytycznych;
  • „timeout/504” zależności;
  • częste 409/idempotencja → znak wyścigów.

14) Przykłady

14. 1422 (walidacja działalności gospodarczej)

json
{
"type": "https://errors.example.com/payments/limit-exceeded",
"title": "Limit exceeded",
"status": 422,
"code": "PAYMENT_LIMIT_EXCEEDED",
"detail": "Daily withdrawal limit reached for KYC1.",
"hint": "Increase limits after KYC2 or try tomorrow.",
"trace_id": "01J5...XYZ"
}

14. 2409 (idempotencja)


HTTP/1.1 409 Conflict
Idempotency-Replay: true
json
{
"type": "https://errors.example.com/idempotency/replay",
"title": "Duplicate request",
"status": 409,
"code": "IDEMPOTENT_REPLAY",
"detail": "A request with the same Idempotency-Key was already processed.",
"hint": "Reuse the same Idempotency-Key and GET the operation status."
}

14. 3,429 (limity)

json
{
"type":"https://errors.example.com/rate/too-many-requests",
"title":"Too many requests",
"status":429,
"code":"RATE_LIMITED",
"detail":"Per-key rate limit exceeded.",
"hint":"Retry after the time specified in Retry-After header."
}

15) Antypattery

Zwróć 200 z tekstem błędu ciała.
Wymieszaj różne formaty błędów między usługami.
Rozwiń stos/SQL/nazwy tabeli/wewnętrzne adresy URL w 'detail'.
Użyj „wiadomości” zamiast stabilnego „kodu ”/„ typu”.
Zwrot 500 w przypadku wystąpienia oczekiwanego błędu biznesowego (na przykład „saldo jest niewystarczające”).
Niespójna semantyka pomiędzy REST/GraphQL/gRPC.


16) Szczegóły dotyczące iGaming/Finance

Jasne kody KYC/AML/sankcji: „KYC _ REQUIRED”, „KYC _ REVIEW”, „AML _ LOCK”, „SANKCJA _ BLOKOWANA”.
Ograniczenia jurysdykcyjne: 451 z bezpiecznym brzmieniem bez notowania.
Operacje monetarne: 409/423 dla konkurencji i zamków, „wskazówka” z oknem redo.
Limit gracza niezmiennie: Użyj 422 do odpowiedzialnych naruszeń płatności.
Audyt: niezmienne dzienniki rozwiązań (kod, czas, aktor, trace_id).


17) Lista kontrolna gotowości Prod

  • Jednolity system błędów JSON, stabilny „typ ”/„ kod”.
  • Odwzorowanie HTTP i GRPC/GraphQL jest spójne i udokumentowane.
  • Semantyka retrasy + „Retry-After”; idempotencja do pisania.
  • PII/tajne maskowanie; 404 ukryć zasoby.
  • Wskaźniki błędów i alarmów; korelacja z 'trace _ id'.
  • Polityka deprecjacji: „Deprecacja”, „Zachód słońca”, „Link”.
  • Testy: negatywne/fuzz, konflikt wersji, spadek zależności, podwójne zgłoszenie.
  • Przewodnik po kliencie: Przykłady cofania i przetwarzanie 409/422/429/5xx.

18) TL; DR

Ujednolicenie pojedynczego formatu błędu JSON z 'type '/' code '/' trace _ id', użycie prawidłowych kodów HTTP, rozróżnienie między walidacją (400/422), prawami (401/403/404), konfliktami/idempotencją (409) i limitami (429). Należy podać wyraźne 'Retry-After' i 'hint', dane wrażliwe na maskę, błędy dziennika z 'trace _ id' i skonstruować wpisy o 5xx/429/p99.

Contact

Skontaktuj się z nami

Napisz do nas w każdej sprawie — pytania, wsparcie, konsultacje.Zawsze jesteśmy gotowi pomóc!

Rozpocznij integrację

Email jest wymagany. Telegram lub WhatsApp są opcjonalne.

Twoje imię opcjonalne
Email opcjonalne
Temat opcjonalne
Wiadomość opcjonalne
Telegram opcjonalne
@
Jeśli podasz Telegram — odpowiemy także tam, oprócz emaila.
WhatsApp opcjonalne
Format: kod kraju i numer (np. +48XXXXXXXXX).

Klikając przycisk, wyrażasz zgodę na przetwarzanie swoich danych.