vote_service.rb 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. # frozen_string_literal: true
  2. class VoteService < BaseService
  3. include Authorization
  4. include Payloadable
  5. include Redisable
  6. include Lockable
  7. def call(account, poll, choices)
  8. return if choices.empty?
  9. authorize_with account, poll, :vote?
  10. @account = account
  11. @poll = poll
  12. @choices = choices
  13. @votes = []
  14. already_voted = true
  15. with_redis_lock("vote:#{@poll.id}:#{@account.id}") do
  16. already_voted = @poll.votes.exists?(account: @account)
  17. ApplicationRecord.transaction do
  18. @choices.each do |choice|
  19. @votes << @poll.votes.create!(account: @account, choice: Integer(choice))
  20. end
  21. end
  22. end
  23. increment_voters_count! unless already_voted
  24. ActivityTracker.increment('activity:interactions')
  25. if @poll.account.local?
  26. distribute_poll!
  27. else
  28. deliver_votes!
  29. queue_final_poll_check!
  30. end
  31. end
  32. private
  33. def distribute_poll!
  34. return if @poll.hide_totals?
  35. ActivityPub::DistributePollUpdateWorker.perform_in(3.minutes, @poll.status.id)
  36. end
  37. def queue_final_poll_check!
  38. return unless @poll.expires?
  39. PollExpirationNotifyWorker.perform_at(@poll.expires_at + 5.minutes, @poll.id)
  40. end
  41. def deliver_votes!
  42. @votes.each do |vote|
  43. ActivityPub::DeliveryWorker.perform_async(
  44. build_json(vote),
  45. @account.id,
  46. @poll.account.inbox_url
  47. )
  48. end
  49. end
  50. def build_json(vote)
  51. Oj.dump(serialize_payload(vote, ActivityPub::VoteSerializer))
  52. end
  53. def increment_voters_count!
  54. unless @poll.voters_count.nil?
  55. @poll.voters_count = @poll.voters_count + 1
  56. @poll.save
  57. end
  58. rescue ActiveRecord::StaleObjectError
  59. @poll.reload
  60. retry
  61. end
  62. end