rufus-scheduler 2.0.24 → 3.1.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.
- data/CHANGELOG.txt +76 -0
- data/CREDITS.txt +23 -0
- data/LICENSE.txt +1 -1
- data/README.md +1439 -0
- data/Rakefile +1 -5
- data/TODO.txt +149 -55
- data/lib/rufus/{sc → scheduler}/cronline.rb +167 -53
- data/lib/rufus/scheduler/job_array.rb +92 -0
- data/lib/rufus/scheduler/jobs.rb +633 -0
- data/lib/rufus/scheduler/locks.rb +95 -0
- data/lib/rufus/scheduler/util.rb +306 -0
- data/lib/rufus/scheduler/zones.rb +174 -0
- data/lib/rufus/scheduler/zotime.rb +154 -0
- data/lib/rufus/scheduler.rb +608 -27
- data/rufus-scheduler.gemspec +6 -4
- data/spec/basics_spec.rb +54 -0
- data/spec/cronline_spec.rb +479 -152
- data/spec/error_spec.rb +139 -0
- data/spec/job_array_spec.rb +39 -0
- data/spec/job_at_spec.rb +58 -0
- data/spec/job_cron_spec.rb +128 -0
- data/spec/job_every_spec.rb +104 -0
- data/spec/job_in_spec.rb +20 -0
- data/spec/job_interval_spec.rb +68 -0
- data/spec/job_repeat_spec.rb +357 -0
- data/spec/job_spec.rb +498 -109
- data/spec/lock_custom_spec.rb +47 -0
- data/spec/lock_flock_spec.rb +47 -0
- data/spec/lock_lockfile_spec.rb +61 -0
- data/spec/lock_spec.rb +59 -0
- data/spec/parse_spec.rb +263 -0
- data/spec/schedule_at_spec.rb +158 -0
- data/spec/schedule_cron_spec.rb +66 -0
- data/spec/schedule_every_spec.rb +109 -0
- data/spec/schedule_in_spec.rb +80 -0
- data/spec/schedule_interval_spec.rb +128 -0
- data/spec/scheduler_spec.rb +928 -124
- data/spec/spec_helper.rb +126 -0
- data/spec/threads_spec.rb +96 -0
- data/spec/zotime_spec.rb +396 -0
- metadata +56 -33
- data/README.rdoc +0 -661
- data/lib/rufus/otime.rb +0 -3
- data/lib/rufus/sc/jobqueues.rb +0 -160
- data/lib/rufus/sc/jobs.rb +0 -471
- data/lib/rufus/sc/rtime.rb +0 -363
- data/lib/rufus/sc/scheduler.rb +0 -636
- data/lib/rufus/sc/version.rb +0 -32
- data/spec/at_in_spec.rb +0 -47
- data/spec/at_spec.rb +0 -125
- data/spec/blocking_spec.rb +0 -64
- data/spec/cron_spec.rb +0 -134
- data/spec/every_spec.rb +0 -304
- data/spec/exception_spec.rb +0 -113
- data/spec/in_spec.rb +0 -150
- data/spec/mutex_spec.rb +0 -159
- data/spec/rtime_spec.rb +0 -137
- data/spec/schedulable_spec.rb +0 -97
- data/spec/spec_base.rb +0 -87
- data/spec/stress_schedule_unschedule_spec.rb +0 -159
- data/spec/timeout_spec.rb +0 -148
- data/test/kjw.rb +0 -113
- data/test/t.rb +0 -20
@@ -0,0 +1,47 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# Specifying rufus-scheduler
|
4
|
+
#
|
5
|
+
# Fri Nov 1 05:56:03 JST 2013
|
6
|
+
#
|
7
|
+
# Ishinomaki
|
8
|
+
#
|
9
|
+
|
10
|
+
require 'spec_helper'
|
11
|
+
|
12
|
+
|
13
|
+
describe Rufus::Scheduler do
|
14
|
+
|
15
|
+
class LosingLockScheduler < Rufus::Scheduler
|
16
|
+
|
17
|
+
attr_reader :counter
|
18
|
+
|
19
|
+
def initialize
|
20
|
+
super
|
21
|
+
@counter = 0
|
22
|
+
end
|
23
|
+
|
24
|
+
def confirm_lock
|
25
|
+
@counter = @counter + 1
|
26
|
+
false
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'custom locks' do
|
31
|
+
|
32
|
+
it 'does not trigger when #confirm_lock returns false' do
|
33
|
+
|
34
|
+
s = LosingLockScheduler.new
|
35
|
+
|
36
|
+
count = 0
|
37
|
+
|
38
|
+
s.in('0s') { count = count + 1 }
|
39
|
+
|
40
|
+
sleep 0.7
|
41
|
+
|
42
|
+
expect(count).to eq(0)
|
43
|
+
expect(s.counter).to eq(1)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
@@ -0,0 +1,47 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# Specifying rufus-scheduler
|
4
|
+
#
|
5
|
+
# Sat Aug 16 05:43:06 JST 2014
|
6
|
+
# added by @ecin
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'spec_helper'
|
10
|
+
|
11
|
+
|
12
|
+
describe Rufus::Scheduler::FileLock do
|
13
|
+
|
14
|
+
before :each do
|
15
|
+
|
16
|
+
@lock_path = '.rufus-scheduler.lock'
|
17
|
+
@lock = Rufus::Scheduler::FileLock.new(@lock_path)
|
18
|
+
end
|
19
|
+
|
20
|
+
after :each do
|
21
|
+
|
22
|
+
FileUtils.rm_f(@lock_path)
|
23
|
+
FileUtils.rm_f('lock.txt')
|
24
|
+
end
|
25
|
+
|
26
|
+
context ':scheduler_lock => Rufus::Scheduler::FileLock.new(path)' do
|
27
|
+
|
28
|
+
it 'writes down a .rufus-scheduler.lock file' do
|
29
|
+
|
30
|
+
@lock.lock
|
31
|
+
|
32
|
+
line = File.read(@lock_path)
|
33
|
+
|
34
|
+
expect(line).to match(/pid: #{$$}/)
|
35
|
+
end
|
36
|
+
|
37
|
+
it '"flocks" the lock file' do
|
38
|
+
|
39
|
+
@lock.lock
|
40
|
+
|
41
|
+
f = File.new(@lock_path, 'a')
|
42
|
+
|
43
|
+
expect(f.flock(File::LOCK_NB | File::LOCK_EX)).to eq(false)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
@@ -0,0 +1,61 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# Specifying rufus-scheduler
|
4
|
+
#
|
5
|
+
# Tue Aug 13 05:58:48 JST 2013
|
6
|
+
#
|
7
|
+
|
8
|
+
require 'spec_helper'
|
9
|
+
|
10
|
+
|
11
|
+
describe Rufus::Scheduler do
|
12
|
+
|
13
|
+
after :each do
|
14
|
+
|
15
|
+
FileUtils.rm_f('.rufus-scheduler.lock')
|
16
|
+
FileUtils.rm_f('lock.txt')
|
17
|
+
end
|
18
|
+
|
19
|
+
context ':lockfile => ".rufus-scheduler.lock"' do
|
20
|
+
|
21
|
+
it 'writes down a .rufus-scheduler.lock file' do
|
22
|
+
|
23
|
+
s = Rufus::Scheduler.new :lockfile => '.rufus-scheduler.lock'
|
24
|
+
|
25
|
+
line = File.read('.rufus-scheduler.lock')
|
26
|
+
|
27
|
+
#p line
|
28
|
+
expect(line).to match(/pid: #{$$}/)
|
29
|
+
end
|
30
|
+
|
31
|
+
it '"flocks" the lock file' do
|
32
|
+
|
33
|
+
s = Rufus::Scheduler.new :lockfile => '.rufus-scheduler.lock'
|
34
|
+
|
35
|
+
f = File.new('.rufus-scheduler.lock', 'a')
|
36
|
+
|
37
|
+
expect(f.flock(File::LOCK_NB | File::LOCK_EX)).to eq(false)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'prevents newer schedulers from starting' do
|
41
|
+
|
42
|
+
s0 = Rufus::Scheduler.new :lockfile => '.rufus-scheduler.lock'
|
43
|
+
s1 = Rufus::Scheduler.new :lockfile => '.rufus-scheduler.lock'
|
44
|
+
|
45
|
+
expect(s0.started_at).not_to eq(nil)
|
46
|
+
expect(s1.started_at).to eq(nil)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'releases the lockfile when shutting down' do
|
50
|
+
|
51
|
+
s = Rufus::Scheduler.new :lockfile => '.rufus-scheduler.lock'
|
52
|
+
|
53
|
+
s.shutdown(:kill)
|
54
|
+
|
55
|
+
f = File.new('.rufus-scheduler.lock', 'a')
|
56
|
+
|
57
|
+
expect(f.flock(File::LOCK_NB | File::LOCK_EX)).to eq(0)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
data/spec/lock_spec.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# Specifying rufus-scheduler
|
4
|
+
#
|
5
|
+
# Sat Aug 16 05:42:11 JST 2014
|
6
|
+
# added by @ecin
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'spec_helper'
|
10
|
+
|
11
|
+
|
12
|
+
describe Rufus::Scheduler do
|
13
|
+
|
14
|
+
context "when running multiple schedulers side-by-side" do
|
15
|
+
|
16
|
+
class AlwaysLock
|
17
|
+
def lock; true; end
|
18
|
+
def unlock; true; end
|
19
|
+
def locked?; true; end
|
20
|
+
end
|
21
|
+
|
22
|
+
class NeverLock
|
23
|
+
def lock; false; end
|
24
|
+
def unlock; true; end
|
25
|
+
def locked?; true; end
|
26
|
+
end
|
27
|
+
|
28
|
+
it "only starts if it can acquire a scheduler lock" do
|
29
|
+
|
30
|
+
main = Rufus::Scheduler.new :scheduler_lock => AlwaysLock.new
|
31
|
+
backup = Rufus::Scheduler.new :scheduler_lock => NeverLock.new
|
32
|
+
|
33
|
+
expect(main).to be_up
|
34
|
+
expect(backup).to be_down
|
35
|
+
end
|
36
|
+
|
37
|
+
it "only triggers jobs when it can acquire a trigger lock" do
|
38
|
+
|
39
|
+
main = Rufus::Scheduler.new(:trigger_lock => AlwaysLock.new)
|
40
|
+
backup = Rufus::Scheduler.new(:trigger_lock => NeverLock.new)
|
41
|
+
|
42
|
+
expect(main).to be_up
|
43
|
+
expect(backup).to be_up
|
44
|
+
|
45
|
+
counter = 0
|
46
|
+
job = proc { counter += 1 }
|
47
|
+
main.schedule_in(0, job)
|
48
|
+
backup.schedule_in(0, job)
|
49
|
+
|
50
|
+
sleep 0.5
|
51
|
+
|
52
|
+
expect(main.jobs).to be_empty
|
53
|
+
expect(backup.jobs.count).to eq(1)
|
54
|
+
expect(backup.jobs.first.next_time).to be(false)
|
55
|
+
expect(counter).to eq(1)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
data/spec/parse_spec.rb
ADDED
@@ -0,0 +1,263 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# Specifying rufus-scheduler
|
4
|
+
#
|
5
|
+
# Wed Apr 17 06:00:59 JST 2013
|
6
|
+
#
|
7
|
+
|
8
|
+
require 'spec_helper'
|
9
|
+
|
10
|
+
|
11
|
+
describe Rufus::Scheduler do
|
12
|
+
|
13
|
+
describe '.parse' do
|
14
|
+
|
15
|
+
def pa(s, opts={}); Rufus::Scheduler.parse(s, opts); end
|
16
|
+
|
17
|
+
it 'parses duration strings' do
|
18
|
+
|
19
|
+
expect(pa('1.0d1.0w1.0d')).to eq(777600.0)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'parses datetimes' do
|
23
|
+
|
24
|
+
# local
|
25
|
+
|
26
|
+
expect(pa('Sun Nov 18 16:01:00 2012').strftime('%c')).to eq(
|
27
|
+
'Sun Nov 18 16:01:00 2012'
|
28
|
+
)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'parses datetimes with timezones' do
|
32
|
+
|
33
|
+
expect(
|
34
|
+
pa('Sun Nov 18 16:01:00 2012 Asia/Singapore').getutc.strftime('%c %z')
|
35
|
+
).to eq('Sun Nov 18 08:01:00 2012 +0000')
|
36
|
+
|
37
|
+
expect(pa('Sun Nov 18 16:01:00 2012 Zulu').getutc.strftime('%c')).to eq(
|
38
|
+
'Sun Nov 18 16:01:00 2012'
|
39
|
+
)
|
40
|
+
|
41
|
+
expect(
|
42
|
+
pa('Sun Nov 18 16:01:00 Asia/Singapore 2012').getutc.strftime('%c %z')
|
43
|
+
).to eq('Sun Nov 18 08:01:00 2012 +0000')
|
44
|
+
|
45
|
+
expect(
|
46
|
+
pa('Asia/Singapore Sun Nov 18 16:01:00 2012').getutc.strftime('%c %z')
|
47
|
+
).to eq('Sun Nov 18 08:01:00 2012 +0000')
|
48
|
+
|
49
|
+
expect(
|
50
|
+
pa('Sun Nov 18 16:01:00 2012 America/New_York').getutc.strftime('%c %z')
|
51
|
+
).to eq('Sun Nov 18 21:01:00 2012 +0000')
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'parses datetimes with named timezones' do
|
55
|
+
|
56
|
+
expect(pa(
|
57
|
+
'Sun Nov 18 16:01:00 2012 Europe/Berlin'
|
58
|
+
).strftime('%c %z')).to eq(
|
59
|
+
'Sun Nov 18 16:01:00 2012 +0100'
|
60
|
+
)
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'parses datetimes (with the local timezone implicitely)' do
|
64
|
+
|
65
|
+
localzone = Time.now.strftime('%z')
|
66
|
+
|
67
|
+
expect(
|
68
|
+
pa('Nov 18 16:01:00 2012').strftime('%c %z')
|
69
|
+
).to eq("Sun Nov 18 16:01:00 2012 #{localzone}")
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'parses cronlines' do
|
73
|
+
|
74
|
+
out = pa('* * * * *')
|
75
|
+
|
76
|
+
expect(out.class).to eq(Rufus::Scheduler::CronLine)
|
77
|
+
expect(out.original).to eq('* * * * *')
|
78
|
+
|
79
|
+
expect(pa('10 23 * * *').class).to eq(Rufus::Scheduler::CronLine)
|
80
|
+
expect(pa('* 23 * * *').class).to eq(Rufus::Scheduler::CronLine)
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'raises on unparseable input' do
|
84
|
+
|
85
|
+
expect {
|
86
|
+
pa('nada')
|
87
|
+
}.to raise_error(ArgumentError, 'couldn\'t parse "nada"')
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'does not use Chronic if not present' do
|
91
|
+
|
92
|
+
t = pa('next monday 7 PM')
|
93
|
+
|
94
|
+
n = Time.now
|
95
|
+
|
96
|
+
expect(t.strftime('%Y-%m-%d %H:%M:%S')).to eq(
|
97
|
+
n.strftime('%Y-%m-%d') + ' 19:00:00'
|
98
|
+
)
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'uses Chronic if present' do
|
102
|
+
|
103
|
+
with_chronic do
|
104
|
+
|
105
|
+
t = pa('next monday 7 PM')
|
106
|
+
|
107
|
+
expect(t.wday).to eq(1)
|
108
|
+
expect(t.hour).to eq(19)
|
109
|
+
expect(t.min).to eq(0)
|
110
|
+
expect(t).to be > Time.now
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'passes options to Chronic' do
|
115
|
+
|
116
|
+
with_chronic do
|
117
|
+
|
118
|
+
t = pa('monday', :context => :past)
|
119
|
+
|
120
|
+
expect(t.wday).to eq(1)
|
121
|
+
expect(t).to be < Time.now
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
describe '.parse_duration' do
|
127
|
+
|
128
|
+
def pd(s)
|
129
|
+
Rufus::Scheduler.parse_duration(s)
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'parses duration strings' do
|
133
|
+
|
134
|
+
expect(pd('-1.0d1.0w1.0d')).to eq(-777600.0)
|
135
|
+
expect(pd('-1d1w1d')).to eq(-777600.0)
|
136
|
+
expect(pd('-1w2d')).to eq(-777600.0)
|
137
|
+
expect(pd('-1h10s')).to eq(-3610.0)
|
138
|
+
expect(pd('-1h')).to eq(-3600.0)
|
139
|
+
expect(pd('-5.')).to eq(-5.0)
|
140
|
+
expect(pd('-2.5s')).to eq(-2.5)
|
141
|
+
expect(pd('-1s')).to eq(-1.0)
|
142
|
+
expect(pd('-500')).to eq(-500)
|
143
|
+
expect(pd('')).to eq(0.0)
|
144
|
+
expect(pd('5.0')).to eq(5.0)
|
145
|
+
expect(pd('0.5')).to eq(0.5)
|
146
|
+
expect(pd('.5')).to eq(0.5)
|
147
|
+
expect(pd('5.')).to eq(5.0)
|
148
|
+
expect(pd('500')).to eq(500)
|
149
|
+
expect(pd('1000')).to eq(1000)
|
150
|
+
expect(pd('1')).to eq(1.0)
|
151
|
+
expect(pd('1s')).to eq(1.0)
|
152
|
+
expect(pd('2.5s')).to eq(2.5)
|
153
|
+
expect(pd('1h')).to eq(3600.0)
|
154
|
+
expect(pd('1h10s')).to eq(3610.0)
|
155
|
+
expect(pd('1w2d')).to eq(777600.0)
|
156
|
+
expect(pd('1d1w1d')).to eq(777600.0)
|
157
|
+
expect(pd('1.0d1.0w1.0d')).to eq(777600.0)
|
158
|
+
|
159
|
+
expect(pd('.5m')).to eq(30.0)
|
160
|
+
expect(pd('5.m')).to eq(300.0)
|
161
|
+
expect(pd('1m.5s')).to eq(60.5)
|
162
|
+
expect(pd('-.5m')).to eq(-30.0)
|
163
|
+
|
164
|
+
expect(pd('1')).to eq(1)
|
165
|
+
expect(pd('0.1')).to eq(0.1)
|
166
|
+
expect(pd('1s')).to eq(1)
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'calls #to_s on its input' do
|
170
|
+
|
171
|
+
expect(pd(0.1)).to eq(0.1)
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'raises on wrong duration strings' do
|
175
|
+
|
176
|
+
expect { pd('-') }.to raise_error(ArgumentError)
|
177
|
+
expect { pd('h') }.to raise_error(ArgumentError)
|
178
|
+
expect { pd('whatever') }.to raise_error(ArgumentError)
|
179
|
+
expect { pd('hms') }.to raise_error(ArgumentError)
|
180
|
+
|
181
|
+
expect { pd(' 1h ') }.to raise_error(ArgumentError)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
describe '.parse_time_string -> .parse_duration' do
|
186
|
+
|
187
|
+
it 'is still around for libs using it out there' do
|
188
|
+
|
189
|
+
expect(Rufus::Scheduler.parse_time_string('1d1w1d')).to eq(777600.0)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe '.parse_duration_string -> .parse_duration' do
|
194
|
+
|
195
|
+
it 'is still around for libs using it out there' do
|
196
|
+
|
197
|
+
expect(Rufus::Scheduler.parse_duration_string('1d1w1d')).to eq(777600.0)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
describe '.to_duration' do
|
202
|
+
|
203
|
+
def td(o, opts={})
|
204
|
+
Rufus::Scheduler.to_duration(o, opts)
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'turns integers into duration strings' do
|
208
|
+
|
209
|
+
expect(td(0)).to eq('0s')
|
210
|
+
expect(td(60)).to eq('1m')
|
211
|
+
expect(td(61)).to eq('1m1s')
|
212
|
+
expect(td(3661)).to eq('1h1m1s')
|
213
|
+
expect(td(24 * 3600)).to eq('1d')
|
214
|
+
expect(td(7 * 24 * 3600 + 1)).to eq('1w1s')
|
215
|
+
expect(td(30 * 24 * 3600 + 1)).to eq('4w2d1s')
|
216
|
+
end
|
217
|
+
|
218
|
+
it 'ignores seconds and milliseconds if :drop_seconds => true' do
|
219
|
+
|
220
|
+
expect(td(0, :drop_seconds => true)).to eq('0m')
|
221
|
+
expect(td(5, :drop_seconds => true)).to eq('0m')
|
222
|
+
expect(td(61, :drop_seconds => true)).to eq('1m')
|
223
|
+
end
|
224
|
+
|
225
|
+
it 'displays months if :months => true' do
|
226
|
+
|
227
|
+
expect(td(1, :months => true)).to eq('1s')
|
228
|
+
expect(td(30 * 24 * 3600 + 1, :months => true)).to eq('1M1s')
|
229
|
+
end
|
230
|
+
|
231
|
+
it 'turns floats into duration strings' do
|
232
|
+
|
233
|
+
expect(td(0.1)).to eq('100')
|
234
|
+
expect(td(1.1)).to eq('1s100')
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
describe '.to_duration_hash' do
|
239
|
+
|
240
|
+
def tdh(o, opts={})
|
241
|
+
Rufus::Scheduler.to_duration_hash(o, opts)
|
242
|
+
end
|
243
|
+
|
244
|
+
it 'turns integers duration hashes' do
|
245
|
+
|
246
|
+
expect(tdh(0)).to eq({})
|
247
|
+
expect(tdh(60)).to eq({ :m => 1 })
|
248
|
+
end
|
249
|
+
|
250
|
+
it 'turns floats duration hashes' do
|
251
|
+
|
252
|
+
expect(tdh(0.128)).to eq({ :ms => 128 })
|
253
|
+
expect(tdh(60.127)).to eq({ :m => 1, :ms => 127 })
|
254
|
+
end
|
255
|
+
|
256
|
+
it 'drops seconds and milliseconds if :drop_seconds => true' do
|
257
|
+
|
258
|
+
expect(tdh(61.127)).to eq({ :m => 1, :s => 1, :ms => 127 })
|
259
|
+
expect(tdh(61.127, :drop_seconds => true)).to eq({ :m => 1 })
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
@@ -0,0 +1,158 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# Specifying rufus-scheduler
|
4
|
+
#
|
5
|
+
# Wed Apr 17 06:00:59 JST 2013
|
6
|
+
#
|
7
|
+
|
8
|
+
require 'spec_helper'
|
9
|
+
|
10
|
+
|
11
|
+
describe Rufus::Scheduler do
|
12
|
+
|
13
|
+
before :each do
|
14
|
+
@scheduler = Rufus::Scheduler.new
|
15
|
+
end
|
16
|
+
after :each do
|
17
|
+
@scheduler.shutdown
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '#at' do
|
21
|
+
|
22
|
+
it 'raises if the block to schedule is missing' do
|
23
|
+
|
24
|
+
expect {
|
25
|
+
@scheduler.at(Time.now + 3600)
|
26
|
+
}.to raise_error(ArgumentError)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'returns a job id' do
|
30
|
+
|
31
|
+
job_id =
|
32
|
+
@scheduler.at(Time.now + 3600) do
|
33
|
+
end
|
34
|
+
|
35
|
+
expect(job_id.class).to eq(String)
|
36
|
+
expect(job_id).to match(/^at_/)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'returns a job if :job => true' do
|
40
|
+
|
41
|
+
job =
|
42
|
+
@scheduler.at(Time.now + 3600, :job => true) do
|
43
|
+
end
|
44
|
+
|
45
|
+
expect(job.class).to eq(Rufus::Scheduler::AtJob)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'adds a job' do
|
49
|
+
|
50
|
+
t = Time.now + 3600
|
51
|
+
|
52
|
+
@scheduler.at(t) do
|
53
|
+
end
|
54
|
+
|
55
|
+
expect(@scheduler.jobs.size).to eq(1)
|
56
|
+
expect(@scheduler.jobs.first.class).to eq(Rufus::Scheduler::AtJob)
|
57
|
+
expect(@scheduler.jobs.first.time).to eq(t)
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'triggers a job' do
|
61
|
+
|
62
|
+
a = false
|
63
|
+
|
64
|
+
@scheduler.at(Time.now + 0.100) do
|
65
|
+
a = true
|
66
|
+
end
|
67
|
+
|
68
|
+
sleep 0.4
|
69
|
+
|
70
|
+
expect(a).to eq(true)
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'removes the job after execution' do
|
74
|
+
|
75
|
+
@scheduler.at(Time.now + 0.100) do
|
76
|
+
end
|
77
|
+
|
78
|
+
sleep 0.4
|
79
|
+
|
80
|
+
expect(@scheduler.jobs.size).to eq(0)
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'accepts a Time instance' do
|
84
|
+
|
85
|
+
t = Time.now + 3600
|
86
|
+
|
87
|
+
job = @scheduler.at(t, :job => true) {}
|
88
|
+
|
89
|
+
expect(job.time).to eq(t)
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'accepts a time string' do
|
93
|
+
|
94
|
+
job = @scheduler.at('2100-12-12 20:30', :job => true) {}
|
95
|
+
|
96
|
+
expect(job.time).to eq(Time.parse('2100-12-12 20:30'))
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'accepts a time string with a delta timezone' do
|
100
|
+
|
101
|
+
job = @scheduler.at('2100-12-12 20:30 -0200', :job => true) {}
|
102
|
+
|
103
|
+
expect(job.time).to eq(Time.parse('2100-12-12 20:30 -0200'))
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'accepts a time string with a named timezone' do
|
107
|
+
|
108
|
+
job = @scheduler.at('2050-12-12 20:30 Europe/Berlin', :job => true) {}
|
109
|
+
|
110
|
+
expect(job.time.strftime('%c %z')).to eq('Mon Dec 12 20:30:00 2050 +0100')
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'accepts a Chronic string (if Chronic is present)' do
|
114
|
+
|
115
|
+
with_chronic do
|
116
|
+
|
117
|
+
job = @scheduler.schedule_at('next tuesday at 12:00') {}
|
118
|
+
|
119
|
+
expect(job.time.wday).to eq(2)
|
120
|
+
expect(job.time.hour).to eq(12)
|
121
|
+
expect(job.time.min).to eq(0)
|
122
|
+
expect(job.time).to be > Time.now
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'accepts a Chronic string and Chronic options (if Chronic present)' do
|
127
|
+
|
128
|
+
with_chronic do
|
129
|
+
|
130
|
+
job =
|
131
|
+
@scheduler.schedule_at(
|
132
|
+
'may 27th at 12:00', :now => Time.local(Time.now.year + 2, 1, 1)
|
133
|
+
) {}
|
134
|
+
|
135
|
+
expect(job.time.year).to eq(Time.now.year + 2)
|
136
|
+
expect(job.time.month).to eq(5)
|
137
|
+
expect(job.time.day).to eq(27)
|
138
|
+
expect(job.time.hour).to eq(12)
|
139
|
+
expect(job.time.min).to eq(0)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'accepts an ActiveSupport time thinggy'
|
144
|
+
end
|
145
|
+
|
146
|
+
describe '#schedule_at' do
|
147
|
+
|
148
|
+
it 'returns a job' do
|
149
|
+
|
150
|
+
job = @scheduler.schedule_at(Time.now + 3600) do
|
151
|
+
end
|
152
|
+
|
153
|
+
expect(job.class).to eq(Rufus::Scheduler::AtJob)
|
154
|
+
expect(job.id).to match(/^at_/)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
@@ -0,0 +1,66 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# Specifying rufus-scheduler
|
4
|
+
#
|
5
|
+
# Sat Jul 13 04:52:08 JST 2013
|
6
|
+
#
|
7
|
+
# In the train between Bern and Fribourg, riding back
|
8
|
+
# from the @ruvetia drinkup
|
9
|
+
#
|
10
|
+
|
11
|
+
require 'spec_helper'
|
12
|
+
|
13
|
+
|
14
|
+
describe Rufus::Scheduler do
|
15
|
+
|
16
|
+
before :each do
|
17
|
+
@scheduler = Rufus::Scheduler.new
|
18
|
+
end
|
19
|
+
after :each do
|
20
|
+
@scheduler.shutdown
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#cron' do
|
24
|
+
|
25
|
+
it 'schedules' do
|
26
|
+
|
27
|
+
counter = 0
|
28
|
+
|
29
|
+
sleep_until_next_second
|
30
|
+
sleep 0.3 # make sure to schedule right after a scheduler 'tick'
|
31
|
+
|
32
|
+
job =
|
33
|
+
@scheduler.cron '* * * * * *', :job => true do
|
34
|
+
counter = counter + 1
|
35
|
+
end
|
36
|
+
|
37
|
+
sleep_until_next_second
|
38
|
+
sleep_until_next_second
|
39
|
+
sleep 0.3 # be sure to be well into the second
|
40
|
+
|
41
|
+
expect(counter).to eq(2)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'raises if the job frequency is higher than the scheduler frequency' do
|
45
|
+
|
46
|
+
@scheduler.frequency = 10
|
47
|
+
|
48
|
+
expect {
|
49
|
+
@scheduler.cron '* * * * * *' do; end
|
50
|
+
}.to raise_error(ArgumentError)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe '#schedule_cron' do
|
55
|
+
|
56
|
+
it 'returns a CronJob instance' do
|
57
|
+
|
58
|
+
job = @scheduler.schedule_cron '* * * * *' do; end
|
59
|
+
|
60
|
+
expect(job.class).to eq(Rufus::Scheduler::CronJob)
|
61
|
+
expect(job.original).to eq('* * * * *')
|
62
|
+
expect(job.job_id).to match(/^cron_/)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|