Sha256: aa65584fd9248c76e16782bc8951cd48e8b49a9d580c734b11c116f9c6fa2011

Contents?: true

Size: 1.94 KB

Versions: 2

Compression:

Stored size: 1.94 KB

Contents

module Counter::Verifyable
  extend ActiveSupport::Concern

  def correct?
    # We can't verify these values
    return true if definition.global?

    old_value, new_value = verify
    old_value == new_value
  end

  def correct!
    # We can't verify these values
    return true if definition.global?

    old_value, new_value = verify

    requires_recalculation = old_value != new_value
    update! value: new_value if requires_recalculation

    !requires_recalculation
  end

  def verify
    if definition.calculated?
      [calculate, value]
    else
      [count_by_sql, value]
    end
  end

  class_methods do
    # on_error: raise, log, correct
    # Returns the number of incorrect counters
    def sample_and_verify scope: -> { all }, samples: 1000, verbose: true, on_error: :raise
      incorrect_counters = 0

      counters = Counter::Value.merge(scope)
      counter_range = counters.minimum(:id)..counters.maximum(:id)

      samples.times do
        random_id = rand(counter_range)
        counter = counters.where("id >= ?", random_id).limit(1).first
        next if counter.nil?

        if counter.definition.global? || counter.definition.calculated?
          puts "➡️ Skipping counter #{counter.name} (#{counter.id})" if verbose
          next
        end

        if counter.correct?
          puts "✅ Counter #{counter.id} is correct" if verbose
        else
          incorrect_counters += 1
          message = "❌ counter #{counter.name} (#{counter.id}) for #{counter.parent_type}##{counter.parent_id} has incorrect counter value. Expected #{counter.value} but got #{counter.count_by_sql}"

          case on_error
          when :raise then raise Counter::Error.new(message)
          when :log then Rails.logger.error message
          when :correct
            counter.correct!
            puts "🔧 Corrected counter #{counter.id}" if verbose
          end
        end
        sleep 0.1
      end
      incorrect_counters
    end
  end
end

Version data entries

2 entries across 2 versions & 1 rubygems

Version Path
counterwise-0.1.5 app/models/concerns/counter/verifyable.rb
counterwise-0.1.4 app/models/concerns/counter/verifyable.rb