say_when 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +5 -0
  4. data/Guardfile +50 -0
  5. data/README.md +135 -2
  6. data/Rakefile +1 -0
  7. data/lib/say_when.rb +33 -18
  8. data/lib/say_when/configuration.rb +16 -0
  9. data/lib/say_when/cron_expression.rb +19 -21
  10. data/lib/say_when/poller/base_poller.rb +108 -0
  11. data/lib/say_when/poller/celluloid_poller.rb +30 -0
  12. data/lib/say_when/poller/concurrent_poller.rb +31 -0
  13. data/lib/say_when/poller/simple_poller.rb +37 -0
  14. data/lib/say_when/processor/active_job_strategy.rb +35 -0
  15. data/lib/say_when/processor/simple_strategy.rb +13 -0
  16. data/lib/say_when/processor/test_strategy.rb +21 -0
  17. data/lib/say_when/scheduler.rb +67 -101
  18. data/lib/say_when/storage/active_record_strategy.rb +204 -0
  19. data/lib/say_when/storage/base_job.rb +96 -0
  20. data/lib/say_when/storage/memory_strategy.rb +140 -0
  21. data/lib/say_when/tasks.rb +15 -3
  22. data/lib/say_when/triggers/base.rb +3 -3
  23. data/lib/say_when/triggers/cron_strategy.rb +2 -3
  24. data/lib/say_when/triggers/instance_strategy.rb +3 -4
  25. data/lib/say_when/triggers/once_strategy.rb +3 -4
  26. data/lib/say_when/utils.rb +16 -0
  27. data/lib/say_when/version.rb +1 -1
  28. data/say_when.gemspec +10 -5
  29. data/test/minitest_helper.rb +45 -15
  30. data/test/say_when/configuration_test.rb +14 -0
  31. data/test/say_when/cron_expression_test.rb +140 -0
  32. data/test/say_when/poller/base_poller_test.rb +42 -0
  33. data/test/say_when/poller/celluloid_poller_test.rb +17 -0
  34. data/test/say_when/poller/concurrent_poller_test.rb +19 -0
  35. data/test/say_when/poller/simple_poller_test.rb +27 -0
  36. data/test/say_when/processor/active_job_strategy_test.rb +31 -0
  37. data/test/say_when/processor/simple_strategy_test.rb +15 -0
  38. data/test/say_when/scheduler_test.rb +41 -57
  39. data/test/say_when/storage/active_record_strategy_test.rb +134 -0
  40. data/test/say_when/storage/memory_strategy_test.rb +96 -0
  41. data/test/say_when/triggers/cron_strategy_test.rb +11 -0
  42. data/test/say_when/triggers/instance_strategy_test.rb +13 -0
  43. data/test/say_when/triggers/once_strategy_test.rb +2 -2
  44. data/test/say_when_test.rb +20 -0
  45. metadata +110 -36
  46. data/lib/say_when/base_job.rb +0 -96
  47. data/lib/say_when/processor/active_messaging.rb +0 -21
  48. data/lib/say_when/processor/base.rb +0 -19
  49. data/lib/say_when/processor/shoryuken.rb +0 -14
  50. data/lib/say_when/processor/simple.rb +0 -17
  51. data/lib/say_when/storage/active_record/acts.rb +0 -92
  52. data/lib/say_when/storage/active_record/job.rb +0 -100
  53. data/lib/say_when/storage/active_record/job_execution.rb +0 -14
  54. data/lib/say_when/storage/memory/base.rb +0 -36
  55. data/lib/say_when/storage/memory/job.rb +0 -53
  56. data/test/say_when/cron_expression_spec.rb +0 -74
  57. data/test/say_when/processor/active_messaging_test.rb +0 -41
  58. data/test/say_when/storage/active_record/job_test.rb +0 -90
  59. data/test/say_when/storage/memory/job_test.rb +0 -32
  60. data/test/say_when/storage/memory/trigger_test.rb +0 -54
  61. data/test/support/models.rb +0 -33
@@ -0,0 +1,14 @@
1
+ # encoding: utf-8
2
+
3
+ require 'minitest_helper'
4
+
5
+ describe SayWhen::Configuration do
6
+ it 'has default values' do
7
+ dos = SayWhen::Configuration.default_options
8
+ dos.wont_be_nil
9
+ dos[:processor_strategy].must_equal :simple
10
+ dos[:storage_strategy].must_equal :memory
11
+ dos[:tick_length].must_equal 5
12
+ dos[:queue].must_equal "default"
13
+ end
14
+ end
@@ -0,0 +1,140 @@
1
+ # encoding: utf-8
2
+ require 'minitest_helper'
3
+
4
+ require 'active_support/all'
5
+ require 'say_when/cron_expression'
6
+
7
+ describe SayWhen::CronExpression do
8
+
9
+ it 'should create with defaults' do
10
+ ce = SayWhen::CronExpression.new
11
+ ce.expression.must_equal "* * * ? * ? *"
12
+ ce.time_zone.must_equal Time.zone.try(:name) || "UTC"
13
+ end
14
+
15
+ it 'should set the time_zone' do
16
+ ce = SayWhen::CronExpression.new("0 0 12 ? * 1#1 *", 'Pacific Time (US & Canada)')
17
+ ce.time_zone.must_equal 'Pacific Time (US & Canada)'
18
+ end
19
+
20
+ it 'has a pretty to_s' do
21
+ ce = SayWhen::CronExpression.new("1 1 1 1 1 ? 2000")
22
+ ce.to_s.must_match(/s:.*/)
23
+ end
24
+
25
+ it 'handles #/# numbers' do
26
+ ce = SayWhen::CronExpression.new("*/10 1 1 1 1 ? 2000")
27
+ ce.seconds.values.must_equal([0, 10, 20, 30, 40, 50])
28
+ end
29
+
30
+ it 'handles #,# numbers' do
31
+ ce = SayWhen::CronExpression.new("1,2 1 1 1 1 ? 2000")
32
+ ce.seconds.values.must_equal([1, 2])
33
+ end
34
+
35
+ it 'handles #-# numbers' do
36
+ ce = SayWhen::CronExpression.new("1-3 1 1 1 1 ? 2000")
37
+ ce.seconds.values.must_equal([1, 2, 3])
38
+ end
39
+
40
+ it 'no values when no match' do
41
+ ce = SayWhen::CronExpression.new("na 1 1 1 1 ? 2000")
42
+ ce.seconds.values.must_equal([])
43
+ end
44
+
45
+ it 'handles changes in seconds' do
46
+ ce = SayWhen::CronExpression.new("1-3 1 1 1 1 ? 2000", "UTC")
47
+ n = ce.next_fire_at(Time.utc(1999,1,1))
48
+ n.must_equal Time.parse("Sat, 01 Jan 2000 01:01:01 UTC")
49
+
50
+ n = ce.next_fire_at(Time.parse("Sat, 01 Jan 2000 01:00:59 UTC"))
51
+ n.must_equal(Time.parse("Sat, 01 Jan 2000 01:01:01 UTC"))
52
+ end
53
+
54
+ describe "Day of the month" do
55
+ it "gets the last day of the month" do
56
+ ce = SayWhen::CronExpression.new("0 0 0 L 1 ? 2004", 'UTC')
57
+ ce.next_fire_at(Time.utc(1999,1,1)).must_equal(Time.parse('Sat, 31 Jan 2004 00:00:00 UTC +00:00'))
58
+ end
59
+
60
+ it "gets the last weekday of the month" do
61
+ ce = SayWhen::CronExpression.new("0 0 0 LW 1 ? 2004", 'UTC')
62
+ ce.next_fire_at(Time.utc(1999,1,1)).must_equal(Time.parse('Fri, 30 Jan 2004 00:00:00 UTC +00:00'))
63
+ end
64
+
65
+ it "gets a weekday in the month" do
66
+ ce = SayWhen::CronExpression.new("0 0 0 W 1 ? 2000", 'UTC')
67
+ ce.next_fire_at(Time.utc(1999,1,1)).must_equal(Time.parse('Mon, 03 Jan 2000 00:00:00 UTC +00:00'))
68
+ end
69
+
70
+ it "gets the closest weekday in the month" do
71
+ ce = SayWhen::CronExpression.new("0 0 0 1W 1 ? 2000", 'UTC')
72
+ ce.next_fire_at(Time.utc(1999,1,1)).must_equal(Time.parse('Tue, 03 Jan 2000 00:00:00 UTC +00:00'))
73
+
74
+ ce = SayWhen::CronExpression.new("0 0 0 10W 1 ? 2000", 'UTC')
75
+ ce.next_fire_at(Time.utc(1999,1,1)).must_equal(Time.parse('Mon, 10 Jan 2000 00:00:00 UTC +00:00'))
76
+ end
77
+ end
78
+
79
+ describe 'get first sunday in the month with "1#1' do
80
+
81
+ before do
82
+ @ce = SayWhen::CronExpression.new("0 0 12 ? * 1#1 *", 'Pacific Time (US & Canada)')
83
+ end
84
+
85
+ it 'finds first sunday in the same month' do
86
+ @ce.next_fire_at(Time.utc(2008,1,1)).must_equal(Time.parse('2008-01-06 12:00:00 -0800'))
87
+ end
88
+
89
+
90
+ it 'finds first sunday in the next month' do
91
+ @ce.next_fire_at(Time.utc(2008,1,7)).must_equal(Time.parse('2008-02-03 12:00:00 -0800'))
92
+ end
93
+
94
+ it 'finds last sunday in the same month' do
95
+ @ce.last_fire_at(Time.utc(2008,1,10)).must_equal(Time.parse('2008-01-06 12:00:00 -0800'))
96
+ end
97
+
98
+ it 'finds sundays in the prior months and years' do
99
+ @ce.last_fire_at(Time.utc(2008,1,5)).must_equal Time.parse('2007-12-02 12:00:00 -0800')
100
+ @ce.last_fire_at(Time.parse('2007-12-02 12:00:00 -0800') - 1.second).must_equal(Time.parse('2007-11-04 12:00:00 -0800'))
101
+ @ce.last_fire_at(Time.parse('2007-11-04 12:00:00 -0800') - 1.second).must_equal(Time.parse('2007-10-07 12:00:00 -0700'))
102
+ @ce.next_fire_at(Time.parse('2007-10-07 12:00:00 -0700') + 1.second).must_equal(Time.parse('2007-11-04 12:00:00 -0800'))
103
+ end
104
+ end
105
+
106
+ describe 'get last sunday in the month with "1L"' do
107
+ before do
108
+ @ce = SayWhen::CronExpression.new("0 0 12 ? * 1L *", 'Pacific Time (US & Canada)')
109
+ end
110
+
111
+ it 'gets next final sunday for same month' do
112
+ @ce.next_fire_at(Time.utc(2008,1,1)).must_equal(Time.parse('2008-01-27 12:00:00 -0800'))
113
+ end
114
+
115
+
116
+ it 'gets next final sunday for next month' do
117
+ @ce.next_fire_at(Time.utc(2008,1,28)).must_equal(Time.parse('2008-02-24 12:00:00 -0800'))
118
+ end
119
+
120
+ it 'gets last final sunday for same month' do
121
+ @ce.last_fire_at(Time.utc(2008,1,28)).must_equal(Time.parse('2008-01-27 12:00:00 -0800'))
122
+ end
123
+
124
+ it 'gets last sunday for prior month and year' do
125
+ @ce.last_fire_at(Time.utc(2008,1,1)).must_equal(Time.parse('2007-12-30 12:00:00 -0800'))
126
+ end
127
+
128
+
129
+ it 'gets last sunday for prior month and year' do
130
+ nfa = @ce.last_fire_at(Time.utc(2007,12,1))
131
+ nfa.must_equal(Time.parse('2007-11-25 12:00:00 -0800'))
132
+
133
+ nfa = @ce.last_fire_at(nfa - 1.second)
134
+ nfa.must_equal(Time.parse('2007-10-28 12:00:00 -0700'))
135
+
136
+ nfa = @ce.next_fire_at(nfa + 1.second)
137
+ nfa.must_equal(Time.parse('2007-11-25 12:00:00 -0800'))
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,42 @@
1
+ # encoding: utf-8
2
+ require 'minitest_helper'
3
+ require 'say_when/poller/base_poller'
4
+
5
+ describe SayWhen::Poller::BasePoller do
6
+
7
+ class TestPoller; include(SayWhen::Poller::BasePoller); end
8
+
9
+ let (:poller) { TestPoller.new }
10
+ let (:time_now) { Time.now }
11
+
12
+ it 'handles errors' do
13
+ job = Minitest::Mock.new
14
+ job.expect(:release, true)
15
+ err = nil
16
+ begin
17
+ raise RuntimeError.new('bad')
18
+ rescue RuntimeError => ex
19
+ err = ex
20
+ end
21
+
22
+ poller.job_error("oh noes", job, err)
23
+ end
24
+
25
+ it "can acquire a job" do
26
+ poller.acquire(time_now)
27
+ end
28
+
29
+ it "can process a job" do
30
+ job = Minitest::Mock.new
31
+ job.expect(:fired, true, [Object])
32
+ poller.process(job, time_now)
33
+ end
34
+
35
+ it "can process jobs" do
36
+ poller.process_jobs
37
+ end
38
+
39
+ it "defines an error tick length" do
40
+ poller.error_tick_length.must_equal 0
41
+ end
42
+ end
@@ -0,0 +1,17 @@
1
+ # encoding: utf-8
2
+ require 'minitest_helper'
3
+ require 'say_when/poller/celluloid_poller'
4
+
5
+ describe SayWhen::Poller::CelluloidPoller do
6
+ let (:poller) { SayWhen::Poller::CelluloidPoller.new(100) }
7
+
8
+ it 'should instantiate the poller' do
9
+ poller.tick_length.must_equal 100
10
+ end
11
+
12
+ it 'should start the poller running, and can stop it' do
13
+ poller.start
14
+ sleep(0.2)
15
+ poller.stop
16
+ end
17
+ end
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+
3
+ require 'minitest_helper'
4
+ require 'say_when/poller/concurrent_poller'
5
+
6
+ describe SayWhen::Poller::ConcurrentPoller do
7
+
8
+ let (:poller) { SayWhen::Poller::ConcurrentPoller.new(100) }
9
+
10
+ it 'should instantiate the poller' do
11
+ poller.tick_length.must_equal 100
12
+ end
13
+
14
+ it 'should start the poller running, and can stop it' do
15
+ poller.start
16
+ sleep(0.2)
17
+ poller.stop
18
+ end
19
+ end
@@ -0,0 +1,27 @@
1
+ # encoding: utf-8
2
+ require 'minitest_helper'
3
+ require 'say_when/poller/simple_poller'
4
+
5
+ describe SayWhen::Poller::SimplePoller do
6
+
7
+ let (:poller) { SayWhen::Poller::SimplePoller.new }
8
+
9
+ it 'should instantiate the poller' do
10
+ poller.wont_be_nil
11
+ end
12
+
13
+ it 'can check if poller is running' do
14
+ poller.wont_be :running?
15
+ end
16
+
17
+ it 'should start the poller running, and can stop it' do
18
+ poller.wont_be :running
19
+
20
+ Thread.start{ poller.start }
21
+ sleep(0.2)
22
+ poller.must_be :running
23
+
24
+ poller.stop
25
+ poller.wont_be :running
26
+ end
27
+ end
@@ -0,0 +1,31 @@
1
+ # encoding: utf-8
2
+
3
+ require 'minitest_helper'
4
+ require 'active_job'
5
+ require 'say_when/processor/active_job_strategy'
6
+
7
+ describe SayWhen::Processor::ActiveJobStrategy do
8
+
9
+ let(:processor) { SayWhen::Processor::ActiveJobStrategy }
10
+
11
+ before {
12
+ SayWhen::Test::TestTask.reset
13
+ }
14
+
15
+ it 'process a memory stored job' do
16
+ options = {
17
+ name: 'Test',
18
+ group: 'Test',
19
+ data: { foo: 'bar', result: 1 },
20
+ job_class: 'SayWhen::Test::TestTask',
21
+ job_method: 'execute'
22
+ }
23
+
24
+ SayWhen::Test::TestTask.wont_be :executed?
25
+
26
+ job = SayWhen::Storage::MemoryStrategy.create(options)
27
+ processor.process(job)
28
+
29
+ SayWhen::Test::TestTask.must_be :executed?
30
+ end
31
+ end
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+
3
+ require 'minitest_helper'
4
+ require 'say_when/processor/simple_strategy'
5
+
6
+ describe SayWhen::Processor::SimpleStrategy do
7
+
8
+ let(:processor) { SayWhen::Processor::SimpleStrategy }
9
+
10
+ it 'process a job by sending a message' do
11
+ job = Minitest::Mock.new
12
+ job.expect(:execute, 'done!')
13
+ processor.process(job).must_equal 'done!'
14
+ end
15
+ end
@@ -4,72 +4,56 @@ require 'minitest_helper'
4
4
 
5
5
  describe SayWhen::Scheduler do
6
6
 
7
- before {
8
- SayWhen::logger = Logger.new('/dev/null')
9
- }
10
-
11
- describe 'class methods' do
12
-
13
- it 'can return singleton' do
14
- s = SayWhen::Scheduler.scheduler
15
- s.wont_be_nil
16
- s.must_equal SayWhen::Scheduler.scheduler
17
- end
18
-
19
- it 'can be configured' do
20
- SayWhen::Scheduler.configure do |scheduler|
21
- scheduler.storage_strategy = :memory
22
- scheduler.processor_class = SayWhen::Test::TestProcessor
23
- end
24
- SayWhen::Scheduler.scheduler.storage_strategy.must_equal :memory
25
- SayWhen::Scheduler.scheduler.processor_class.must_equal SayWhen::Test::TestProcessor
26
- end
27
-
28
- it 'can schedule a new job' do
29
- SayWhen::Scheduler.configure do |scheduler|
30
- scheduler.storage_strategy = :memory
31
- scheduler.processor_class = SayWhen::Test::TestProcessor
32
- end
33
-
34
- job = SayWhen::Scheduler.schedule(
35
- trigger_strategy: 'once',
36
- trigger_options: { at: 10.second.since },
37
- job_class: 'SayWhen::Test::TestTask',
38
- job_method: 'execute'
39
- )
40
- job.wont_be_nil
41
- end
7
+ let (:scheduler) { SayWhen::Scheduler.new }
42
8
 
9
+ it 'has a logger' do
10
+ scheduler.logger.must_be_instance_of Logger
43
11
  end
44
12
 
45
- describe 'instance methods' do
13
+ it 'extracts data' do
14
+ scheduler.extract_data({}).must_be_nil
15
+ scheduler.extract_data(data: 'data').must_equal 'data'
16
+ end
46
17
 
47
- before(:all) do
48
- SayWhen::Scheduler.configure do |scheduler|
49
- scheduler.storage_strategy = :memory
50
- scheduler.processor_class = SayWhen::Test::TestProcessor
51
- end
52
- end
18
+ it 'extracts job method' do
19
+ scheduler.extract_job_method({}).must_equal 'execute'
20
+ scheduler.extract_job_method(job_method: 'just_doit').must_equal 'just_doit'
21
+ scheduler.extract_job_method(method: 'doit').must_equal 'doit'
22
+ end
53
23
 
54
- let (:scheduler) { SayWhen::Scheduler.scheduler }
24
+ it 'extracts job class' do
25
+ scheduler.extract_job_class(job_class: 'foo').must_equal 'foo'
26
+ scheduler.extract_job_class(class: 'foo').must_equal 'foo'
27
+ scheduler.extract_job_class(SayWhen::Test::TestTask).must_equal 'SayWhen::Test::TestTask'
28
+ scheduler.extract_job_class('SayWhen::Test::TestTask').must_equal 'SayWhen::Test::TestTask'
55
29
 
56
- it 'should instantiate the processor from its class' do
57
- scheduler.processor.must_be_instance_of(SayWhen::Test::TestProcessor)
58
- end
30
+ lambda do
31
+ scheduler.extract_job_class(bar: 'foo')
32
+ end.must_raise RuntimeError
33
+ end
59
34
 
60
- it 'should get the job class based on the strategy' do
61
- scheduler.job_class.must_equal SayWhen::Storage::Memory::Job
62
- end
35
+ it 'gets job options' do
36
+ keys = [:job_class, :job_method, :data]
37
+ opts = scheduler.job_options(keys.inject({}) { |s, k| s[k] = k.to_s; s } )
38
+ keys.each{|k| opts[k].must_equal k.to_s }
39
+ end
63
40
 
64
- it 'should start the scheduler running, and can stop it' do
65
- scheduler.wont_be :running
41
+ it 'can schedule a new job' do
42
+ job = scheduler.schedule(
43
+ trigger_strategy: 'once',
44
+ trigger_options: { at: 10.second.since },
45
+ job_class: 'SayWhen::Test::TestTask',
46
+ job_method: 'execute'
47
+ )
48
+ job.wont_be_nil
49
+ end
66
50
 
67
- scheduler_thread = Thread.start{ scheduler.start }
68
- sleep(0.2)
69
- scheduler.must_be :running
51
+ it 'can schedule a cron job' do
52
+ job = scheduler.schedule_cron("0 0 12 ? * * *", SayWhen::Test::TestTask)
53
+ job.wont_be_nil
54
+ end
70
55
 
71
- scheduler.stop
72
- scheduler.wont_be :running
73
- end
56
+ it 'should provide the storage strategy' do
57
+ scheduler.storage.must_equal SayWhen::Storage::MemoryStrategy
74
58
  end
75
59
  end
@@ -0,0 +1,134 @@
1
+ # encoding: utf-8
2
+
3
+ require 'minitest_helper'
4
+ require 'active_record_helper'
5
+ require 'say_when/storage/active_record_strategy'
6
+
7
+ describe SayWhen::Storage::ActiveRecordStrategy do
8
+ let(:valid_attributes) {
9
+ {
10
+ trigger_strategy: :cron,
11
+ trigger_options: { expression: '0 0 12 ? * * *', time_zone: 'Pacific Time (US & Canada)' },
12
+ data: { foo: 'bar', result: 1 },
13
+ job_class: 'SayWhen::Test::TestTask',
14
+ job_method: 'execute'
15
+ }
16
+ }
17
+
18
+ let(:strategy) { SayWhen::Storage::ActiveRecordStrategy }
19
+
20
+ let(:job) { strategy.create(valid_attributes) }
21
+
22
+ it 'job can be created' do
23
+ j = strategy.create(valid_attributes)
24
+ j.wont_be_nil
25
+ end
26
+
27
+ it 'job can be serialized' do
28
+ strategy.serialize(job).must_equal job
29
+ strategy.deserialize(job).must_equal job
30
+ end
31
+
32
+ it 'can execute the task for the job' do
33
+ job.execute_job( { result: 1 } ).must_equal 1
34
+ end
35
+
36
+ it 'can execute the job' do
37
+ j = strategy.create(valid_attributes)
38
+ j.execute.must_equal 1
39
+ end
40
+
41
+ it 'derives a trigger from the attributes' do
42
+ t = strategy.create(valid_attributes)
43
+ t.trigger.wont_be_nil
44
+ t.trigger.must_be_instance_of SayWhen::Triggers::CronStrategy
45
+ end
46
+
47
+ it 'has a waiting state on create' do
48
+ t = strategy.create(valid_attributes)
49
+ t.status.must_equal SayWhen::Storage::BaseJob::STATE_WAITING
50
+ end
51
+
52
+ it 'has a next fire at set on create' do
53
+ opts = valid_attributes[:trigger_options]
54
+ ce = SayWhen::CronExpression.new(opts[:expression], opts[:time_zone])
55
+ j = strategy.create(valid_attributes)
56
+ j.status.must_equal SayWhen::Storage::BaseJob::STATE_WAITING
57
+ j.next_fire_at.must_equal ce.next_fire_at
58
+ end
59
+
60
+ it 'can acquire and release the next job' do
61
+ SayWhen::Storage::ActiveRecordStrategy::Job.delete_all
62
+
63
+ j2_opts = {
64
+ trigger_strategy: :cron,
65
+ trigger_options: { expression: '0 0 10 ? * * *', time_zone: 'Pacific Time (US & Canada)' },
66
+ data: { foo: 'bar', result: 2 },
67
+ job_class: 'SayWhen::Test::TestTask',
68
+ job_method: 'execute'
69
+ }
70
+
71
+ now = Time.now.change(hour: 0)
72
+ Time.stub(:now, now) do
73
+ j1 = strategy.create(valid_attributes)
74
+ j1.wont_be_nil
75
+ j2 = strategy.create(j2_opts)
76
+
77
+ next_job = strategy.acquire_next(2.days.since)
78
+ next_job.status.must_equal "acquired"
79
+ next_job.must_equal j2
80
+ strategy.release(next_job)
81
+ next_job.status.must_equal "waiting"
82
+ end
83
+ end
84
+
85
+ it 'resets acquired jobs' do
86
+ old = 2.hours.ago
87
+ j = strategy.create(valid_attributes)
88
+ j.update_attributes(status: 'acquired', updated_at: old, created_at: old)
89
+
90
+ j.status.must_equal 'acquired'
91
+
92
+ strategy.reset_acquired(3600)
93
+
94
+ j.reload
95
+ j.status.must_equal 'waiting'
96
+ end
97
+
98
+ it 'can be fired' do
99
+ opts = valid_attributes[:trigger_options]
100
+ ce = SayWhen::CronExpression.new(opts[:expression], opts[:time_zone])
101
+ j = strategy.create(valid_attributes)
102
+ nfa = ce.last_fire_at(j.created_at - 1.second)
103
+ lfa = ce.last_fire_at(nfa - 1.second)
104
+ j.next_fire_at = nfa
105
+ j.last_fire_at = lfa
106
+
107
+ now = Time.now
108
+ Time.stub(:now, now) do
109
+ strategy.fired(j, now)
110
+ j.next_fire_at.must_equal ce.next_fire_at(now)
111
+ j.last_fire_at.must_equal now
112
+ j.status.must_equal SayWhen::Storage::BaseJob::STATE_WAITING
113
+ end
114
+ end
115
+
116
+ describe "acts_as_scheduled" do
117
+ it "acts_as_scheduled calls has_many" do
118
+ SayWhen::Test::TestActsAsScheduled.must_be :has_many_called?
119
+ end
120
+
121
+ it "includes schedule methods" do
122
+ taas = SayWhen::Test::TestActsAsScheduled.new
123
+ [:schedule, :schedule_instance, :schedule_cron, :schedule_once, :schedule_in].each do |m|
124
+ taas.respond_to?(m).must_equal true
125
+ end
126
+ end
127
+
128
+ it "sets the scheduled value" do
129
+ taas = SayWhen::Test::TestActsAsScheduled.new
130
+ job = taas.set_scheduled({})
131
+ job[:scheduled].must_equal taas
132
+ end
133
+ end
134
+ end