diff --git a/clockwork.gemspec b/clockwork.gemspec index 954dfe1..20eaea3 100644 --- a/clockwork.gemspec +++ b/clockwork.gemspec @@ -26,4 +26,5 @@ Gem::Specification.new do |s| s.add_development_dependency "minitest", "~> 5.8" s.add_development_dependency "mocha" s.add_development_dependency "test-unit" + s.add_development_dependency "timecop" end diff --git a/lib/clockwork/event.rb b/lib/clockwork/event.rb index 0d7f333..848ee5e 100644 --- a/lib/clockwork/event.rb +++ b/lib/clockwork/event.rb @@ -1,6 +1,6 @@ module Clockwork class Event - attr_accessor :job, :last + attr_accessor :job, :last, :skip_first_run def initialize(manager, period, job, block, options={}) validate_if_option(options[:if]) @@ -12,8 +12,8 @@ def initialize(manager, period, job, block, options={}) @if = options[:if] @thread = options.fetch(:thread, @manager.config[:thread]) @timezone = options.fetch(:tz, @manager.config[:tz]) - @skip_first_run = options[:skip_first_run] - @last = @skip_first_run ? convert_timezone(Time.now) : nil + @skip_first_run = options.fetch(:skip_first_run, false) + @last = nil end def convert_timezone(t) diff --git a/lib/clockwork/manager.rb b/lib/clockwork/manager.rb index 55ec497..46467df 100644 --- a/lib/clockwork/manager.rb +++ b/lib/clockwork/manager.rb @@ -160,7 +160,8 @@ def log(msg) private def events_to_run(t) - @events.select{ |event| event.run_now?(t) } + events_to_run = @events.select{ |event| event.run_now?(t) } + clear_first_run_skips(events_to_run) end def register(period, job, block, options) @@ -176,5 +177,23 @@ def every_with_multiple_times(period, job, options={}, &block) register(period, job, block, each_options) end end + + def clear_first_run_skips(events_to_run) + skippable_events = events_to_run.select(&:skip_first_run) + return events_to_run if skippable_events.empty? + events_to_run.reject!(&:skip_first_run) + skippable_events.each do |event| + clear_skips(event) + event.last = Time.now + end + events_to_run + end + + def clear_skips(event) + return unless event.skip_first_run + @events.select { |e| e.to_s == event.to_s }.each do |selected_event| + selected_event.skip_first_run = false + end + end end end diff --git a/test/database_events/test_helpers.rb b/test/database_events/test_helpers.rb index 7f25da0..f2fddcc 100644 --- a/test/database_events/test_helpers.rb +++ b/test/database_events/test_helpers.rb @@ -68,4 +68,4 @@ def name def if?(time) @if_state end -end \ No newline at end of file +end diff --git a/test/event_test.rb b/test/event_test.rb index 2ef77b6..566a426 100644 --- a/test/event_test.rb +++ b/test/event_test.rb @@ -34,41 +34,4 @@ end end end - - describe '#run_now?' do - before do - @manager = Class.new - @manager.stubs(:config).returns({}) - end - - describe 'event skip_first_run option set to true' do - it 'returns false on first attempt' do - event = Clockwork::Event.new(@manager, 1, nil, nil, :skip_first_run => true) - assert_equal false, event.run_now?(Time.now) - end - - it 'returns true on subsequent attempts' do - event = Clockwork::Event.new(@manager, 1, nil, nil, :skip_first_run => true) - # first run - event.run_now?(Time.now) - - # second run - assert_equal true, event.run_now?(Time.now + 1) - end - end - - describe 'event skip_first_run option not set' do - it 'returns true on first attempt' do - event = Clockwork::Event.new(@manager, 1, nil, nil) - assert_equal true, event.run_now?(Time.now + 1) - end - end - - describe 'event skip_first_run option set to false' do - it 'returns true on first attempt' do - event = Clockwork::Event.new(@manager, 1, nil, nil, :skip_first_run => false) - assert_equal true, event.run_now?(Time.now) - end - end - end end diff --git a/test/manager_test.rb b/test/manager_test.rb index c102c43..48c3638 100644 --- a/test/manager_test.rb +++ b/test/manager_test.rb @@ -2,6 +2,7 @@ require "minitest/autorun" require 'mocha/setup' require 'time' +require 'timecop' require 'active_support/time' describe Clockwork::Manager do @@ -185,6 +186,36 @@ def assert_wont_run(t) assert_will_run 'jan 1 2010 18:10:00' assert_wont_run 'jan 1 2010 18:10:01' end + + it "once a day with :skip_first_run" do + Timecop.travel Time.new(2010, 1, 1, 16, 19, 59) do + @manager.every(5.minutes, 'myjob', :at => "16:20", :skip_first_run => true) + + assert_wont_run 'jan 1 2010 16:19:59' + assert_wont_run 'jan 1 2010 16:20:00' + assert_wont_run 'jan 1 2010 16:20:01' + assert_wont_run 'jan 2 2010 16:19:59' + assert_will_run 'jan 2 2010 16:20:00' + assert_will_run 'jan 3 2010 16:20:00' + end + end + + it "twice a day with :skip_first_run" do + Timecop.travel Time.new(2010, 1, 1, 16, 19, 59) do + @manager.every(1.day, 'myjob', :at => ['18:10', '16:20'], :skip_first_run => true) + + assert_wont_run 'jan 1 2010 16:19:59' + assert_wont_run 'jan 1 2010 16:20:00' + assert_wont_run 'jan 1 2010 16:20:01' + + assert_wont_run 'jan 1 2010 18:09:59' + assert_will_run 'jan 1 2010 18:10:00' + assert_wont_run 'jan 1 2010 18:10:01' + + assert_will_run 'jan 2 2010 16:20:00' + assert_will_run 'jan 2 2010 18:10:00' + end + end end describe ':tz option' do