diff options
Diffstat (limited to 'app/services/vote_service.rb')
-rw-r--r-- | app/services/vote_service.rb | 32 |
1 files changed, 29 insertions, 3 deletions
diff --git a/app/services/vote_service.rb b/app/services/vote_service.rb index 0eeb8fd56..cb7dce6e8 100644 --- a/app/services/vote_service.rb +++ b/app/services/vote_service.rb @@ -12,12 +12,24 @@ class VoteService < BaseService @choices = choices @votes = [] - ApplicationRecord.transaction do - @choices.each do |choice| - @votes << @poll.votes.create!(account: @account, choice: choice) + already_voted = true + + RedisLock.acquire(lock_options) do |lock| + if lock.acquired? + already_voted = @poll.votes.where(account: @account).exists? + + ApplicationRecord.transaction do + @choices.each do |choice| + @votes << @poll.votes.create!(account: @account, choice: choice) + end + end + else + raise Mastodon::RaceConditionError end end + increment_voters_count! unless already_voted + ActivityTracker.increment('activity:interactions') if @poll.account.local? @@ -53,4 +65,18 @@ class VoteService < BaseService def build_json(vote) Oj.dump(serialize_payload(vote, ActivityPub::VoteSerializer)) end + + def increment_voters_count! + unless @poll.voters_count.nil? + @poll.voters_count = @poll.voters_count + 1 + @poll.save + end + rescue ActiveRecord::StaleObjectError + @poll.reload + retry + end + + def lock_options + { redis: Redis.current, key: "vote:#{@poll.id}:#{@account.id}" } + end end |