Scenariusz edukacyjny inspirowany praktyką. To przypadek modelowy, a nie opis potwierdzonego incydentu.
Sytuacja
Serwis zapisuje zamówienie i w tym samym żądaniu wywołuje usługę pocztową. Zamówienie otrzymuje numer i transakcja w bazie zostaje zatwierdzona. E-mail zwraca timeout, więc API odpowiada błędem 500. Użytkownik widzi polecenie ponowienia operacji, chociaż pierwsze zamówienie już istnieje. W tym procesie wiadomość jest informacyjna i nie stanowi warunku przyjęcia zamówienia.
Gdzie powstaje antywzorzec
Pomocniczy skutek techniczny steruje komunikatem o wyniku biznesowym. System nie rozróżnia: „zamówienie przyjęte” oraz „potwierdzenie oczekuje na wysłanie”. W efekcie retry obejmuje zbyt duży zakres. Próbuje ponownie utworzyć zamówienie, zamiast naprawić wysyłkę.
Objawy
- endpoint zwraca błąd po zatwierdzeniu głównej transakcji;
- użytkownik nie otrzymuje numeru istniejącego zamówienia i ma nacisnąć „spróbuj ponownie”;
- wysyłka e-maila odbywa się synchronicznie bez osobnego stanu i właściciela retry;
- monitoring nie odróżnia błędu przyjęcia zamówienia od błędu powiadomienia;
- zespół proponuje kolejkę, ale nie wyjaśnia, co dzieje się przy awarii między commitem bazy a publikacją komunikatu.
Konsekwencje
Mogą powstać duplikaty zamówień, a obsługa klienta widzi sprzeczne komunikaty. Zwiększanie liczby retry pogarsza sytuację: ponawiany jest niewłaściwy fragment procesu. Zwykła publikacja do kolejki po zapisie bazy także może zgubić zadanie, jeśli proces zakończy się pomiędzy tymi dwoma zapisami.
Lepsza decyzja
- Ustal, kiedy operacja biznesowa jest przyjęta, i zwracaj jej prawdziwy wynik wraz z identyfikatorem.
- Zapisz zamiar wysłania powiadomienia trwale. Rekord zadania w tej samej transakcji lub transactional outbox zamyka lukę pomiędzy bazą i brokerem.
- Ponawiaj wyłącznie wysyłkę. Używaj stabilnego identyfikatora, ograniczonej liczby prób, backoffu oraz deduplikacji lub idempotencji konsumenta.
- Pokaż stan operacyjny: oczekujące zadania, wiek najstarszego, liczbę prób i trwałe błędy. Po wyczerpaniu prób skieruj zadanie do obsługi, nie do zapomnienia.
- Sprawdź awarię poczty, przerwanie procesu tuż po commicie oraz podwójną publikację. Oczekiwany wynik to jedno zamówienie i kontrolowane dostarczenie powiadomienia.
Granica
Jeżeli dostarczenie komunikatu jest warunkiem prawnym lub biznesowym przyjęcia operacji, trzeba zaprojektować inny kontrakt. Nie można jednak dopisywać takiego warunku dopiero dlatego, że wygodniej było wykonać dwa wywołania w jednym wątku.
Ponawiaj nieudany skutek, nie zakończoną operację biznesową.
Porozmawiajmy o tym artykule
Podziel się uwagą lub zanonimizowanym przykładem. Komentarze sprawdza AI przed publikacją. Niejednoznaczne przypadki trafiają do moderatora.