Załóżmy że mam aplikacje która rozrosła się w dość spory sposób, i czasami występują hazardy przy płatnościach.
Nasza aplikacja wysyła requesty do zewnętrznego API od płatności.
Każda płatność (model Payment) zawiera pole line_item_id i należy do modelu Service.
line_item_id jest unikatowe.
Mam znaleźć lub utworzyć obiekt poprzez unikatowy klucz i zaktualizować go bez budowania nadmiarowych konstrukcji.
Mamy klasę AR
class Payment < ActiveRecord::Base
belongs_to :service
end
Aplikacja nie posiada obecnie żadnego mechanizmu który powodował by że była by odporna na hazardy.
Rozrosła się do stopnia w którym wiele procesów wysyła request do zewnętrznego API i można wiele requestów może uzyskać dostęp do tego samej płatności - trzeba zaprojektować rozwiązanie które spowoduje że nie będą występować zduplikowane obiekty od płatności w całym systemie.
Jako DB jest używany PostgreSQL i można wykorzystać jego feature do pomocy.
Wiele procesów/wątków może uzyskać dostęp do tej samego samego obiektu płatności.
Jeśli 2 lub więcej procesów chce zaktualizować płatność, powinna się zrobić taka jakby kolejka i lock.
Jeden proces robi update, drugi czeka -> Pierwszy proces zakończył update, drugi go zaczyna itd
Jeśli płatność nie istnieje to pierwszy proces ją tworzy, a inne procesy na nią czekają.
Jak narazie mam 1 pomysł na zrobienie czegoś takiego (delayed job) oraz metoda typu
[code=ruby]Payment.update_with(:line_item_id => line_item_id, :service_id => service_id) do |payment|
update
end[/code]
Da się to jakoś lepiej zrobić?
PS Ten ‘task’ wydawał mi się dość ambitny, dlatego postanowiłem złapać nieco perspektywy od bardziej doświadczonych osób.