Aktywne Wpisy
dexterpol +31
W końcu dzisiaj wyplatka po podwyżce wleciala, lvl 26, a jak tam u was? Dalej jebnie za 4k u fabryce smrodu? ( ͡° ͜ʖ ͡°)#pracbaza #praca #korposwiat
AXSIS +12
Mirki co tu się dzieje to ja nie ogarniam. Ćwiczę sobie pisanie na apkach randkowych i zaproponowałem takiej naprawdę ślicznej Julce 20lvl kino, a ta mi głosówkę wysłała, że chętnie i w ogóle lubi takie filmy itp.
Miała taki ładny głosik jak z jakiejś baśni... Gdyby nie niska pewność siebie to bym się pofatygował te 100km do niej, a tak to trzeba usunąć parę. Już nigdy takiej nie spotkam pewnie, ehh...
Teraz
Miała taki ładny głosik jak z jakiejś baśni... Gdyby nie niska pewność siebie to bym się pofatygował te 100km do niej, a tak to trzeba usunąć parę. Już nigdy takiej nie spotkam pewnie, ehh...
Teraz
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.