rufus-scheduler 3.1.3 → 3.1.4

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 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
@@ -39,7 +39,7 @@ module Rufus
39
39
  require 'rufus/scheduler/job_array'
40
40
  require 'rufus/scheduler/locks'
41
41
 
42
- VERSION = '3.1.3'
42
+ VERSION = '3.1.4'
43
43
 
44
44
  #
45
45
  # A common error class for rufus-scheduler
@@ -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].each do |sec|
220
+ secs[1..-1].inject([ secs[0], 60 ]) { |(prev, delta), sec|
236
221
  d = sec - prev
237
- delta = d if d < delta
238
- end
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.sort
276
+ secs = toa(@seconds)
296
277
 
297
- return secs.last + 60 - time.sec if time.sec > secs.last
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.sort
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
 
@@ -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
- to_a '0 23-24 * * *', [ [0], [0], [0, 23], nil, nil, nil, nil, nil ]
73
- else
74
- to_a '0 23-24 * * *', [ [0], [0], [23, 0], nil, nil, nil, nil, nil ]
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
- to_a '0 23-2 * * *', [ [0], [0], [0, 1, 2, 23], nil, nil, nil, nil, nil ]
82
- else
83
- to_a '0 23-2 * * *', [ [0], [0], [23, 0, 1, 2], nil, nil, nil, nil, nil ]
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.3
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-06-19 00:00:00.000000000 Z
12
+ date: 2015-08-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake