Added specs for the HuginnScheduler

This commit is contained in:
Dominik Sander 2014-09-01 00:41:53 +02:00
parent f27b6c5c21
commit 250a244de5
3 changed files with 130 additions and 53 deletions

View file

@ -1,16 +1,54 @@
require 'rufus/scheduler'
class HuginnScheduler
FAILED_JOBS_TO_KEEP = 100
attr_accessor :mutex
def initialize
@rufus_scheduler = Rufus::Scheduler.new
self.mutex = Mutex.new
end
def stop
@rufus_scheduler.stop
end
def run!
tzinfo_friendly_timezone = ActiveSupport::TimeZone::MAPPING[ENV['TIMEZONE'].present? ? ENV['TIMEZONE'] : "Pacific Time (US & Canada)"]
# Schedule event propagation.
@rufus_scheduler.every '1m' do
propagate!
end
# Schedule event cleanup.
@rufus_scheduler.cron "0 0 * * * " + tzinfo_friendly_timezone do
cleanup_expired_events!
end
# Schedule failed job cleanup.
@rufus_scheduler.every '1h' do
cleanup_failed_jobs!
end
# Schedule repeating events.
%w[1m 2m 5m 10m 30m 1h 2h 5h 12h 1d 2d 7d].each do |schedule|
@rufus_scheduler.every schedule do
run_schedule "every_#{schedule}"
end
end
# Schedule events for specific times.
24.times do |hour|
@rufus_scheduler.cron "0 #{hour} * * * " + tzinfo_friendly_timezone do
run_schedule hour_to_schedule_name(hour)
end
end
@rufus_scheduler.join
end
private
def run_schedule(time)
with_mutex do
puts "Queuing schedule for #{time}"
@ -33,10 +71,23 @@ class HuginnScheduler
end
def cleanup_failed_jobs!
first_to_delete = Delayed::Job.where.not(failed_at: nil).order("failed_at DESC").offset(ENV['FAILED_JOBS_TO_KEEP'].try(:to_i) || 100).limit(ENV['FAILED_JOBS_TO_KEEP'].try(:to_i) || 100).pluck(:failed_at).first
num_to_keep = (ENV['FAILED_JOBS_TO_KEEP'].presence || FAILED_JOBS_TO_KEEP).to_i
first_to_delete = Delayed::Job.where.not(failed_at: nil).order("failed_at DESC").offset(num_to_keep).limit(num_to_keep).pluck(:failed_at).first
Delayed::Job.where(["failed_at <= ?", first_to_delete]).delete_all if first_to_delete.present?
end
def hour_to_schedule_name(hour)
if hour == 0
"midnight"
elsif hour < 12
"#{hour}am"
elsif hour == 12
"noon"
else
"#{hour - 12}pm"
end
end
def with_mutex
ActiveRecord::Base.connection_pool.with_connection do
mutex.synchronize do
@ -44,56 +95,4 @@ class HuginnScheduler
end
end
end
def run!
self.mutex = Mutex.new
tzinfo_friendly_timezone = ActiveSupport::TimeZone::MAPPING[ENV['TIMEZONE'].present? ? ENV['TIMEZONE'] : "Pacific Time (US & Canada)"]
# Schedule event propagation.
@rufus_scheduler.every '1m' do
propagate!
end
# Schedule event cleanup.
@rufus_scheduler.cron "0 0 * * * " + tzinfo_friendly_timezone do
cleanup_expired_events!
end
# Schedule failed job cleanup.
@rufus_scheduler.every '1h' do
cleanup_failed_jobs!
end
# Schedule repeating events.
%w[1m 2m 5m 10m 30m 1h 2h 5h 12h 1d 2d 7d].each do |schedule|
@rufus_scheduler.every schedule do
run_schedule "every_#{schedule}"
end
end
# Schedule events for specific times.
# Times are assumed to be in PST for now. Can store a user#timezone later.
24.times do |hour|
@rufus_scheduler.cron "0 #{hour} * * * " + tzinfo_friendly_timezone do
if hour == 0
run_schedule "midnight"
elsif hour < 12
run_schedule "#{hour}am"
elsif hour == 12
run_schedule "noon"
else
run_schedule "#{hour - 12}pm"
end
end
end
@rufus_scheduler.join
end
end

View file

@ -3,3 +3,4 @@ TWITTER_OAUTH_KEY=twitteroauthkey
TWITTER_OAUTH_SECRET=twitteroauthsecret
THIRTY_SEVEN_SIGNALS_OAUTH_KEY=TESTKEY
THIRTY_SEVEN_SIGNALS_OAUTH_SECRET=TESTSECRET
FAILED_JOBS_TO_KEEP=2

View file

@ -0,0 +1,77 @@
require 'spec_helper'
describe HuginnScheduler do
before(:each) do
@scheduler = HuginnScheduler.new
stub
end
it "should stop the scheduler" do
mock.instance_of(Rufus::Scheduler).stop
@scheduler.stop
end
it "schould register the schedules with the rufus scheduler and run" do
mock.instance_of(Rufus::Scheduler).join
@scheduler.run!
end
it "should run scheduled agents" do
mock(Agent).run_schedule('every_1h')
mock.instance_of(IO).puts('Queuing schedule for every_1h')
@scheduler.send(:run_schedule, 'every_1h')
end
it "should propagate events" do
mock(Agent).receive!
stub.instance_of(IO).puts
@scheduler.send(:propagate!)
end
it "schould clean up expired events" do
mock(Event).cleanup_expired!
stub.instance_of(IO).puts
@scheduler.send(:cleanup_expired_events!)
end
describe "#hour_to_schedule_name" do
it "for 0h" do
@scheduler.send(:hour_to_schedule_name, 0).should == 'midnight'
end
it "for the forenoon" do
@scheduler.send(:hour_to_schedule_name, 6).should == '6am'
end
it "for 12h" do
@scheduler.send(:hour_to_schedule_name, 12).should == 'noon'
end
it "for the afternoon" do
@scheduler.send(:hour_to_schedule_name, 17).should == '5pm'
end
end
describe "cleanup_failed_jobs!" do
before do
3.times do |i|
Delayed::Job.create(failed_at: Time.now - i.minutes)
end
@keep = Delayed::Job.order(:failed_at)[1]
end
it "work with set FAILED_JOBS_TO_KEEP env variable", focus: true do
expect { @scheduler.send(:cleanup_failed_jobs!) }.to change(Delayed::Job, :count).by(-1)
expect { @scheduler.send(:cleanup_failed_jobs!) }.to change(Delayed::Job, :count).by(0)
@keep.id.should == Delayed::Job.order(:failed_at)[0].id
end
it "work without the FAILED_JOBS_TO_KEEP env variable" do
old = ENV['FAILED_JOBS_TO_KEEP']
ENV['FAILED_JOBS_TO_KEEP'] = nil
expect { @scheduler.send(:cleanup_failed_jobs!) }.to change(Delayed::Job, :count).by(0)
ENV['FAILED_JOBS_TO_KEEP'] = old
end
end
end