Dwa eventy odebrane w zbyt krótkim czasie.

0

Hej, mam taki case, że reaguję na dwa eventy, załóżmy A i B i eventy te dochodzą po sobie w przeciągu 300-400 milisekund.

Na event A pobieram encję, dokonuję zmian i zapisuję. Na event B pobieram tą samą encję (z tym samym id) i dokonuję innych zmian. Problem w tym, że w przetwarzaniu eventu B muszę znać zmiany z eventu A, a jak debuguję to to jeszcze tych zmian tam nie widać.

Brokker to RabbitMQ + standardowo Spring na Tomcacie.

Wstawianie na pałe delaya do obsługi eventu B wydaje się średnie. Co się robi w takich momentach?

9

Coś średnio tu te eventy pasują w takim razie. A co jak event A w ogóle zaginie, albo przyjdzie dużo później albo przynajmniej później niż B? Boję się w ogóle pytać co byś zrobił jakby aplikacja miała więcej niz 1 node.
Jeśli masz takie powiązanie między eventami to czemu to nie jest 1 event? Albo musisz sobie zrobić jakiś stateful handler tych eventów, który będzie synchronizować ten odbiór i wykonywać akcje dopiero jak przyjdą oba.

9

Jak wyżej - być może to jest jeden event, być moze używasz złej architektury.

W architekturze eventowej - musisz być przygotowany, że eventy dojdą w zupełnie dowolnej kolejności( czasem są pewne gwarantowane "zależności" - ale w ogólności, mając kolejki perzystentne przeważnie nie możesz na zależnościach czasowych polegać).
To jakby podstawa takiej architektury.

Najpierw dostajesz event o wycofaniu zamówienia, a potem dopiero to zamówienie - normalka.
Jak sobie z tym radzić? są różne metody:

Napisac tak kod obsługi B tak, że jeśli nie ma jeszcze A - to zapisze co trzeba zrobić jak przyjdzie A i handler A to zrobi.
(w przypadku wyżej tabelka "cancelled orders" - do której zaglądamy jak przychodzi event - zamówienie złożone).

Ewentualnie jeśli teraz eventu nie da się przetworzyć to wstaw na nowo na koniec kolejki - to drugie rozwiązanie zwykle szybko kończy się jakimś never ending zapętleniem (ale temu też można zapobiec).

Wszelkie pomysły z delayem w event handlerze itp NIE BĘDĄ DZIAŁAĆ.

0

Jeżeli eventy mają realizować jakiś biznes to można sprawdzać status encji np. czy aktualnie czeka na event B czy na event A.

0

W takiej sytuacji, po pierwsze trzeba https://www.rabbitmq.com/tutorials/tutorial-six-python.html. Nie jest to niestety ładne rozwiązanie, chodzi tutaj tylko o synchronizację i z obu stron jest coś wrzucane na kolejki B możesz dopiero wysłać jak dostałeś response z odpowiednymi danymi na kolejke. Alternatywa https://www.rabbitmq.com/direct-reply-to.html. Jeżeli chodzi o widoczność zmian załatwia się to po prostu transakcjami i lockami

0

Nie ja projektowałem mikroserwis, który rzuca te eventy ;p

Mamy w systemie wersjonowanie eventów, aby nie przetwarzać jakiś zagubionych albo zduplikowanych. Wersja eventu jest wstawiana na podstawie wersji encji.

W moim przykładzie chodzi o dwa eventy:

order.accepted oraz oraz.completed.

Flow wygląda tak:

  1. User klika w apce, że przekazał przedmiot odbiorcy
  2. Idzie request do backendu (mikroserwisu od zamówień), zamówienie zmienia status i emituje order.accepted
  3. Z mikroserwisu zamówień idzie request do mikroserwisu z płatnościami i jak wszystko pójdzie ok to order zmienia status na completed i emituje order.completed.
  4. Response wraca na front

Punkt 3 trwa generalnie szybko, więc czas między order.accepted i order.completed jest bardzo krótki.

Jestem przygotowany, że te dwa eventy przyjdą w odwrotnej kolejności czy najpierw order.completed a potem .accepted ale to nie rozwiązuje tego problemu zbyt krótkiego czasu między nimi.
Ba! Gdyby najpierw przyszło order.completed a potem po dłuższym czasie order.accepted (czyli odwrotnie ale z dłuższym odstępem czasu między nimi) to by mi to zadziałało.

Dzięki za odp.

2

No to wersjonowanie na poziomie encji, np. optimistic locking. Jak będziesz miał race condition, to przetwarzanie drugiego eventu zostanie odbite przez bazę i będzie musiało zostać ponowione po czasie zależnym od tego jaki tam masz ustawiony retry backoff. Dzięki optimistic locking nie masz... locków.

1 użytkowników online, w tym zalogowanych: 0, gości: 1