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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +5 -0
- data/Guardfile +50 -0
- data/README.md +135 -2
- data/Rakefile +1 -0
- data/lib/say_when.rb +33 -18
- data/lib/say_when/configuration.rb +16 -0
- data/lib/say_when/cron_expression.rb +19 -21
- data/lib/say_when/poller/base_poller.rb +108 -0
- data/lib/say_when/poller/celluloid_poller.rb +30 -0
- data/lib/say_when/poller/concurrent_poller.rb +31 -0
- data/lib/say_when/poller/simple_poller.rb +37 -0
- data/lib/say_when/processor/active_job_strategy.rb +35 -0
- data/lib/say_when/processor/simple_strategy.rb +13 -0
- data/lib/say_when/processor/test_strategy.rb +21 -0
- data/lib/say_when/scheduler.rb +67 -101
- data/lib/say_when/storage/active_record_strategy.rb +204 -0
- data/lib/say_when/storage/base_job.rb +96 -0
- data/lib/say_when/storage/memory_strategy.rb +140 -0
- data/lib/say_when/tasks.rb +15 -3
- data/lib/say_when/triggers/base.rb +3 -3
- data/lib/say_when/triggers/cron_strategy.rb +2 -3
- data/lib/say_when/triggers/instance_strategy.rb +3 -4
- data/lib/say_when/triggers/once_strategy.rb +3 -4
- data/lib/say_when/utils.rb +16 -0
- data/lib/say_when/version.rb +1 -1
- data/say_when.gemspec +10 -5
- data/test/minitest_helper.rb +45 -15
- data/test/say_when/configuration_test.rb +14 -0
- data/test/say_when/cron_expression_test.rb +140 -0
- data/test/say_when/poller/base_poller_test.rb +42 -0
- data/test/say_when/poller/celluloid_poller_test.rb +17 -0
- data/test/say_when/poller/concurrent_poller_test.rb +19 -0
- data/test/say_when/poller/simple_poller_test.rb +27 -0
- data/test/say_when/processor/active_job_strategy_test.rb +31 -0
- data/test/say_when/processor/simple_strategy_test.rb +15 -0
- data/test/say_when/scheduler_test.rb +41 -57
- data/test/say_when/storage/active_record_strategy_test.rb +134 -0
- data/test/say_when/storage/memory_strategy_test.rb +96 -0
- data/test/say_when/triggers/cron_strategy_test.rb +11 -0
- data/test/say_when/triggers/instance_strategy_test.rb +13 -0
- data/test/say_when/triggers/once_strategy_test.rb +2 -2
- data/test/say_when_test.rb +20 -0
- metadata +110 -36
- data/lib/say_when/base_job.rb +0 -96
- data/lib/say_when/processor/active_messaging.rb +0 -21
- data/lib/say_when/processor/base.rb +0 -19
- data/lib/say_when/processor/shoryuken.rb +0 -14
- data/lib/say_when/processor/simple.rb +0 -17
- data/lib/say_when/storage/active_record/acts.rb +0 -92
- data/lib/say_when/storage/active_record/job.rb +0 -100
- data/lib/say_when/storage/active_record/job_execution.rb +0 -14
- data/lib/say_when/storage/memory/base.rb +0 -36
- data/lib/say_when/storage/memory/job.rb +0 -53
- data/test/say_when/cron_expression_spec.rb +0 -74
- data/test/say_when/processor/active_messaging_test.rb +0 -41
- data/test/say_when/storage/active_record/job_test.rb +0 -90
- data/test/say_when/storage/memory/job_test.rb +0 -32
- data/test/say_when/storage/memory/trigger_test.rb +0 -54
- 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
|
-
|
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
|
-
|
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
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
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
|
-
|
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
|
-
|
57
|
-
scheduler.
|
58
|
-
end
|
30
|
+
lambda do
|
31
|
+
scheduler.extract_job_class(bar: 'foo')
|
32
|
+
end.must_raise RuntimeError
|
33
|
+
end
|
59
34
|
|
60
|
-
|
61
|
-
|
62
|
-
|
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
|
-
|
65
|
-
|
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
|
-
|
68
|
-
|
69
|
-
|
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
|
-
|
72
|
-
|
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
|