say_when 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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