Kontekst:
SMSApi uderza pod /przykladowy/url
z rezultatem odpowiedzi na SMS. Ten SMS jest wysyłany do kilku ludzi, którzy mają odpowiedzieć TAK lub NIE i w myśl zasady kto pierwszy ten lepszy coś tam się dzieje. Oczywiście każda kolejna osoba nie może nadpisać tego co się wykona, gdy pierwsza osoba odpowie TAK. Każda kolejna osoba jest po prostu ignorowana.
Problem:
Do tej pory ktoś to tak zaimplementował, że przetwarzanie całej logiki biznesowej (która czasami może trochę pomielić, w tym wypadku juz ponad 1 sek to długo) upchnął do tej samej akcji, która przechwytuje response od SMSApi. Problem pojawił się ostatnio, jak 3 osoby odpowiedziały na sms w przeciągu 5 sek i ostatnia osoba stała się tak jakby pierwszą.
Do tej pory cała logika biznesowa nie była nawet owinięta transakcją. Sprawdzenie, czy ktoś jest pierwszy odbywa się na samej górze, a aktualizacja stanu na samym końcu, więc jak w międzyczasie ktoś się wepchnie, to oczywiście nadpisze poprzednika.
Wcześniej nie miałem takich problemów, więc nie bardzo wiem jakie rozwiązanie wybrać. Widzę dwa:
-
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
- to chyba załatwi sprawę, bo każde kolejne query się zawiesi do momentu aż pierwszy request się nie przemieli. Pytanie jakie to może nieść konsekwencje. Rozumiem, że zawieszę tylko te zapytania, które dotykają tych samych rekordów co moja transakcja, a nie np. całą tabelę z zamówieniami? -
Zamiast procesować to w momencie, w którym SMSApi do nas uderza, to w tym miejscu wrzuce to tylko do jakiejś tabeli pośredniej. Dodam cron'a, który będzie sobie chodził co 5min i przetwarzał rekordy pojedynczo i wtedy nie będzie problemu, bo weźmie kolejny dopiero jak skończy poprzedni.