rufus-scheduler 3.1.3 → 3.1.4
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.txt +5 -0
- data/CREDITS.txt +1 -0
- data/lib/rufus/scheduler.rb +1 -1
- data/lib/rufus/scheduler/cronline.rb +26 -26
- data/spec/cronline_spec.rb +193 -10
- metadata +2 -2
data/CHANGELOG.txt
CHANGED
@@ -2,6 +2,11 @@
|
|
2
2
|
= rufus-scheduler CHANGELOG.txt
|
3
3
|
|
4
4
|
|
5
|
+
== rufus-scheduler - 3.1.4 released 2015/08/29
|
6
|
+
|
7
|
+
- fix cron issue reported by Jesse https://github.com/jhw-at-prosperworks-com
|
8
|
+
|
9
|
+
|
5
10
|
== rufus-scheduler - 3.1.3 released 2015/06/20
|
6
11
|
|
7
12
|
- prevent Thread[:rufus_scheduler_time] -> nil, gh-156
|
data/CREDITS.txt
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
|
5
5
|
== Contributors
|
6
6
|
|
7
|
+
- Jesse Willet (https://github.com/jhw-at-prosperworks-com) cron vs "*/10"
|
7
8
|
- Pascal Ouellet (https://github.com/pouellet) Scheduler#timeline loop fix
|
8
9
|
- Ryan Biesemeyer (https://github.com/yaauie) ZoTime.is_timezone? on OSX
|
9
10
|
- Ketan Padegaonkar (https://github.com/ketan) .brute_frequency improvement
|
data/lib/rufus/scheduler.rb
CHANGED
@@ -186,19 +186,6 @@ class Rufus::Scheduler
|
|
186
186
|
time
|
187
187
|
end
|
188
188
|
|
189
|
-
if RUBY_VERSION >= '1.9'
|
190
|
-
def toa(item)
|
191
|
-
item == nil ? nil : item.to_a
|
192
|
-
end
|
193
|
-
else
|
194
|
-
def toi(item); item.is_a?(String) ? item.hash.abs : item.to_i; end
|
195
|
-
protected :toi
|
196
|
-
def toa(item)
|
197
|
-
item.is_a?(Set) ? item.to_a.sort_by { |e| toi(e) } : item
|
198
|
-
end
|
199
|
-
end
|
200
|
-
protected :toa
|
201
|
-
|
202
189
|
# Returns an array of 6 arrays (seconds, minutes, hours, days,
|
203
190
|
# months, weekdays).
|
204
191
|
# This method is used by the cronline unit tests.
|
@@ -228,16 +215,12 @@ class Rufus::Scheduler
|
|
228
215
|
|
229
216
|
return brute_frequency unless @seconds && @seconds.length > 1
|
230
217
|
|
231
|
-
delta = 60
|
232
218
|
secs = toa(@seconds)
|
233
|
-
prev = secs[0]
|
234
219
|
|
235
|
-
secs[1..-1].
|
220
|
+
secs[1..-1].inject([ secs[0], 60 ]) { |(prev, delta), sec|
|
236
221
|
d = sec - prev
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
delta
|
222
|
+
[ sec, d < delta ? d : delta ]
|
223
|
+
}[1]
|
241
224
|
end
|
242
225
|
|
243
226
|
# Returns the shortest delta between two potential occurences of the
|
@@ -288,13 +271,11 @@ class Rufus::Scheduler
|
|
288
271
|
delta
|
289
272
|
end
|
290
273
|
|
291
|
-
protected
|
292
|
-
|
293
274
|
def next_second(time)
|
294
275
|
|
295
|
-
secs = @seconds
|
276
|
+
secs = toa(@seconds)
|
296
277
|
|
297
|
-
return secs.
|
278
|
+
return secs.first + 60 - time.sec if time.sec > secs.last
|
298
279
|
|
299
280
|
secs.shift while secs.first < time.sec
|
300
281
|
|
@@ -303,13 +284,30 @@ class Rufus::Scheduler
|
|
303
284
|
|
304
285
|
def prev_second(time)
|
305
286
|
|
306
|
-
secs = @seconds
|
287
|
+
secs = toa(@seconds)
|
307
288
|
|
308
289
|
secs.pop while time.sec < secs.last
|
309
290
|
|
310
291
|
time.sec - secs.last
|
311
292
|
end
|
312
293
|
|
294
|
+
protected
|
295
|
+
|
296
|
+
def sc_sort(a)
|
297
|
+
|
298
|
+
a.sort_by { |e| e.is_a?(String) ? 61 : e.to_i }
|
299
|
+
end
|
300
|
+
|
301
|
+
if RUBY_VERSION >= '1.9'
|
302
|
+
def toa(item)
|
303
|
+
item == nil ? nil : item.to_a
|
304
|
+
end
|
305
|
+
else
|
306
|
+
def toa(item)
|
307
|
+
item.is_a?(Set) ? sc_sort(item.to_a) : item
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
313
311
|
WEEKDAYS = %w[ sun mon tue wed thu fri sat ]
|
314
312
|
DAY_S = 24 * 3600
|
315
313
|
WEEK_S = 7 * DAY_S
|
@@ -351,7 +349,7 @@ class Rufus::Scheduler
|
|
351
349
|
end
|
352
350
|
end
|
353
351
|
|
354
|
-
weekdays = weekdays.uniq if weekdays
|
352
|
+
weekdays = weekdays.uniq.sort if weekdays
|
355
353
|
|
356
354
|
[ weekdays, monthdays ]
|
357
355
|
end
|
@@ -366,6 +364,8 @@ class Rufus::Scheduler
|
|
366
364
|
"found duplicates in #{item.inspect}"
|
367
365
|
) if r.uniq.size < r.size
|
368
366
|
|
367
|
+
r = sc_sort(r)
|
368
|
+
|
369
369
|
Set.new(r)
|
370
370
|
end
|
371
371
|
|
data/spec/cronline_spec.rb
CHANGED
@@ -32,6 +32,10 @@ describe Rufus::Scheduler::CronLine do
|
|
32
32
|
in_zone(tz) { tu.getlocal }
|
33
33
|
end
|
34
34
|
|
35
|
+
def ns(cronline, now)
|
36
|
+
Rufus::Scheduler::CronLine.new(cronline).next_second(now)
|
37
|
+
end
|
38
|
+
|
35
39
|
def match(line, time)
|
36
40
|
expect(cl(line).matches?(time)).to eq(true)
|
37
41
|
end
|
@@ -68,20 +72,30 @@ describe Rufus::Scheduler::CronLine do
|
|
68
72
|
|
69
73
|
to_a '52 0 * * *', [ [0], [52], [0], nil, nil, nil, nil, nil ]
|
70
74
|
|
71
|
-
if ruby18?
|
72
|
-
|
73
|
-
else
|
74
|
-
|
75
|
-
end
|
75
|
+
#if ruby18?
|
76
|
+
# to_a '0 23-24 * * *', [ [0], [0], [0, 23], nil, nil, nil, nil, nil ]
|
77
|
+
#else
|
78
|
+
# to_a '0 23-24 * * *', [ [0], [0], [23, 0], nil, nil, nil, nil, nil ]
|
79
|
+
#end
|
76
80
|
#
|
77
81
|
# as reported by Aimee Rose in
|
78
82
|
# https://github.com/jmettraux/rufus-scheduler/issues/56
|
83
|
+
to_a '0 23-24 * * *', [ [0], [0], [0, 23], nil, nil, nil, nil, nil ]
|
79
84
|
|
80
|
-
if ruby18?
|
81
|
-
|
82
|
-
else
|
83
|
-
|
84
|
-
end
|
85
|
+
#if ruby18?
|
86
|
+
# to_a '0 23-2 * * *', [ [0], [0], [0, 1, 2, 23], nil, nil, nil, nil, nil ]
|
87
|
+
#else
|
88
|
+
# to_a '0 23-2 * * *', [ [0], [0], [23, 0, 1, 2], nil, nil, nil, nil, nil ]
|
89
|
+
#end
|
90
|
+
to_a '0 23-2 * * *', [ [0], [0], [0, 1, 2, 23], nil, nil, nil, nil, nil ]
|
91
|
+
|
92
|
+
# modulo forms work for five-field forms
|
93
|
+
to_a '*/17 * * * *', [[0], [0, 17, 34, 51], nil, nil, nil, nil, nil, nil]
|
94
|
+
to_a '13 */17 * * *', [[0], [13], [0, 17], nil, nil, nil, nil, nil]
|
95
|
+
|
96
|
+
# modulo forms work for six-field forms
|
97
|
+
to_a '*/17 * * * * *', [[0, 17, 34, 51], nil, nil, nil, nil, nil, nil, nil]
|
98
|
+
to_a '13 */17 * * * *', [[13], [0, 17, 34, 51], nil, nil, nil, nil, nil, nil]
|
85
99
|
end
|
86
100
|
|
87
101
|
it 'rejects invalid weekday expressions' do
|
@@ -215,6 +229,36 @@ describe Rufus::Scheduler::CronLine do
|
|
215
229
|
# as reported by Aimee Rose in
|
216
230
|
# https://github.com/jmettraux/rufus-scheduler/pull/58
|
217
231
|
end
|
232
|
+
|
233
|
+
it 'sorts seconds' do
|
234
|
+
|
235
|
+
to_a(
|
236
|
+
'23,30,10 * * * * *', [ [10,23,30], nil, nil, nil, nil, nil, nil, nil ])
|
237
|
+
end
|
238
|
+
|
239
|
+
it 'sorts minutes' do
|
240
|
+
|
241
|
+
to_a(
|
242
|
+
'23,30,10 * * * * ', [ [0], [10,23,30], nil, nil, nil, nil, nil, nil ])
|
243
|
+
end
|
244
|
+
|
245
|
+
it 'sorts days' do
|
246
|
+
|
247
|
+
to_a(
|
248
|
+
'* * 14,7 * * ', [ [0], nil, nil, [7, 14], nil, nil, nil, nil ])
|
249
|
+
end
|
250
|
+
|
251
|
+
it 'sorts months' do
|
252
|
+
|
253
|
+
to_a(
|
254
|
+
'* * * 11,3,4 * ', [ [0], nil, nil, nil, [3,4,11], nil, nil, nil ])
|
255
|
+
end
|
256
|
+
|
257
|
+
it 'sorts days of week' do
|
258
|
+
|
259
|
+
to_a(
|
260
|
+
'* * * * Sun,Fri,2 ', [ [0], nil, nil, nil, nil, [0, 2, 5], nil, nil ])
|
261
|
+
end
|
218
262
|
end
|
219
263
|
|
220
264
|
describe '#next_time' do
|
@@ -363,6 +407,55 @@ describe Rufus::Scheduler::CronLine do
|
|
363
407
|
)
|
364
408
|
).to eq(ltz('America/New_York', 2015, 3, 9, 2, 0, 0))
|
365
409
|
end
|
410
|
+
|
411
|
+
it 'understands six-field crontabs' do
|
412
|
+
|
413
|
+
expect(nt('* * * * * *',local(1970,1,1,1,1,1))).to(
|
414
|
+
eq(local(1970,1,1,1,1,2))
|
415
|
+
)
|
416
|
+
expect(nt('* * * * * *',local(1970,1,1,1,1,2))).to(
|
417
|
+
eq(local(1970,1,1,1,1,3))
|
418
|
+
)
|
419
|
+
expect(nt('*/10 * * * * *',local(1970,1,1,1,1,0))).to(
|
420
|
+
eq(local(1970,1,1,1,1,10))
|
421
|
+
)
|
422
|
+
expect(nt('*/10 * * * * *',local(1970,1,1,1,1,9))).to(
|
423
|
+
eq(local(1970,1,1,1,1,10))
|
424
|
+
)
|
425
|
+
expect(nt('*/10 * * * * *',local(1970,1,1,1,1,10))).to(
|
426
|
+
eq(local(1970,1,1,1,1,20))
|
427
|
+
)
|
428
|
+
expect(nt('*/10 * * * * *',local(1970,1,1,1,1,40))).to(
|
429
|
+
eq(local(1970,1,1,1,1,50))
|
430
|
+
)
|
431
|
+
expect(nt('*/10 * * * * *',local(1970,1,1,1,1,49))).to(
|
432
|
+
eq(local(1970,1,1,1,1,50))
|
433
|
+
)
|
434
|
+
expect(nt('*/10 * * * * *',local(1970,1,1,1,1,50))).to(
|
435
|
+
eq(local(1970,1,1,1,2,00)) # FAILS: skips a minute to 2:50, not 2:00
|
436
|
+
)
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
440
|
+
describe '#next_second' do
|
441
|
+
[
|
442
|
+
[ '*/10 * * * * *', local(1970,1,1,1,1, 0), 0 ], # 0 sec to 0s mark
|
443
|
+
[ '*/10 * * * * *', local(1970,1,1,1,1, 1), 9 ], # 9 sec to 10s mark
|
444
|
+
[ '*/10 * * * * *', local(1970,1,1,1,1, 9), 1 ], # 1 sec to 10s mark
|
445
|
+
[ '*/10 * * * * *', local(1970,1,1,1,1,10), 0 ], # 0 sec to 10s mark
|
446
|
+
[ '*/10 * * * * *', local(1970,1,1,1,1,11), 9 ], # 9 sec to 20s mark
|
447
|
+
[ '*/10 * * * * *', local(1970,1,1,1,1,19), 1 ], # 1 sec to 20s mark
|
448
|
+
[ '*/10 * * * * *', local(1970,1,1,1,1,20), 0 ], # 0 sec to 20s mark
|
449
|
+
[ '*/10 * * * * *', local(1970,1,1,1,1,21), 9 ], # 1 sec to 30s mark
|
450
|
+
# ...
|
451
|
+
[ '*/10 * * * * *', local(1970,1,1,1,1,49), 1 ], # 9 sec to 50s mark
|
452
|
+
[ '*/10 * * * * *', local(1970,1,1,1,1,50), 0 ], # 0 sec to 50s mark
|
453
|
+
[ '*/10 * * * * *', local(1970,1,1,1,1,51), 9 ], # FAILS: gives 59
|
454
|
+
].each do |cronline,now,sec|
|
455
|
+
it "understands that next_second('#{cronline}',#{now}) is #{sec}" do
|
456
|
+
expect(ns(cronline,now)).to eq(sec)
|
457
|
+
end
|
458
|
+
end
|
366
459
|
end
|
367
460
|
|
368
461
|
describe '#previous_time' do
|
@@ -417,6 +510,20 @@ describe Rufus::Scheduler::CronLine do
|
|
417
510
|
)
|
418
511
|
).to eq(ltz('America/New_York', 2015, 3, 9, 2, 0, 0))
|
419
512
|
end
|
513
|
+
|
514
|
+
it 'computes correctly when * 0,10,20' do
|
515
|
+
|
516
|
+
expect(
|
517
|
+
pt('* 0,10,20 * * *', lo(2000, 1, 1))).to eq(
|
518
|
+
lo(1999, 12, 31, 20, 59, 00))
|
519
|
+
end
|
520
|
+
|
521
|
+
it 'computes correctly when * */10' do
|
522
|
+
|
523
|
+
expect(
|
524
|
+
pt('* */10 * * *', lo(2000, 1, 1))).to eq(
|
525
|
+
lo(1999, 12, 31, 20, 59, 00))
|
526
|
+
end
|
420
527
|
end
|
421
528
|
|
422
529
|
describe '#matches?' do
|
@@ -543,6 +650,46 @@ describe Rufus::Scheduler::CronLine do
|
|
543
650
|
expect(Rufus::Scheduler::CronLine.new(
|
544
651
|
'10,20,30 * * * * *').frequency).to eq(10)
|
545
652
|
end
|
653
|
+
|
654
|
+
it 'spots B-A vs C-B asymmetry in five-field forms' do
|
655
|
+
|
656
|
+
expect(Rufus::Scheduler::CronLine.new(
|
657
|
+
'10,17,30 * * * *').frequency).to eq(7 * 60)
|
658
|
+
expect(Rufus::Scheduler::CronLine.new(
|
659
|
+
'10,23,30 * * * *').frequency).to eq(7 * 60)
|
660
|
+
expect(Rufus::Scheduler::CronLine.new(
|
661
|
+
'23,10,30 * * * *').frequency).to eq(7 * 60)
|
662
|
+
end
|
663
|
+
|
664
|
+
it 'spots B-A vs C-B asymmetry in six-field forms' do
|
665
|
+
|
666
|
+
expect(Rufus::Scheduler::CronLine.new(
|
667
|
+
'10,17,30 * * * * *').frequency).to eq(7)
|
668
|
+
expect(Rufus::Scheduler::CronLine.new(
|
669
|
+
'10,23,30 * * * * *').frequency).to eq(7)
|
670
|
+
expect(Rufus::Scheduler::CronLine.new(
|
671
|
+
'23,10,30 * * * * *').frequency).to eq(7)
|
672
|
+
end
|
673
|
+
|
674
|
+
it 'handles crontab steps syntax in five-field forms' do
|
675
|
+
|
676
|
+
expect(Rufus::Scheduler::CronLine.new(
|
677
|
+
'*/10 * * * *').frequency).to eq(10 * 60)
|
678
|
+
expect(Rufus::Scheduler::CronLine.new(
|
679
|
+
'* */10 * * *').frequency).to eq(60) # "*" all minutes [0..59]
|
680
|
+
expect(Rufus::Scheduler::CronLine.new(
|
681
|
+
'0 */10 * * *').frequency).to eq(4 * 60 * 60) # 2000 to 0000
|
682
|
+
end
|
683
|
+
|
684
|
+
it 'handles crontab steps syntax in six-field forms' do
|
685
|
+
|
686
|
+
expect(Rufus::Scheduler::CronLine.new(
|
687
|
+
'*/10 * * * * *').frequency).to eq(10)
|
688
|
+
expect(Rufus::Scheduler::CronLine.new(
|
689
|
+
'* */10 * * * *').frequency).to eq(1) # "*" all seconds [0..59]
|
690
|
+
expect(Rufus::Scheduler::CronLine.new(
|
691
|
+
'0 */10 * * * *').frequency).to eq(10 * 60)
|
692
|
+
end
|
546
693
|
end
|
547
694
|
|
548
695
|
describe '#brute_frequency' do
|
@@ -574,6 +721,42 @@ describe Rufus::Scheduler::CronLine do
|
|
574
721
|
expect(Rufus::Scheduler::CronLine.new(
|
575
722
|
'1 2 3 4 5').brute_frequency).to eq(31622400)
|
576
723
|
end
|
724
|
+
|
725
|
+
it 'spots B-A vs C-B asymmetry in five-field forms' do
|
726
|
+
|
727
|
+
expect(Rufus::Scheduler::CronLine.new(
|
728
|
+
'10,17,30 * * * *').brute_frequency).to eq(7 * 60)
|
729
|
+
expect(Rufus::Scheduler::CronLine.new(
|
730
|
+
'10,23,30 * * * *').brute_frequency).to eq(7 * 60)
|
731
|
+
end
|
732
|
+
|
733
|
+
it 'spots B-A vs C-B asymmetry in six-field forms' do
|
734
|
+
|
735
|
+
expect(Rufus::Scheduler::CronLine.new(
|
736
|
+
'10,17,30 * * * * *').brute_frequency).to eq(7)
|
737
|
+
expect(Rufus::Scheduler::CronLine.new(
|
738
|
+
'10,23,30 * * * * *').brute_frequency).to eq(7)
|
739
|
+
end
|
740
|
+
|
741
|
+
it 'handles crontab modulo syntax in five-field forms' do
|
742
|
+
|
743
|
+
expect(Rufus::Scheduler::CronLine.new(
|
744
|
+
'*/10 * * * *').brute_frequency).to eq(10 * 60)
|
745
|
+
expect(Rufus::Scheduler::CronLine.new(
|
746
|
+
'* */10 * * *').brute_frequency).to eq(60) # "*" all minutes [0..59]
|
747
|
+
expect(Rufus::Scheduler::CronLine.new(
|
748
|
+
'0 */10 * * *').brute_frequency).to eq(4 * 60 * 60) # 2000 to 0000
|
749
|
+
end
|
750
|
+
|
751
|
+
it 'handles crontab modulo syntax in six-field forms' do
|
752
|
+
|
753
|
+
expect(Rufus::Scheduler::CronLine.new(
|
754
|
+
'*/10 * * * * *').brute_frequency).to eq(10)
|
755
|
+
expect(Rufus::Scheduler::CronLine.new(
|
756
|
+
'* */10 * * * *').brute_frequency).to eq(1) # "*" all seconds [0..59]
|
757
|
+
expect(Rufus::Scheduler::CronLine.new(
|
758
|
+
'0 */10 * * * *').brute_frequency).to eq(10 * 60)
|
759
|
+
end
|
577
760
|
end
|
578
761
|
|
579
762
|
context 'summer time' do
|
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: 3.1.
|
4
|
+
version: 3.1.4
|
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: 2015-
|
12
|
+
date: 2015-08-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|