Aktywne Wpisy
Sylvio19 +86
Nigdy nie zapomne jak wszedłem do pokoju mojej siostry na jej osiemnastce i zobaczyłem ją na kolanach robiącą gałe najlepszemu kumplowi swojego chłopaka. Powiedziałem tylko: sorry i się wycofałem. Schodząc ze schodów widziałem jak Bartek (jej chłopak) je krokieta z barszczem i sie uśmiecha bo już miał ostrą faze. Nigdy mu o tym nie powiedziałem. W zeszłym roku wzięli ślub. #zwiazki #seks #rozowepaski #logikarozowychpaskow
iErdo +243
No więc skiepściłem xD Czemu? Bo jestem głupi. Generalnie ładnie to sobie wymyśliłem, ale nie wziąłem pod uwagę wody za Zimorodkiem, i to co w wizjerze wyglądało fajnie, na kompie wyglądało okropnie, odbicia wody wzmacniają efekt aberracji chromatycznej i dziwnego rozszczepiania światła, więc Zimorodek był w złym stanie. ALE żeby dowieźć, to postarałem się coś z niego wykrzesać, musiałem zasymulować inne tło. Ogólnie normalnie bym nie edytował tego zdjęcia i je wyrzucił.
poproszę o gotowe rozwiązanie albo link do materiału z którego mógłbym skorzystać. Mam następujący problem:
Jest aplikacja napisana w #php #symfony która to publikuje eventy w kolejce #rabbitmq. Są też 2 consumery, które to konsumują te eventy. Problem jest taki, że w pewnym miejscu mam race condition. Są opublikowane rożne eventy, które podczas konsumpcji tworzą lub aktualizują rekord w bazie danych. Problem jest w tym, że konsumpcja może nastąpić w bardzo krótkim czasie przez co 2 consumery będą próbowały stworzyć rekord w bazie danych. Dodałem kod, który sprawdza czy rekord istnieje w bazie danych czy nie, a następnie rzucam wyjątek, żeby wykonała się aktualizacja rekordu, ale czasami różnice są takie minimalne, że tego nie wystarcza.
Poproszę o odpowiedź inną niż - zostaw sobie jednego consumera i problem rozwiązany - to nie zadziała, bo czasami ktoś chce wygenerować ogromny raport, np. za pół roku czy za rok i consumer będzie zablokowany przez cały czas generowania raportu, więc reszta systemu nie będzie działać poprawnie, a z dwoma consumerami można sobie pozwolić na blokadę jednego przez dłuższy czas, ponieważ drugi będzie dalej obsługiwał eventy z kolejki.
Myślałem nad wykorzystaniem cache (redis, memcached czy coś innego) i umieszczenie tam flagi - obsługa tego rekordu jest zablokowana w tym momencie, spróbuj później, ale nie wiem czy takie rzeczy się stosuje czy jest na to lepsze rozwiązanie.
#webdev #programowanie
https://symfony.com/doc/current/components/lock.html
Może sprawdź jeszcze czy nie ograsz tego w middleware.
https://symfony.com/doc/current/messenger.html#middleware-for-doctrine
Dziękuję.
Problem z doctrine jest następujący - błąd
The EntityManager is closed.
Jest to spowodowane błędem po stronie Mysql - dziś wreszcie udało mi się namierzyć co się dzieje.Otóż to wygląda tak:
1. z powodu wyżej opisanej sytuacji pierwszy consumer tworzy rekord w bazie danych
2. drugi consumer sprawdza czy rekord istnieje - a rekord nie
Na race condition aktualizacji może pomóc transakcja +
SELECT FOR UPDATE
, żeby zrobić locka na wierszu dopóki nie skończysz swojej operacji update'u.Co do race condition przy tworzeniu wierszy, to już musiałbyś dokładnie napisać co tam
Tutaj jest klasa o której mowa: https://pastebin.com/Z9a7DVB6
dałem tutaj funkcję rekurencyjną, żeby w razie złapania wyjątku kod wykonał się jeszcze raz, ale no tak jak pisałem poprzednio - tego nie wystarcza i nadal mam mnóstwo błędów z powodu EntityManager is closed.
Zamiast tego zrób albo tak jak pisałem - transakcja, select for update, update/insert, koniec transakcji. Albo jeśli jesteś w stanie to zrobić w sposób idempotentny to po prostu
INSERT ... ON DUPLICATE KEY UPDATE
alboREPLACE
.Ewentualnie zapytaj po prostu jakiegoś seniora w
nie wiem czy dobrze zrozumialem problem, ale to co mozesz uzyc to UPSERT, a jak musisz cos sprawdzic przed to optimistic locking + retry
overengineering
@mariecziek:
@mariecziek: Już kilka lat nie siedzę w symfony, ale kiedyś miałem podobny problem. Doctrine po utworzeniu encji i dodaniu jej do em nie zapisuje tego od razu do bazy, ale możesz to wymuśić bodajrze przez flush (czy jakoś tak). To powinno pozwolić zmniejszyć ilość konfliktów w tym miejscu.