Śmiga sobie nginx a pod nim kilka mongreli w clusterze.
Jest sobie user na którego można głosować za pomocą klasy UserVotes (klasa zlicza głosy oddane przez jednego usera na drugiego- raz dziennie każdy może na każdego głosować)
Jest sobie kolejna klas UserContestVotes, która to z kolei jest w relacji z konkursem i zawiera licznik głosów wszystkich userów na tego jednego, czyli za każdym wywołaniem głosowania zwiększa się licznuk w UserVotes i UserContestVotes.
Problem:
— Co stanie się jeśli w jednym momencie dwóch różnych userów zagłosuje na tego jednego? Mamy kilka mongreli więc zostaną obsłużeni równolegle.
UserVotes, na pewno będą spójne, ale co stanie się z licznikiem w UserContestVotes, skoro głosujący pobrali identyczna liczbę głosów ogólnych (np. 300) i zwiększając go o jeden, każdy z nich wyśle informacje do db, że nowa wartość to 301.
Użyj transakcji jeśli upierasz się przy osobnych modelach. Jak zainwestujesz w counter cache jak radzi sevos to ich aktualizacja zostanie automatycznie zamknięta w transakcji.
class Contest < ActiveRecord::Base
has_many :users
has_many :user_contests
end[/code]
Więc counter_cache w moim przypadku w czystej formie się raczej nie sprawdzi, ponieważ każdy użytkownik, może zagłosować kilka razy, co uaktualni licznik w Vote. A counter_cache zwróciłby nam w takim wypadku o ile dobrze rozumiem liczbę głosujących. W związku z czym licznik globalny user jest w UserContest i Optimistic Locking to rozwiązanie, którego szukałem. Tranzakcja jest też opcją, ale raczej nadmiarową w tym przypadku.