rufus-scheduler 2.0.19 → 2.0.20
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 +9 -0
- data/CREDITS.txt +4 -0
- data/README.rdoc +48 -7
- data/lib/rufus/sc/cronline.rb +96 -73
- data/lib/rufus/sc/jobs.rb +1 -1
- data/lib/rufus/sc/rtime.rb +0 -2
- data/lib/rufus/sc/scheduler.rb +59 -1
- data/lib/rufus/sc/version.rb +1 -1
- data/lib/rufus/scheduler.rb +7 -0
- data/spec/cronline_spec.rb +78 -31
- data/spec/exception_spec.rb +17 -1
- data/spec/rtime_spec.rb +1 -1
- data/spec/scheduler_spec.rb +32 -0
- data/spec/spec_base.rb +9 -0
- metadata +25 -32
- data/out.txt +0 -4
data/CHANGELOG.txt
CHANGED
@@ -2,6 +2,15 @@
|
|
2
2
|
= rufus-scheduler CHANGELOG.txt
|
3
3
|
|
4
4
|
|
5
|
+
== rufus-scheduler - 2.0.20 released 2013/07/15
|
6
|
+
|
7
|
+
- add Rufus::Scheduler.new (so that rs 3.0 quickstarts are OK with 2.0.20)
|
8
|
+
- implement CronLine#previous_time(now=Time.now) (Idea Matteo Cerutti)
|
9
|
+
- throw ArgumentError for invalid cron lines (Thanks Aimee Rose)
|
10
|
+
- cron 0 vs 24 hour case straightening (Thanks Aimee Rose)
|
11
|
+
- support for sun#L or sun#-2 in cron lines
|
12
|
+
|
13
|
+
|
5
14
|
== rufus-scheduler - 2.0.19 released 2013/05/07
|
6
15
|
|
7
16
|
- raise ArgumentError on <= 0.0 "every" frequency (Thanks Lucy Fu)
|
data/CREDITS.txt
CHANGED
@@ -4,6 +4,9 @@
|
|
4
4
|
|
5
5
|
== Contributors
|
6
6
|
|
7
|
+
- Thomas Sevestre (https://github.com/thomassevestre) :exception option
|
8
|
+
- Matteo Cerutti - last_time / previous_time idea (and initial implementation)
|
9
|
+
- Aimee Rose (https://github.com/AimeeRose) cronline and > 24
|
7
10
|
- Lucy Fu (https://github.com/lfu) arg error on <= 0 "every" freq
|
8
11
|
- Rainux Luo (https://github.com/rainux) multiple mutexes
|
9
12
|
- Andrew Davey (https://github.com/asdavey) "L" in cron lines
|
@@ -22,6 +25,7 @@
|
|
22
25
|
|
23
26
|
== Feedback
|
24
27
|
|
28
|
+
- Hongli Lai - Scheduler#stop(:terminate => true) request
|
25
29
|
- Tero Tilus - raises on unsupported/unknown options
|
26
30
|
- Louis Coilliot - Scheduler#running_jobs
|
27
31
|
- Henrique G. Testa - pause/resume concept
|
data/README.rdoc
CHANGED
@@ -98,12 +98,18 @@ The timezones are the ones supported by the 'tzinfo' rubygem (http://tzinfo.ruby
|
|
98
98
|
|
99
99
|
The timezone support was contributed by Tanzeeb Khalili.
|
100
100
|
|
101
|
-
|
101
|
+
"monthdays" are supported
|
102
102
|
|
103
103
|
scheduler.cron '0 22 * * sun#1,sun#2' do
|
104
104
|
# every first and second sunday of the month, at 22:00
|
105
105
|
end
|
106
106
|
|
107
|
+
It's also OK (since 2.0.19) to use L (for last monthday) or negative numbers.
|
108
|
+
|
109
|
+
scheduler.cron '0 22 * * sun#-1' do
|
110
|
+
# every last sunday of the month, at 22:00
|
111
|
+
end
|
112
|
+
|
107
113
|
|
108
114
|
== scheduler.join
|
109
115
|
|
@@ -132,6 +138,18 @@ You shouldn't be exposed to this issue when using EventMachine, since while runn
|
|
132
138
|
DO NOT CALL this #join method if you're running rufus-scheduler from Rails or Sinatra or any application that's already some kind of 'daemon'. It's not necessary! #join is meant for small standalone scripts.
|
133
139
|
|
134
140
|
|
141
|
+
== schedule.stop
|
142
|
+
|
143
|
+
scheduler.stop
|
144
|
+
|
145
|
+
This call stops the scheduler. It doesn't unschedule jobs. If there are running jobs, they're left running.
|
146
|
+
|
147
|
+
If you need to stop the scheduler and wait for all the jobs currently running to finish (without killing them), rufus-scheduler 2.0.20 brings a new :terminate => true option.
|
148
|
+
|
149
|
+
scheduler.stop(:terminate => true)
|
150
|
+
# returns once all the jobs have been unscheduled and no jobs is running
|
151
|
+
|
152
|
+
|
135
153
|
== block parameters
|
136
154
|
|
137
155
|
Scheduled blocks accept 0 or 1 parameter (this unique parameter is the job
|
@@ -319,7 +337,7 @@ The chronic gem may help (http://chronic.rubyforge.org/) :
|
|
319
337
|
require 'chronic' # sudo gem install chronic
|
320
338
|
|
321
339
|
scheduler.every '3h', :first_at => Chronic.parse('this tuesday 5:00') do
|
322
|
-
# do something starting this
|
340
|
+
# do something starting this tuesday
|
323
341
|
end
|
324
342
|
|
325
343
|
Note : setting a :first_at/:first_in in the past will get rufus-scheduler to trigger for all the past schedules until now. Adding :discard_past => true will prevent this.
|
@@ -520,6 +538,15 @@ For backward compatibility, overriding #log_exception is still OK :
|
|
520
538
|
|
521
539
|
Note that an every job or a cron job will stay scheduled even if it experiences an exception.
|
522
540
|
|
541
|
+
By default, all exceptions are rescued. It's easy to customize that behaviour :
|
542
|
+
|
543
|
+
scheduler = Rufus::Scheduler::PlainScheduler.start_new(:exception => StandardError)
|
544
|
+
# or
|
545
|
+
#scheduler = Rufus::Scheduler::EmScheduler.start_new(:exception => StandardError)
|
546
|
+
|
547
|
+
scheduler.in "3s" do
|
548
|
+
exit
|
549
|
+
end
|
523
550
|
|
524
551
|
== frequency
|
525
552
|
|
@@ -555,7 +582,7 @@ More and more ruby applications are using EventMachine. This flavour of the sche
|
|
555
582
|
|
556
583
|
== with Passenger
|
557
584
|
|
558
|
-
"it terminates for no apparent reason
|
585
|
+
"it terminates for no apparent reason!"
|
559
586
|
|
560
587
|
https://github.com/jmettraux/rufus-scheduler/issues/issue/10
|
561
588
|
|
@@ -576,22 +603,35 @@ The 'tzinfo' rubygem.
|
|
576
603
|
The ruby gem 'eventmachine' if you use Rufus::Scheduler::EmScheduler, else no other dependencies.
|
577
604
|
|
578
605
|
|
579
|
-
==
|
606
|
+
== support
|
607
|
+
|
608
|
+
If you identify and pinpoint a bug, please use the issue tracker. If you are unsure whether the fault lies in rufus-scheduler or in your software, use the mailing list. The mailing list is Google-powered, so, yes, you can search it.
|
609
|
+
|
610
|
+
Please read carefully: http://www.chiark.greenend.org.uk/~sgtatham/bugs.html (then re-read it).
|
611
|
+
|
612
|
+
|
613
|
+
=== mailing list
|
580
614
|
|
581
615
|
On the rufus-ruby list :
|
582
616
|
|
583
617
|
http://groups.google.com/group/rufus-ruby
|
584
618
|
|
619
|
+
Newcomers' first message is held for moderation in order to prevent spam. Further messages are not held.
|
620
|
+
|
621
|
+
|
622
|
+
=== issue tracker
|
585
623
|
|
586
|
-
|
624
|
+
https://github.com/jmettraux/rufus-scheduler/issues
|
587
625
|
|
588
|
-
http://rubyforge.org/tracker/?atid=18584&group_id=4812&func=browse
|
589
626
|
|
627
|
+
=== irc
|
590
628
|
|
591
|
-
|
629
|
+
If you come over to #ruote to ask for rufus-scheduler help, please make sure to 1) say hello 2) be polite 3) state that you're looking for rufus-scheduler help 4) remember that we cannot read your mind and guess whatever lies in your deployment.
|
592
630
|
|
593
631
|
irc.freenode.net #ruote
|
594
632
|
|
633
|
+
If there is no answer on IRC, use the mailing list.
|
634
|
+
|
595
635
|
|
596
636
|
== source
|
597
637
|
|
@@ -618,3 +658,4 @@ http://rufus.rubyforge.org
|
|
618
658
|
== license
|
619
659
|
|
620
660
|
MIT
|
661
|
+
|
data/lib/rufus/sc/cronline.rb
CHANGED
@@ -33,6 +33,9 @@ module Rufus
|
|
33
33
|
#
|
34
34
|
class CronLine
|
35
35
|
|
36
|
+
DAY_S = 24 * 3600
|
37
|
+
WEEK_S = 7 * DAY_S
|
38
|
+
|
36
39
|
# The string used for creating this cronline instance.
|
37
40
|
#
|
38
41
|
attr_reader :original
|
@@ -74,7 +77,7 @@ module Rufus
|
|
74
77
|
|
75
78
|
raise ArgumentError.new(
|
76
79
|
"invalid cronline: '#{line}'"
|
77
|
-
) if es && es.find { |e| ! e.is_a?(
|
80
|
+
) if es && es.find { |e| ! e.is_a?(Fixnum) }
|
78
81
|
end
|
79
82
|
end
|
80
83
|
|
@@ -125,25 +128,21 @@ module Rufus
|
|
125
128
|
time = @timezone ? @timezone.utc_to_local(now.getutc) : now
|
126
129
|
|
127
130
|
time = time - time.usec * 1e-6 + 1
|
128
|
-
#
|
131
|
+
# small adjustment before starting
|
129
132
|
|
130
133
|
loop do
|
131
134
|
|
132
135
|
unless date_match?(time)
|
133
|
-
time += (24 - time.hour) * 3600 - time.min * 60 - time.sec
|
134
|
-
next
|
136
|
+
time += (24 - time.hour) * 3600 - time.min * 60 - time.sec; next
|
135
137
|
end
|
136
138
|
unless sub_match?(time, :hour, @hours)
|
137
|
-
time += (60 - time.min) * 60 - time.sec
|
138
|
-
next
|
139
|
+
time += (60 - time.min) * 60 - time.sec; next
|
139
140
|
end
|
140
141
|
unless sub_match?(time, :min, @minutes)
|
141
|
-
time += 60 - time.sec
|
142
|
-
next
|
142
|
+
time += 60 - time.sec; next
|
143
143
|
end
|
144
144
|
unless sub_match?(time, :sec, @seconds)
|
145
|
-
time += 1
|
146
|
-
next
|
145
|
+
time += 1; next
|
147
146
|
end
|
148
147
|
|
149
148
|
break
|
@@ -157,6 +156,28 @@ module Rufus
|
|
157
156
|
time
|
158
157
|
end
|
159
158
|
|
159
|
+
# Returns the previous the cronline matched. It's like next_time, but
|
160
|
+
# for the past.
|
161
|
+
#
|
162
|
+
def previous_time(now=Time.now)
|
163
|
+
|
164
|
+
# looks back by slices of two hours,
|
165
|
+
#
|
166
|
+
# finds for '* * * * sun', '* * 13 * *' and '0 12 13 * *'
|
167
|
+
# starting 1970, 1, 1 in 1.8 to 2 seconds (says Rspec)
|
168
|
+
|
169
|
+
start = current = now - 2 * 3600
|
170
|
+
result = nil
|
171
|
+
|
172
|
+
loop do
|
173
|
+
nex = next_time(current)
|
174
|
+
return (result ? result : previous_time(start)) if nex > now
|
175
|
+
result = current = nex
|
176
|
+
end
|
177
|
+
|
178
|
+
# never reached
|
179
|
+
end
|
180
|
+
|
160
181
|
# Returns an array of 6 arrays (seconds, minutes, hours, days,
|
161
182
|
# months, weekdays).
|
162
183
|
# This method is used by the cronline unit tests.
|
@@ -190,15 +211,18 @@ module Rufus
|
|
190
211
|
|
191
212
|
items.each do |it|
|
192
213
|
|
193
|
-
if it.match(
|
214
|
+
if m = it.match(/^(.+)#(l|-?[12345])$/)
|
194
215
|
|
195
216
|
raise ArgumentError.new(
|
196
217
|
"ranges are not supported for monthdays (#{it})"
|
197
|
-
) if
|
218
|
+
) if m[1].index('-')
|
219
|
+
|
220
|
+
expr = it.gsub(/#l/, '#-1')
|
198
221
|
|
199
|
-
(monthdays ||= []) <<
|
222
|
+
(monthdays ||= []) << expr
|
200
223
|
|
201
224
|
else
|
225
|
+
|
202
226
|
expr = it.dup
|
203
227
|
WEEKDAYS.each_with_index { |a, i| expr.gsub!(/#{a}/, i.to_s) }
|
204
228
|
|
@@ -221,110 +245,109 @@ module Rufus
|
|
221
245
|
def parse_item(item, min, max)
|
222
246
|
|
223
247
|
return nil if item == '*'
|
224
|
-
return [ 'L' ] if item == 'L'
|
225
|
-
return parse_list(item, min, max) if item.index(',')
|
226
|
-
return parse_range(item, min, max) if item.match(/[*-\/]/)
|
227
248
|
|
228
|
-
|
229
|
-
|
230
|
-
i = min if i < min
|
231
|
-
i = max if i > max
|
232
|
-
|
233
|
-
[ i ]
|
234
|
-
end
|
235
|
-
|
236
|
-
def parse_list(item, min, max)
|
237
|
-
|
238
|
-
l = item.split(',').collect { |i| parse_range(i, min, max) }.flatten
|
249
|
+
r = item.split(',').map { |i| parse_range(i.strip, min, max) }.flatten
|
239
250
|
|
240
251
|
raise ArgumentError.new(
|
241
252
|
"found duplicates in #{item.inspect}"
|
242
|
-
) if
|
253
|
+
) if r.uniq.size < r.size
|
243
254
|
|
244
|
-
|
255
|
+
r
|
245
256
|
end
|
246
257
|
|
258
|
+
RANGE_REGEX = /^(\*|\d{1,2})(?:-(\d{1,2}))?(?:\/(\d{1,2}))?$/
|
259
|
+
|
247
260
|
def parse_range(item, min, max)
|
248
261
|
|
249
|
-
|
250
|
-
slash = item.index('/')
|
262
|
+
return %w[ L ] if item == 'L'
|
251
263
|
|
252
|
-
|
264
|
+
m = item.match(RANGE_REGEX)
|
253
265
|
|
254
266
|
raise ArgumentError.new(
|
255
|
-
"
|
256
|
-
|
257
|
-
) if item.index('L')
|
267
|
+
"cannot parse #{item.inspect}"
|
268
|
+
) unless m
|
258
269
|
|
259
|
-
|
270
|
+
sta = m[1]
|
271
|
+
sta = sta == '*' ? min : sta.to_i
|
260
272
|
|
261
|
-
|
262
|
-
|
273
|
+
edn = m[2]
|
274
|
+
edn = edn ? edn.to_i : sta
|
275
|
+
edn = max if m[1] == '*'
|
263
276
|
|
264
|
-
|
277
|
+
inc = m[3]
|
278
|
+
inc = inc ? inc.to_i : 1
|
265
279
|
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
else # case */x
|
270
|
-
|
271
|
-
istart = min
|
272
|
-
iend = max
|
273
|
-
end
|
274
|
-
|
275
|
-
istart = min if istart < min
|
276
|
-
iend = max if iend > max
|
280
|
+
raise ArgumentError.new(
|
281
|
+
"#{item.inspect} is not in range #{min}..#{max}"
|
282
|
+
) if sta < min or edn > max
|
277
283
|
|
278
|
-
|
284
|
+
r = []
|
285
|
+
val = sta
|
279
286
|
|
280
|
-
value = istart
|
281
287
|
loop do
|
282
|
-
|
283
|
-
|
284
|
-
|
288
|
+
v = val
|
289
|
+
v = 0 if max == 24 && v == 24
|
290
|
+
r << v
|
291
|
+
break if inc == 1 && val == edn
|
292
|
+
val += inc
|
293
|
+
break if inc > 1 && val > edn
|
294
|
+
val = min if val > max
|
285
295
|
end
|
286
296
|
|
287
|
-
|
297
|
+
r.uniq
|
288
298
|
end
|
289
299
|
|
290
|
-
def sub_match?(time, accessor, values
|
300
|
+
def sub_match?(time, accessor, values)
|
291
301
|
|
292
|
-
value
|
293
|
-
if values == :none
|
294
|
-
[ time, accessor ]
|
295
|
-
else
|
296
|
-
[ time.send(accessor), values ]
|
297
|
-
end
|
302
|
+
value = time.send(accessor)
|
298
303
|
|
299
304
|
return true if values.nil?
|
300
|
-
return true if values.include?('L') && (time +
|
305
|
+
return true if values.include?('L') && (time + DAY_S).day == 1
|
306
|
+
|
307
|
+
return true if value == 0 && accessor == :hour && values.include?(24)
|
301
308
|
|
302
309
|
values.include?(value)
|
303
310
|
end
|
304
311
|
|
312
|
+
def monthday_match?(date, values)
|
313
|
+
|
314
|
+
return true if values.nil?
|
315
|
+
|
316
|
+
today_values = monthdays(date)
|
317
|
+
|
318
|
+
(today_values & values).any?
|
319
|
+
end
|
320
|
+
|
305
321
|
def date_match?(date)
|
306
322
|
|
307
323
|
return false unless sub_match?(date, :day, @days)
|
308
324
|
return false unless sub_match?(date, :month, @months)
|
309
325
|
return false unless sub_match?(date, :wday, @weekdays)
|
310
|
-
return false unless
|
326
|
+
return false unless monthday_match?(date, @monthdays)
|
311
327
|
true
|
312
328
|
end
|
313
329
|
|
314
|
-
|
330
|
+
def monthdays(date)
|
331
|
+
|
332
|
+
pos = 1
|
333
|
+
d = date.dup
|
315
334
|
|
316
|
-
|
335
|
+
loop do
|
336
|
+
d = d - WEEK_S
|
337
|
+
break if d.month != date.month
|
338
|
+
pos = pos + 1
|
339
|
+
end
|
317
340
|
|
318
|
-
|
319
|
-
|
341
|
+
neg = -1
|
342
|
+
d = date.dup
|
320
343
|
|
321
344
|
loop do
|
322
|
-
|
323
|
-
break if
|
324
|
-
|
345
|
+
d = d + WEEK_S
|
346
|
+
break if d.month != date.month
|
347
|
+
neg = neg - 1
|
325
348
|
end
|
326
349
|
|
327
|
-
"#{WEEKDAYS[date.wday]}##{
|
350
|
+
[ "#{WEEKDAYS[date.wday]}##{pos}", "#{WEEKDAYS[date.wday]}##{neg}" ]
|
328
351
|
end
|
329
352
|
end
|
330
353
|
end
|
data/lib/rufus/sc/jobs.rb
CHANGED
data/lib/rufus/sc/rtime.rb
CHANGED
data/lib/rufus/sc/scheduler.rb
CHANGED
@@ -327,6 +327,21 @@ module Rufus::Scheduler
|
|
327
327
|
}.compact
|
328
328
|
end
|
329
329
|
|
330
|
+
# This is a blocking call, it will return when all the jobs have been
|
331
|
+
# unscheduled, waiting for any running one to finish before unscheduling
|
332
|
+
# it.
|
333
|
+
#
|
334
|
+
def terminate_all_jobs
|
335
|
+
|
336
|
+
all_jobs.each do |job_id, job|
|
337
|
+
job.unschedule
|
338
|
+
end
|
339
|
+
|
340
|
+
while running_jobs.size > 0
|
341
|
+
sleep 0.01
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
330
345
|
protected
|
331
346
|
|
332
347
|
# Returns a job queue instance.
|
@@ -455,9 +470,23 @@ module Rufus::Scheduler
|
|
455
470
|
"#{self.class} - #{Rufus::Scheduler::VERSION}"
|
456
471
|
end
|
457
472
|
|
473
|
+
# Stops this scheduler.
|
474
|
+
#
|
475
|
+
# == :terminate => true
|
476
|
+
#
|
477
|
+
# If the option :terminate is set to true,
|
478
|
+
# the method will return once all the jobs have been unscheduled and
|
479
|
+
# are done with their current run if any.
|
480
|
+
#
|
481
|
+
# (note that if a job is
|
482
|
+
# currently running, this method will wait for it to terminate, it
|
483
|
+
# will not interrupt the job run).
|
484
|
+
#
|
458
485
|
def stop(opts={})
|
459
486
|
|
460
487
|
@thread.exit
|
488
|
+
|
489
|
+
terminate_all_jobs if opts[:terminate]
|
461
490
|
end
|
462
491
|
|
463
492
|
def join
|
@@ -487,9 +516,24 @@ module Rufus::Scheduler
|
|
487
516
|
end
|
488
517
|
end
|
489
518
|
|
490
|
-
|
519
|
+
|
520
|
+
# Stops this scheduler.
|
521
|
+
#
|
522
|
+
# == :terminate => true
|
523
|
+
#
|
524
|
+
# If the option :terminate is set to true,
|
525
|
+
# the method will return once all the jobs have been unscheduled and
|
526
|
+
# are done with their current run if any.
|
527
|
+
#
|
528
|
+
# (note that if a job is
|
529
|
+
# currently running, this method will wait for it to terminate, it
|
530
|
+
# will not interrupt the job run).
|
531
|
+
#
|
532
|
+
def stop(opts={})
|
491
533
|
|
492
534
|
trap(@options[:signal] || 10)
|
535
|
+
|
536
|
+
terminate_all_jobs if opts[:terminate]
|
493
537
|
end
|
494
538
|
end
|
495
539
|
|
@@ -530,13 +574,27 @@ module Rufus::Scheduler
|
|
530
574
|
|
531
575
|
# Stops the scheduler.
|
532
576
|
#
|
577
|
+
# == :stop_em => true
|
578
|
+
#
|
533
579
|
# If the :stop_em option is passed and set to true, it will stop the
|
534
580
|
# EventMachine (but only if it started the EM by itself !).
|
535
581
|
#
|
582
|
+
# == :terminate => true
|
583
|
+
#
|
584
|
+
# If the option :terminate is set to true,
|
585
|
+
# the method will return once all the jobs have been unscheduled and
|
586
|
+
# are done with their current run if any.
|
587
|
+
#
|
588
|
+
# (note that if a job is
|
589
|
+
# currently running, this method will wait for it to terminate, it
|
590
|
+
# will not interrupt the job run).
|
591
|
+
#
|
536
592
|
def stop(opts={})
|
537
593
|
|
538
594
|
@timer.cancel
|
539
595
|
|
596
|
+
terminate_all_jobs if opts[:terminate]
|
597
|
+
|
540
598
|
EM.stop if opts[:stop_em] and @em_thread
|
541
599
|
end
|
542
600
|
|
data/lib/rufus/sc/version.rb
CHANGED
data/lib/rufus/scheduler.rb
CHANGED
@@ -28,6 +28,13 @@ require 'rufus/sc/scheduler'
|
|
28
28
|
|
29
29
|
module Rufus::Scheduler
|
30
30
|
|
31
|
+
# Starts and return a new instance of a PlainScheduler.
|
32
|
+
#
|
33
|
+
def self.new(opts={})
|
34
|
+
|
35
|
+
PlainScheduler.start_new(opts)
|
36
|
+
end
|
37
|
+
|
31
38
|
# A quick way to get a scheduler up an running
|
32
39
|
#
|
33
40
|
# require 'rubygems'
|
data/spec/cronline_spec.rb
CHANGED
@@ -24,13 +24,6 @@ describe Rufus::CronLine do
|
|
24
24
|
cl(line).to_array.should == array
|
25
25
|
end
|
26
26
|
|
27
|
-
def local(*args)
|
28
|
-
Time.local(*args)
|
29
|
-
end
|
30
|
-
def utc(*args)
|
31
|
-
Time.utc(*args)
|
32
|
-
end
|
33
|
-
|
34
27
|
describe '.new' do
|
35
28
|
|
36
29
|
it 'interprets cron strings correctly' do
|
@@ -54,6 +47,13 @@ describe Rufus::CronLine do
|
|
54
47
|
to_a '1-5 * * * * *', [ [1,2,3,4,5], nil, nil, nil, nil, nil, nil, nil ]
|
55
48
|
|
56
49
|
to_a '0 0 1 1 *', [ [0], [0], [0], [1], [1], nil, nil, nil ]
|
50
|
+
|
51
|
+
to_a '0 23-24 * * *', [ [0], [0], [23, 0], nil, nil, nil, nil, nil ]
|
52
|
+
#
|
53
|
+
# as reported by Aimee Rose in
|
54
|
+
# https://github.com/jmettraux/rufus-scheduler/issues/56
|
55
|
+
|
56
|
+
to_a '0 23-2 * * *', [ [0], [0], [23, 0, 1, 2], nil, nil, nil, nil, nil ]
|
57
57
|
end
|
58
58
|
|
59
59
|
it 'rejects invalid weekday expressions' do
|
@@ -84,7 +84,7 @@ describe Rufus::CronLine do
|
|
84
84
|
|
85
85
|
to_a(
|
86
86
|
'0 */2 * * *',
|
87
|
-
[ [0], [0], (0..
|
87
|
+
[ [0], [0], (0..11).collect { |e| e * 2 }, nil, nil, nil, nil, nil ])
|
88
88
|
to_a(
|
89
89
|
'0 7-23/2 * * *',
|
90
90
|
[ [0], [0], (7..23).select { |e| e.odd? }, nil, nil, nil, nil, nil ])
|
@@ -105,7 +105,8 @@ describe Rufus::CronLine do
|
|
105
105
|
to_a '09 * * * *', [ [0], [9], nil, nil, nil, nil, nil, nil ]
|
106
106
|
to_a '09-12 * * * *', [ [0], [9, 10, 11, 12], nil, nil, nil, nil, nil, nil ]
|
107
107
|
to_a '07-08 * * * *', [ [0], [7, 8], nil, nil, nil, nil, nil, nil ]
|
108
|
-
to_a '* */08 * * *', [ [0], nil, [0, 8, 16
|
108
|
+
to_a '* */08 * * *', [ [0], nil, [0, 8, 16], nil, nil, nil, nil, nil ]
|
109
|
+
to_a '* */07 * * *', [ [0], nil, [0, 7, 14, 21], nil, nil, nil, nil, nil ]
|
109
110
|
to_a '* 01-09/04 * * *', [ [0], nil, [1, 5, 9], nil, nil, nil, nil, nil ]
|
110
111
|
to_a '* * * * 06', [ [0], nil, nil, nil, nil, [6], nil, nil ]
|
111
112
|
end
|
@@ -132,6 +133,18 @@ describe Rufus::CronLine do
|
|
132
133
|
|
133
134
|
lambda { cl '* L * * *'}.should raise_error(ArgumentError)
|
134
135
|
end
|
136
|
+
|
137
|
+
it 'raises for out of range input' do
|
138
|
+
|
139
|
+
lambda { cl '60-62 * * * *'}.should raise_error(ArgumentError)
|
140
|
+
lambda { cl '62 * * * *'}.should raise_error(ArgumentError)
|
141
|
+
lambda { cl '60 * * * *'}.should raise_error(ArgumentError)
|
142
|
+
lambda { cl '* 25-26 * * *'}.should raise_error(ArgumentError)
|
143
|
+
lambda { cl '* 25 * * *'}.should raise_error(ArgumentError)
|
144
|
+
#
|
145
|
+
# as reported by Aimee Rose in
|
146
|
+
# https://github.com/jmettraux/rufus-scheduler/pull/58
|
147
|
+
end
|
135
148
|
end
|
136
149
|
|
137
150
|
describe '#next_time' do
|
@@ -151,9 +164,16 @@ describe Rufus::CronLine do
|
|
151
164
|
|
152
165
|
nt('10 12 13 12 *', now).should == now + 29938200
|
153
166
|
# this one is slow (1 year == 3 seconds)
|
167
|
+
#
|
168
|
+
# historical note:
|
169
|
+
# (comment made in 2006 or 2007, the underlying libs got better and
|
170
|
+
# that slowness is gone)
|
154
171
|
|
155
172
|
nt('0 0 * * thu', now).should == now + 604800
|
156
173
|
|
174
|
+
nt('0 0 * * *', now).should == now + 24 * 3600
|
175
|
+
nt('0 24 * * *', now).should == now + 24 * 3600
|
176
|
+
|
157
177
|
now = local(2008, 12, 31, 23, 59, 59, 0)
|
158
178
|
|
159
179
|
nt('* * * * *', now).should == now + 1
|
@@ -225,34 +245,56 @@ describe Rufus::CronLine do
|
|
225
245
|
|
226
246
|
it 'computes the next time correctly when there is a sun#2 involved' do
|
227
247
|
|
228
|
-
|
248
|
+
nt('* * * * sun#1', local(1970, 1, 1)).should == local(1970, 1, 4)
|
249
|
+
nt('* * * * sun#2', local(1970, 1, 1)).should == local(1970, 1, 11)
|
229
250
|
|
230
|
-
nt('* * * * sun#
|
231
|
-
|
251
|
+
nt('* * * * sun#2', local(1970, 1, 12)).should == local(1970, 2, 8)
|
252
|
+
end
|
232
253
|
|
233
|
-
|
254
|
+
it 'computes the next time correctly when there is a sun#2,sun#3 involved' do
|
234
255
|
|
235
|
-
nt('* * * * sun#2',
|
256
|
+
nt('* * * * sun#2,sun#3', local(1970, 1, 1)).should == local(1970, 1, 11)
|
257
|
+
nt('* * * * sun#2,sun#3', local(1970, 1, 12)).should == local(1970, 1, 18)
|
236
258
|
end
|
237
259
|
|
238
|
-
it '
|
260
|
+
it 'understands sun#L' do
|
239
261
|
|
240
|
-
|
262
|
+
nt('* * * * sun#L', local(1970, 1, 1)).should == local(1970, 1, 25)
|
263
|
+
end
|
264
|
+
|
265
|
+
it 'understands sun#-1' do
|
266
|
+
|
267
|
+
nt('* * * * sun#-1', local(1970, 1, 1)).should == local(1970, 1, 25)
|
268
|
+
end
|
269
|
+
|
270
|
+
it 'understands sun#-2' do
|
271
|
+
|
272
|
+
nt('* * * * sun#-2', local(1970, 1, 1)).should == local(1970, 1, 18)
|
273
|
+
end
|
241
274
|
|
242
|
-
|
275
|
+
it 'computes the next time correctly when "L" (last day of month)' do
|
243
276
|
|
244
|
-
|
277
|
+
nt('* * L * *', lo(1970, 1, 1)).should == lo(1970, 1, 31)
|
278
|
+
nt('* * L * *', lo(1970, 2, 1)).should == lo(1970, 2, 28)
|
279
|
+
nt('* * L * *', lo(1972, 2, 1)).should == lo(1972, 2, 29)
|
280
|
+
nt('* * L * *', lo(1970, 4, 1)).should == lo(1970, 4, 30)
|
281
|
+
end
|
282
|
+
end
|
245
283
|
|
246
|
-
|
284
|
+
describe '#previous_time' do
|
285
|
+
|
286
|
+
def pt(cronline, now)
|
287
|
+
Rufus::CronLine.new(cronline).previous_time(now)
|
247
288
|
end
|
248
289
|
|
249
|
-
|
290
|
+
it 'returns the previous time the cron should have triggered' do
|
291
|
+
|
292
|
+
pt('* * * * sun', lo(1970, 1, 1)).should == lo(1969, 12, 28, 23, 59, 00)
|
293
|
+
pt('* * 13 * *', lo(1970, 1, 1)).should == lo(1969, 12, 13, 23, 59, 00)
|
294
|
+
pt('0 12 13 * *', lo(1970, 1, 1)).should == lo(1969, 12, 13, 12, 00)
|
250
295
|
|
251
|
-
|
252
|
-
|
253
|
-
nt('* * L * *', local(1972,2,1)).should == local(1972, 2, 29)
|
254
|
-
nt('* * L * *', local(1970,4,1)).should == local(1970, 4, 30)
|
255
|
-
end
|
296
|
+
pt('* * * * * sun', lo(1970, 1, 1)).should == lo(1969, 12, 28, 23, 59, 59)
|
297
|
+
end
|
256
298
|
end
|
257
299
|
|
258
300
|
describe '#matches?' do
|
@@ -325,16 +367,21 @@ describe Rufus::CronLine do
|
|
325
367
|
end
|
326
368
|
end
|
327
369
|
|
328
|
-
describe '
|
370
|
+
describe '#monthdays' do
|
329
371
|
|
330
372
|
it 'returns the appropriate "sun#2"-like string' do
|
331
373
|
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
374
|
+
class Rufus::CronLine
|
375
|
+
public :monthdays
|
376
|
+
end
|
377
|
+
|
378
|
+
cl = Rufus::CronLine.new('* * * * *')
|
379
|
+
|
380
|
+
cl.monthdays(local(1970, 1, 1)).should == %w[ thu#1 thu#-5 ]
|
381
|
+
cl.monthdays(local(1970, 1, 7)).should == %w[ wed#1 wed#-4 ]
|
382
|
+
cl.monthdays(local(1970, 1, 14)).should == %w[ wed#2 wed#-3 ]
|
336
383
|
|
337
|
-
|
384
|
+
cl.monthdays(local(2011, 3, 11)).should == %w[ fri#2 fri#-3 ]
|
338
385
|
end
|
339
386
|
end
|
340
387
|
end
|
data/spec/exception_spec.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
#
|
3
2
|
# Specifying rufus-scheduler
|
4
3
|
#
|
@@ -93,5 +92,22 @@ describe SCHEDULER_CLASS do
|
|
93
92
|
$j.class.should == Rufus::Scheduler::InJob
|
94
93
|
$e.to_s.should == 'Houston we have a problem'
|
95
94
|
end
|
95
|
+
|
96
|
+
it 'allow custom exception rescue' do
|
97
|
+
@s.options[:exception]= StandardError
|
98
|
+
|
99
|
+
job = @s.in 0 do
|
100
|
+
exit
|
101
|
+
end
|
102
|
+
|
103
|
+
@e= nil
|
104
|
+
begin
|
105
|
+
wait_next_tick
|
106
|
+
rescue SystemExit => e
|
107
|
+
@e= e
|
108
|
+
end
|
109
|
+
|
110
|
+
@e.should_not == nil
|
111
|
+
end
|
96
112
|
end
|
97
113
|
|
data/spec/rtime_spec.rb
CHANGED
data/spec/scheduler_spec.rb
CHANGED
@@ -200,6 +200,38 @@ describe SCHEDULER_CLASS do
|
|
200
200
|
end
|
201
201
|
end
|
202
202
|
end
|
203
|
+
|
204
|
+
context 'termination' do
|
205
|
+
|
206
|
+
describe '#stop(true)' do
|
207
|
+
|
208
|
+
it 'terminates the scheduler, blocking until all the jobs are unscheduled' do
|
209
|
+
|
210
|
+
$every = nil
|
211
|
+
$cron = nil
|
212
|
+
|
213
|
+
s = start_scheduler
|
214
|
+
s.every '1s' do
|
215
|
+
$every = :in
|
216
|
+
sleep 0.5
|
217
|
+
$every = :out
|
218
|
+
end
|
219
|
+
s.cron '* * * * * *' do
|
220
|
+
$cron = :in
|
221
|
+
sleep 0.5
|
222
|
+
$cron = :out
|
223
|
+
end
|
224
|
+
|
225
|
+
sleep 2
|
226
|
+
|
227
|
+
s.stop(:terminate => true)
|
228
|
+
|
229
|
+
s.jobs.size.should == 0
|
230
|
+
$every.should == :out
|
231
|
+
$cron.should == :out
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
203
235
|
end
|
204
236
|
|
205
237
|
describe 'Rufus::Scheduler#start_new' do
|
data/spec/spec_base.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rufus-scheduler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.20
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-07-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: tzinfo
|
@@ -67,39 +67,38 @@ extensions: []
|
|
67
67
|
extra_rdoc_files: []
|
68
68
|
files:
|
69
69
|
- Rakefile
|
70
|
-
- lib/rufus
|
71
|
-
- lib/rufus/
|
72
|
-
- lib/rufus/sc/jobqueues.rb
|
73
|
-
- lib/rufus/sc/jobs.rb
|
74
|
-
- lib/rufus/sc/rtime.rb
|
70
|
+
- lib/rufus-scheduler.rb
|
71
|
+
- lib/rufus/scheduler.rb
|
75
72
|
- lib/rufus/sc/scheduler.rb
|
73
|
+
- lib/rufus/sc/rtime.rb
|
76
74
|
- lib/rufus/sc/version.rb
|
77
|
-
- lib/rufus/
|
78
|
-
- lib/rufus
|
79
|
-
-
|
80
|
-
-
|
81
|
-
- spec/
|
82
|
-
- spec/
|
83
|
-
- spec/
|
84
|
-
- spec/every_spec.rb
|
75
|
+
- lib/rufus/sc/cronline.rb
|
76
|
+
- lib/rufus/sc/jobs.rb
|
77
|
+
- lib/rufus/sc/jobqueues.rb
|
78
|
+
- lib/rufus/otime.rb
|
79
|
+
- spec/job_spec.rb
|
80
|
+
- spec/stress_schedule_unschedule_spec.rb
|
81
|
+
- spec/schedulable_spec.rb
|
85
82
|
- spec/exception_spec.rb
|
86
83
|
- spec/in_spec.rb
|
87
|
-
- spec/
|
88
|
-
- spec/
|
84
|
+
- spec/timeout_spec.rb
|
85
|
+
- spec/at_spec.rb
|
86
|
+
- spec/at_in_spec.rb
|
87
|
+
- spec/spec_base.rb
|
88
|
+
- spec/cronline_spec.rb
|
89
89
|
- spec/rtime_spec.rb
|
90
|
-
- spec/
|
90
|
+
- spec/mutex_spec.rb
|
91
91
|
- spec/scheduler_spec.rb
|
92
|
-
- spec/
|
93
|
-
- spec/
|
94
|
-
- spec/
|
95
|
-
- test/kjw.rb
|
92
|
+
- spec/blocking_spec.rb
|
93
|
+
- spec/every_spec.rb
|
94
|
+
- spec/cron_spec.rb
|
96
95
|
- test/t.rb
|
96
|
+
- test/kjw.rb
|
97
97
|
- rufus-scheduler.gemspec
|
98
98
|
- CHANGELOG.txt
|
99
|
-
- CREDITS.txt
|
100
|
-
- LICENSE.txt
|
101
|
-
- out.txt
|
102
99
|
- TODO.txt
|
100
|
+
- LICENSE.txt
|
101
|
+
- CREDITS.txt
|
103
102
|
- README.rdoc
|
104
103
|
homepage: http://github.com/jmettraux/rufus-scheduler
|
105
104
|
licenses: []
|
@@ -113,21 +112,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
113
112
|
- - ! '>='
|
114
113
|
- !ruby/object:Gem::Version
|
115
114
|
version: '0'
|
116
|
-
segments:
|
117
|
-
- 0
|
118
|
-
hash: -1513262691769122142
|
119
115
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
120
116
|
none: false
|
121
117
|
requirements:
|
122
118
|
- - ! '>='
|
123
119
|
- !ruby/object:Gem::Version
|
124
120
|
version: '0'
|
125
|
-
segments:
|
126
|
-
- 0
|
127
|
-
hash: -1513262691769122142
|
128
121
|
requirements: []
|
129
122
|
rubyforge_project: rufus
|
130
|
-
rubygems_version: 1.8.
|
123
|
+
rubygems_version: 1.8.23
|
131
124
|
signing_key:
|
132
125
|
specification_version: 3
|
133
126
|
summary: job scheduler for Ruby (at, cron, in and every jobs)
|
data/out.txt
DELETED