21
1
Fork 0
mirror of https://github.com/Evolix/chexpire.git synced 2024-05-05 10:15:09 +02:00

Checks processor refactoring for more flexibility

This commit is contained in:
Colin Darie 2018-07-02 14:25:35 +02:00
parent 47d8641a66
commit db4e7d42b2
No known key found for this signature in database
GPG key ID: 4FB865FDBCA4BCC4
9 changed files with 120 additions and 50 deletions

View file

@ -0,0 +1,25 @@
class CheckDomainProcessor
include CheckProcessor
protected
def configuration_key
"checks_domain"
end
def resolvers
%i[
resolve_last_run_failed
resolve_expire_short_term
resolve_expire_long_term
resolve_unknown_expiry
]
end
def scope
base_scope.domain
end
def process(check)
WhoisSyncJob.perform_now(check.id)
end
end

View file

@ -1,17 +1,12 @@
class CheckProcessor module CheckProcessor
attr_reader :configuration attr_reader :configuration
def initialize(configuration = nil) def initialize(configuration = nil)
@configuration = configuration || default_configuration @configuration = configuration || default_configuration
end end
def sync_dates # rubocop:disable Metrics/MethodLength def sync_dates
%i[ resolvers.each do |resolver|
resolve_last_run_failed
resolve_expire_short_term
resolve_expire_long_term
resolve_unknown_expiry
].each do |resolver|
public_send(resolver).find_each(batch_size: 100).each do |check| public_send(resolver).find_each(batch_size: 100).each do |check|
process(check) process(check)
@ -20,6 +15,12 @@ class CheckProcessor
end end
end end
# :nocov:
def resolvers
fail NotImplementedError, "#{self.class.name} did not implemented method #{__callee__}"
end
# :nocov:
def resolve_last_run_failed def resolve_last_run_failed
scope.last_run_failed scope.last_run_failed
end end
@ -41,25 +42,32 @@ class CheckProcessor
scope.where("domain_expires_at IS NULL") scope.where("domain_expires_at IS NULL")
end end
private protected
def scope def base_scope
Check Check
.active .active
.where("last_run_at IS NULL OR last_run_at < DATE_SUB(NOW(), INTERVAL 12 HOUR)") .where("last_run_at IS NULL OR last_run_at < DATE_SUB(NOW(), INTERVAL 12 HOUR)")
end end
def process(check) # :nocov:
case check.kind.to_sym def scope
when :domain fail NotImplementedError, "#{self.class.name} did not implemented method #{__callee__}"
WhoisSyncJob.perform_now(check.id)
else
fail ArgumentError, "Unsupported check kind `#{check.kind}`"
end
end end
def process(check)
fail NotImplementedError, "#{self.class.name} did not implemented method #{__callee__}"
end
def configuration_key
fail NotImplementedError, "#{self.class.name} did not implemented method #{__callee__}"
end
# :nocov:
private
def default_configuration def default_configuration
config = Rails.configuration.chexpire.fetch("checks", {}) config = Rails.configuration.chexpire.fetch(configuration_key, {})
OpenStruct.new( OpenStruct.new(
interval: config.fetch("interval") { 0.00 }, interval: config.fetch("interval") { 0.00 },

View file

@ -3,7 +3,7 @@ default: &default
notifier: notifier:
interval: 0.00 interval: 0.00
failure_days: 3 failure_days: 3
checks: checks_domain:
interval: 0.5 interval: 0.5
long_term: 60 long_term: 60
long_term_frequency: 10 long_term_frequency: 10

View file

@ -4,7 +4,7 @@ test:
notifier: notifier:
interval: 0.00 interval: 0.00
failure_days: 3 failure_days: 3
checks: checks_domain:
interval: 0.00 interval: 0.00
long_term: 60 long_term: 60
long_term_frequency: 10 long_term_frequency: 10

View file

@ -19,7 +19,7 @@ set :output, standard: "log/cron.log"
# Learn more: http://github.com/javan/whenever # Learn more: http://github.com/javan/whenever
every 1.day, at: '4:30 am', roles: [:app] do every 1.day, at: '4:30 am', roles: [:app] do
rake "checks:sync_dates" rake "checks:sync_dates:all"
end end
every 1.day, at: '10:30 am', roles: [:app] do every 1.day, at: '10:30 am', roles: [:app] do

View file

@ -1,7 +1,11 @@
namespace :checks do namespace :checks do
desc "Refresh expiry dates for checks" namespace :sync_dates do
task sync_dates: :environment do task all: [:domain]
process = CheckProcessor.new
process.sync_dates desc "Refresh domains expiry dates"
task domain: :environment do
process = CheckDomainProcessor.new
process.sync_dates
end
end end
end end

View file

@ -44,6 +44,10 @@ FactoryBot.define do
kind :domain kind :domain
end end
trait :ssl do
kind :ssl
end
trait :nil_dates do trait :nil_dates do
domain_created_at nil domain_created_at nil
domain_updated_at nil domain_updated_at nil

View file

@ -0,0 +1,34 @@
require "test_helper"
class CheckDomainProcessorTest < ActiveSupport::TestCase
setup do
@processor = CheckDomainProcessor.new
end
test "process WhoisSyncJob for domain checks" do
domain = "domain.fr"
check = create(:check, :domain, :nil_dates, domain: domain)
mock_system_command("whois", domain, stdout: file_fixture("whois/domain.fr.txt").read) do
@processor.send(:process, check)
end
check.reload
assert_equal Time.new(2019, 2, 17, 0, 0, 0, 0), check.domain_expires_at
end
test "scope concerns only checks of kind 'domain'" do
domains = create_list(:check, 2, :domain)
create_list(:check, 2, :ssl)
assert_equal domains, @processor.send(:scope)
end
test "resolvers returns an array of methods returning a scope" do
assert_not_empty @processor.send(:resolvers)
@processor.send(:resolvers).each do |method|
assert_kind_of ActiveRecord::Relation, @processor.public_send(method)
end
end
end

View file

@ -1,31 +1,26 @@
require "test_helper" require "test_helper"
class CheckDummyProcessor
include CheckProcessor
def scope
base_scope
end
def configuration_key
"checks_dummy"
end
def resolvers
%i[
resolve_expire_short_term
resolve_expire_long_term
]
end
end
class CheckProcessorTest < ActiveSupport::TestCase class CheckProcessorTest < ActiveSupport::TestCase
setup do setup do
@processor = CheckProcessor.new @processor = CheckDummyProcessor.new
end
test "process WhoisSyncJob for domain checks" do
domain = "domain.fr"
check = create(:check, :domain, :nil_dates, domain: domain)
mock_system_command("whois", domain, stdout: file_fixture("whois/domain.fr.txt").read) do
@processor.send(:process, check)
end
check.reload
assert_equal Time.new(2019, 2, 17, 0, 0, 0, 0), check.domain_expires_at
end
test "raises an error for an unsupported check kind" do
check = build(:check)
check.stub :kind, :unknown do
assert_raises ArgumentError do
@processor.send(:process, check)
end
end
end end
test "resolve_last_run_failed includes already and never succeeded" do test "resolve_last_run_failed includes already and never succeeded" do
@ -113,7 +108,7 @@ class CheckProcessorTest < ActiveSupport::TestCase
configuration.expect(:interval, 0.000001) configuration.expect(:interval, 0.000001)
end end
processor = CheckProcessor.new(configuration) processor = CheckDummyProcessor.new(configuration)
mock = Minitest::Mock.new mock = Minitest::Mock.new
assert_stub = lambda { |actual_time| assert_stub = lambda { |actual_time|