rufus-scheduler 3.1.4 → 3.8.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +410 -0
  3. data/CREDITS.md +142 -0
  4. data/LICENSE.txt +1 -1
  5. data/Makefile +27 -0
  6. data/README.md +407 -143
  7. data/lib/rufus/scheduler/job_array.rb +36 -66
  8. data/lib/rufus/scheduler/jobs_core.rb +369 -0
  9. data/lib/rufus/scheduler/jobs_one_time.rb +53 -0
  10. data/lib/rufus/scheduler/jobs_repeat.rb +335 -0
  11. data/lib/rufus/scheduler/locks.rb +41 -67
  12. data/lib/rufus/scheduler/util.rb +89 -179
  13. data/lib/rufus/scheduler.rb +545 -453
  14. data/rufus-scheduler.gemspec +22 -11
  15. metadata +44 -85
  16. data/CHANGELOG.txt +0 -243
  17. data/CREDITS.txt +0 -88
  18. data/Rakefile +0 -83
  19. data/TODO.txt +0 -151
  20. data/lib/rufus/scheduler/cronline.rb +0 -470
  21. data/lib/rufus/scheduler/jobs.rb +0 -633
  22. data/lib/rufus/scheduler/zones.rb +0 -174
  23. data/lib/rufus/scheduler/zotime.rb +0 -155
  24. data/spec/basics_spec.rb +0 -54
  25. data/spec/cronline_spec.rb +0 -915
  26. data/spec/error_spec.rb +0 -139
  27. data/spec/job_array_spec.rb +0 -39
  28. data/spec/job_at_spec.rb +0 -58
  29. data/spec/job_cron_spec.rb +0 -128
  30. data/spec/job_every_spec.rb +0 -104
  31. data/spec/job_in_spec.rb +0 -20
  32. data/spec/job_interval_spec.rb +0 -68
  33. data/spec/job_repeat_spec.rb +0 -357
  34. data/spec/job_spec.rb +0 -631
  35. data/spec/lock_custom_spec.rb +0 -47
  36. data/spec/lock_flock_spec.rb +0 -47
  37. data/spec/lock_lockfile_spec.rb +0 -61
  38. data/spec/lock_spec.rb +0 -59
  39. data/spec/parse_spec.rb +0 -263
  40. data/spec/schedule_at_spec.rb +0 -158
  41. data/spec/schedule_cron_spec.rb +0 -66
  42. data/spec/schedule_every_spec.rb +0 -109
  43. data/spec/schedule_in_spec.rb +0 -80
  44. data/spec/schedule_interval_spec.rb +0 -128
  45. data/spec/scheduler_spec.rb +0 -1067
  46. data/spec/spec_helper.rb +0 -126
  47. data/spec/threads_spec.rb +0 -96
  48. data/spec/zotime_spec.rb +0 -396
data/spec/job_spec.rb DELETED
@@ -1,631 +0,0 @@
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::Job do
12
-
13
- # specify behaviours common to all job classes
14
-
15
- before :each do
16
-
17
- @taoe = Thread.abort_on_exception
18
- Thread.abort_on_exception = false
19
-
20
- @ose = $stderr
21
- $stderr = StringIO.new
22
-
23
- @scheduler = Rufus::Scheduler.new
24
- end
25
-
26
- after :each do
27
-
28
- @scheduler.shutdown
29
-
30
- Thread.abort_on_exception = @taoe
31
-
32
- $stderr = @ose
33
- end
34
-
35
- describe '#last_time' do
36
-
37
- it 'returns nil if the job never fired' do
38
-
39
- job = @scheduler.schedule_in '10d' do; end
40
-
41
- expect(job.last_time).to eq(nil)
42
- end
43
-
44
- it 'returns the last time the job fired' do
45
-
46
- job = @scheduler.schedule_in '0s' do; end
47
-
48
- sleep 0.4
49
-
50
- expect(job.last_time).not_to eq(nil)
51
- end
52
- end
53
-
54
- describe '#threads' do
55
-
56
- it 'returns an empty list when the job is not running' do
57
-
58
- job = @scheduler.in('1d', :job => true) {}
59
-
60
- expect(job.threads.size).to eq(0)
61
- end
62
-
63
- it 'returns an empty list after the job terminated' do
64
-
65
- job = @scheduler.in('0s', :job => true) {}
66
-
67
- sleep 0.8
68
-
69
- expect(job.threads.size).to eq(0)
70
- end
71
-
72
- it 'lists the threads the job currently runs in' do
73
-
74
- job =
75
- @scheduler.schedule_in('0s') do
76
- sleep(1)
77
- end
78
-
79
- sleep 0.4
80
-
81
- expect(job.threads.size).to eq(1)
82
-
83
- t = job.threads.first
84
- expect(t[:rufus_scheduler_job]).to eq(job)
85
- end
86
- end
87
-
88
- describe '#kill' do
89
-
90
- it 'has no effect if the job is not running' do
91
-
92
- job = @scheduler.schedule_in '10d' do; end
93
-
94
- tls = Thread.list.size
95
-
96
- job.kill
97
-
98
- expect(Thread.list.size).to eq(tls)
99
- end
100
-
101
- it 'makes the threads vacant' do
102
-
103
- counter = 0
104
-
105
- job =
106
- @scheduler.schedule_in '0s' do
107
- sleep 2
108
- counter = counter + 1
109
- end
110
-
111
- sleep 1
112
-
113
- v0 = @scheduler.work_threads(:vacant).size
114
- a0 = @scheduler.work_threads(:active).size
115
-
116
- job.kill
117
-
118
- sleep 2
119
-
120
- v1 = @scheduler.work_threads(:vacant).size
121
- a1 = @scheduler.work_threads(:active).size
122
-
123
- expect(counter).to eq(0)
124
-
125
- expect(v0).to eq(0)
126
- expect(a0).to eq(1)
127
-
128
- expect(v1).to eq(1)
129
- expect(a1).to eq(0)
130
- end
131
- end
132
-
133
- describe '#running?' do
134
-
135
- it 'returns false when the job is not running in any thread' do
136
-
137
- job = @scheduler.in('1d', :job => true) {}
138
-
139
- expect(job.running?).to eq(false)
140
- end
141
-
142
- it 'returns true when the job is running in at least one thread' do
143
-
144
- job = @scheduler.in('0s', :job => true) { sleep(1) }
145
-
146
- sleep 0.4
147
-
148
- expect(job.running?).to eq(true)
149
- end
150
- end
151
-
152
- describe '#scheduled?' do
153
-
154
- it 'returns true when the job is scheduled' do
155
-
156
- job = @scheduler.schedule_in('1d') {}
157
-
158
- expect(job.scheduled?).to eq(true)
159
- end
160
-
161
- it 'returns false when the job is not scheduled' do
162
-
163
- job = @scheduler.schedule_in('0.1s') {}
164
-
165
- sleep 0.4
166
-
167
- expect(job.scheduled?).to eq(false)
168
- end
169
-
170
- it 'returns true for repeat jobs that are running' do
171
-
172
- job = @scheduler.schedule_interval('0.4s') { sleep(10) }
173
-
174
- sleep 1
175
-
176
- expect(job.running?).to eq(true)
177
- expect(job.scheduled?).to eq(true)
178
- end
179
- end
180
-
181
- describe '#call' do
182
-
183
- it 'calls the job (like it were a proc)' do
184
-
185
- counter = 0
186
-
187
- job =
188
- @scheduler.schedule_in('0.5s') do
189
- counter = counter + 1
190
- end
191
- job.call
192
-
193
- sleep 0.8
194
-
195
- expect(counter).to eq(2)
196
- end
197
- end
198
-
199
- describe '#call(true)' do
200
-
201
- it 'calls the job and let the scheduler handle errors' do
202
-
203
- $err = nil
204
-
205
- def @scheduler.on_error(job, err)
206
- $err = "#{job.class} #{job.original} #{err.message}"
207
- rescue
208
- p $!
209
- end
210
-
211
- job =
212
- @scheduler.schedule_in('1d') do
213
- fail 'again'
214
- end
215
-
216
- job.call(true)
217
-
218
- expect($err).to eq('Rufus::Scheduler::InJob 1d again')
219
- end
220
- end
221
-
222
- describe '#call(false)' do
223
-
224
- it 'calls the job and let errors slip through' do
225
-
226
- job =
227
- @scheduler.schedule_in('1d') do
228
- fail 'fast'
229
- end
230
-
231
- begin
232
-
233
- #job.call(false)
234
- job.call # false is the default
235
-
236
- expect(false).to eq(true)
237
-
238
- rescue => ex
239
-
240
- expect(ex.message).to eq('fast')
241
- end
242
- end
243
- end
244
-
245
- context 'job-local variables' do
246
-
247
- describe '#[]=' do
248
-
249
- it 'sets a job-local variable' do
250
-
251
- job =
252
- @scheduler.schedule_every '1s' do |job|
253
- job[:counter] ||= 0
254
- job[:counter] += 1
255
- end
256
-
257
- sleep 3
258
-
259
- expect(job[:counter]).to be > 1
260
- end
261
- end
262
-
263
- describe '#[]' do
264
-
265
- it 'returns nil if there is no such entry' do
266
-
267
- job = @scheduler.schedule_in '1s' do; end
268
-
269
- expect(job[:nada]).to eq(nil)
270
- end
271
-
272
- it 'returns the value of a job-local variable' do
273
-
274
- job = @scheduler.schedule_in '1s' do; end
275
- job[:x] = :y
276
-
277
- expect(job[:x]).to eq(:y)
278
- end
279
- end
280
-
281
- describe '#key?' do
282
-
283
- it 'returns true if there is an entry with the given key' do
284
-
285
- job = @scheduler.schedule_in '1s' do; end
286
- job[:x] = :y
287
-
288
- expect(job.key?(:x)).to eq(true)
289
- end
290
- end
291
-
292
- describe '#keys' do
293
-
294
- it 'returns the array of keys of the job-local variables' do
295
-
296
- job = @scheduler.schedule_in '1s' do; end
297
- job[:x] = :y
298
- job['hello'] = :z
299
- job[123] = {}
300
-
301
- expect(job.keys.sort_by { |k| k.to_s }).to eq([ 123, 'hello', :x ])
302
- end
303
- end
304
- end
305
-
306
- context ':tag / :tags => [ t0, t1 ]' do
307
-
308
- it 'accepts one tag' do
309
-
310
- job = @scheduler.in '10d', :job => true, :tag => 't0' do; end
311
-
312
- expect(job.tags).to eq(%w[ t0 ])
313
- end
314
-
315
- it 'accepts an array of tags' do
316
-
317
- job = @scheduler.in '10d', :job => true, :tag => %w[ t0 t1 ] do; end
318
-
319
- expect(job.tags).to eq(%w[ t0 t1 ])
320
- end
321
-
322
- it 'turns tags into strings' do
323
-
324
- job = @scheduler.in '10d', :job => true, :tags => [ 1, 2 ] do; end
325
-
326
- expect(job.tags).to eq(%w[ 1 2 ])
327
- end
328
- end
329
-
330
- context ':blocking => true' do
331
-
332
- it 'runs the job in the same thread as the scheduler thread' do
333
-
334
- job =
335
- @scheduler.in('0s', :job => true, :blocking => true) do
336
- sleep(1)
337
- end
338
-
339
- sleep 0.4
340
-
341
- expect(job.threads.first).to eq(@scheduler.thread)
342
-
343
- sleep 1.4
344
-
345
- expect(job.threads.size).to eq(0)
346
- end
347
- end
348
-
349
- context 'default one thread per job behaviour' do
350
-
351
- it 'runs the job in a dedicated thread' do
352
-
353
- job =
354
- @scheduler.in('0s', :job => true) do
355
- sleep(1)
356
- end
357
-
358
- sleep 0.4
359
-
360
- expect(job.threads.first).not_to eq(@scheduler.thread)
361
-
362
- sleep 1.4
363
-
364
- expect(job.threads.size).to eq(0)
365
- end
366
- end
367
-
368
- context ':allow_overlapping / :allow_overlap / :overlap' do
369
-
370
- context 'default (:overlap => true)' do
371
-
372
- it 'lets a job overlap itself' do
373
-
374
- job =
375
- @scheduler.every('0.3', :job => true) do
376
- sleep(5)
377
- end
378
-
379
- sleep 3
380
-
381
- expect(job.threads.size).to be > 1
382
- end
383
- end
384
-
385
- context 'when :overlap => false' do
386
-
387
- it 'prevents a job from overlapping itself' do
388
-
389
- job =
390
- @scheduler.every('0.3', :job => true, :overlap => false) do
391
- sleep(5)
392
- end
393
-
394
- sleep 3
395
-
396
- expect(job.threads.size).to eq(1)
397
- end
398
- end
399
- end
400
-
401
- context ':mutex' do
402
-
403
- context ':mutex => "mutex_name"' do
404
-
405
- it 'prevents concurrent executions' do
406
-
407
- j0 =
408
- @scheduler.in('0s', :job => true, :mutex => 'vladivostok') do
409
- sleep(3)
410
- end
411
- j1 =
412
- @scheduler.in('0s', :job => true, :mutex => 'vladivostok') do
413
- sleep(3)
414
- end
415
-
416
- sleep 0.7
417
-
418
- if j0.threads.any?
419
- expect(j0.threads.size).to eq(1)
420
- expect(j1.threads.size).to eq(0)
421
- else
422
- expect(j0.threads.size).to eq(0)
423
- expect(j1.threads.size).to eq(1)
424
- end
425
-
426
- expect(@scheduler.mutexes.keys).to eq(%w[ vladivostok ])
427
- end
428
- end
429
-
430
- context ':mutex => mutex_instance' do
431
-
432
- it 'prevents concurrent executions' do
433
-
434
- m = Mutex.new
435
-
436
- j0 = @scheduler.in('0s', :job => true, :mutex => m) { sleep(3) }
437
- j1 = @scheduler.in('0s', :job => true, :mutex => m) { sleep(3) }
438
-
439
- sleep 0.7
440
-
441
- if j0.threads.any?
442
- expect(j0.threads.size).to eq(1)
443
- expect(j1.threads.size).to eq(0)
444
- else
445
- expect(j0.threads.size).to eq(0)
446
- expect(j1.threads.size).to eq(1)
447
- end
448
-
449
- expect(@scheduler.mutexes.keys).to eq([])
450
- end
451
- end
452
-
453
- context ':mutex => [ array_of_mutex_names_or_instances ]' do
454
-
455
- it 'prevents concurrent executions' do
456
-
457
- j0 =
458
- @scheduler.in('0s', :job => true, :mutex => %w[ a b ]) do
459
- sleep(3)
460
- end
461
- j1 =
462
- @scheduler.in('0s', :job => true, :mutex => %w[ a b ]) do
463
- sleep(3)
464
- end
465
-
466
- sleep 0.7
467
-
468
- if j0.threads.any?
469
- expect(j0.threads.size).to eq(1)
470
- expect(j1.threads.size).to eq(0)
471
- else
472
- expect(j0.threads.size).to eq(0)
473
- expect(j1.threads.size).to eq(1)
474
- end
475
-
476
- expect(@scheduler.mutexes.keys.sort).to eq(%w[ a b ])
477
- end
478
- end
479
- end
480
-
481
- context ':timeout => duration_or_point_in_time' do
482
-
483
- it 'interrupts the job it is stashed to (duration)' do
484
-
485
- counter = 0
486
- toe = nil
487
-
488
- job =
489
- @scheduler.schedule_in '0s', :timeout => '1s' do
490
- begin
491
- counter = counter + 1
492
- sleep 1.5
493
- counter = counter + 1
494
- rescue Rufus::Scheduler::TimeoutError => e
495
- toe = e
496
- end
497
- end
498
-
499
- sleep(3)
500
-
501
- expect(counter).to eq(1)
502
- expect(toe.class).to eq(Rufus::Scheduler::TimeoutError)
503
- end
504
-
505
- it 'interrupts the job it is stashed to (point in time)' do
506
-
507
- counter = 0
508
-
509
- job =
510
- @scheduler.schedule_in '0s', :timeout => Time.now + 1 do
511
- begin
512
- counter = counter + 1
513
- sleep 1.5
514
- counter = counter + 1
515
- rescue Rufus::Scheduler::TimeoutError => e
516
- end
517
- end
518
-
519
- sleep(3)
520
-
521
- expect(counter).to eq(1)
522
- end
523
-
524
- it 'starts timing when the job enters successfully all its mutexes' do
525
-
526
- t0, t1, t2 = nil
527
-
528
- @scheduler.schedule_in '0s', :mutex => 'a' do
529
- sleep 1
530
- t0 = Time.now
531
- end
532
-
533
- job =
534
- @scheduler.schedule_in '0.5s', :mutex => 'a', :timeout => '1s' do
535
- begin
536
- t1 = Time.now
537
- sleep 2
538
- rescue Rufus::Scheduler::TimeoutError => e
539
- t2 = Time.now
540
- end
541
- end
542
-
543
- sleep 3
544
-
545
- expect(t0).to be <= t1
546
-
547
- d = t2 - t1
548
- expect(d).to be >= 1.0
549
- expect(d).to be < 1.5
550
- end
551
-
552
- it 'emits the timeout information to $stderr (default #on_error)' do
553
-
554
- @scheduler.every('1s', :timeout => '0.5s') do
555
- sleep 0.9
556
- end
557
-
558
- sleep 2
559
-
560
- expect($stderr.string).to match(/Rufus::Scheduler::TimeoutError/)
561
- end
562
-
563
- it 'does not prevent a repeat job from recurring' do
564
-
565
- counter = 0
566
-
567
- @scheduler.every('1s', :timeout => '0.5s') do
568
- counter = counter + 1
569
- sleep 0.9
570
- end
571
-
572
- sleep 3
573
-
574
- expect(counter).to be > 1
575
- end
576
- end
577
-
578
- context 'work time' do
579
-
580
- describe '#last_work_time' do
581
-
582
- it 'starts at 0' do
583
-
584
- job = @scheduler.schedule_every '5m' do; end
585
-
586
- expect(job.last_work_time).to eq(0.0)
587
- end
588
-
589
- it 'keeps track of how long the work was upon last trigger' do
590
-
591
- job =
592
- @scheduler.schedule_in '0.5s' do
593
- sleep 0.7
594
- end
595
-
596
- sleep 2
597
-
598
- expect(job.last_work_time).to be >= 0.7
599
- expect(job.last_work_time).to be < 0.8
600
- end
601
- end
602
-
603
- describe '#mean_work_time' do
604
-
605
- it 'starts at 0' do
606
-
607
- job = @scheduler.schedule_every '5m' do; end
608
-
609
- expect(job.mean_work_time).to eq(0.0)
610
- end
611
-
612
- it 'gathers work times and computes the mean' do
613
-
614
- job =
615
- @scheduler.schedule_every '0.5s' do |j|
616
- #p j.last_work_time
617
- #p j.mean_work_time
618
- sleep 0.01 * (j.count + 1)
619
- end
620
-
621
- sleep 4.6
622
-
623
- expect(job.last_work_time).to be >= 0.08
624
- expect(job.last_work_time).to be < 0.099
625
- expect(job.mean_work_time).to be > 0.05
626
- expect(job.mean_work_time).to be < 0.06
627
- end
628
- end
629
- end
630
- end
631
-
@@ -1,47 +0,0 @@
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
-
@@ -1,47 +0,0 @@
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
-