1class UpdateSignatureCountsJob < ApplicationJob
 
2  queue_as :highest_priority
 
3
 
4  delegate :update_signature_counts, to: :Site
 
5  delegate :signature_count_updated_at, to: :Site
 
6  delegate :signature_count_interval, to: :Site
 
7  delegate :signature_count_updated_at!, to: :Site
 
8  delegate :petition_ids_signed_since, to: :Signature
 
 9
 
10  rescue_from StandardError do |exception|
 
11    log_exception(exception)
 
12    retry_job(wait: signature_count_interval)
 
13  end
 
  • DuplicateMethodCall - calls 'petition.last_signed_at' 2 times » reek
  • TooManyStatements - has approx 14 statements » reek
  • Complexity 8 » saikuro
  • Method "perform" has 42 lines. It should have 20 or less. » roodi
15  def perform(now = current_time)
 
16    # Exit if updating signature counts is disabled
 
17    return unless update_signature_counts
 
 
19    time = now.in_time_zone
 
20    signature_count_at = signature_count_interval.seconds.ago(time)
 
 
22    # Exit if the signature counts have been updated since this job was scheduled
 
23    return unless signature_count_updated_at < signature_count_at
 
  • Block cyclomatic complexity is 6. It should be 4 or less. » roodi
25    petitions.each do |petition|
 
26      # Skip this petition if it's been updated since this job was scheduled
 
27      next if petition.last_signed_at? && petition.last_signed_at > signature_count_at
 
 
29      # Check to see if the signature count is being reset
 
30      if petition.signature_count_reset_at?
 
31        if petition.signature_count_reset_at < 5.minutes.ago
 
32          # Something's seriously wrong if a petition is taking
 
33          # more than 5 minutes to reset its signature count
 
34          message = "Petition #{petition.id} has been resetting its count for more than 5 minutes"
 
35          Appsignal.send_exception(RuntimeError.new(message))
 
36        end
 
 
38        # Skip this petition as the updates will conflict
 
39        next
 
40      end
 
 
42      # Save the current last_signed_at for the start of the journal window
 
43      last_signed_at = petition.last_signed_at
 
 
45      # Don't update the journals unless we have updated the signature count
 
46      # This prevents the journals getting multiple updates before the creator's
 
47      # signature is added to the count which may not be done immediately as the
 
48      # main signature count window lags by `signature_count_interval` seconds
 
49      # to prevent race conditions with validated_at timestamps created in Ruby
 
50      if petition.increment_signature_count!(signature_count_at)
 
51        ConstituencyPetitionJournal.increment_signature_counts_for(petition, last_signed_at)
 
52        CountryPetitionJournal.increment_signature_counts_for(petition, last_signed_at)
 
53      end
 
54    end
 
 
56    signature_count_updated_at!(signature_count_at)
 
57    reschedule_job(scheduled_time(time))
 
58  end
 
 
60  private
 
  • UtilityFunction - doesn't depend on instance state (maybe move it to another class?) » reek
  • Complexity 1 » saikuro
62  def current_time
 
63    Time.current.change(usec: 0).iso8601
 
64  end
 
  • Complexity 1 » saikuro
66  def log_exception(exception)
 
67    logger.info(log_message(exception))
 
68  end
 
  • Complexity 1 » saikuro
70  def log_message(exception)
 
71    "#{exception.class.name} while running #{self.class.name}"
 
72  end
 
  • Complexity 1 » saikuro
74  def petition_ids
 
75    petition_ids_signed_since(signature_count_updated_at)
 
76  end
 
  • Complexity 1 » saikuro
78  def petitions
 
79    Petition.where(id: petition_ids)
 
80  end
 
  • Complexity 1 » saikuro
82  def reschedule_job(time)
 
83    self.class.set(wait_until: time).perform_later(time.iso8601)
 
84  end
 
  • Complexity 1 » saikuro
86  def scheduled_time(now)
 
87    signature_count_interval.seconds.since(now)
 
88  end
 
89end