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:
parent
47d8641a66
commit
db4e7d42b2
25
app/services/check_domain_processor.rb
Normal file
25
app/services/check_domain_processor.rb
Normal 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
|
|
@ -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 },
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
34
test/services/check_domain_processor_test.rb
Normal file
34
test/services/check_domain_processor_test.rb
Normal 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
|
|
@ -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|
|
||||||
|
|
Loading…
Reference in a new issue