rufus-scheduler 3.1.9 → 3.2.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/spec/job_spec.rb DELETED
@@ -1,671 +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
-
180
- it 'returns false if job is unscheduled' do
181
- job = @scheduler.schedule_interval('0.1s') { sleep 0.1 }
182
- job.unschedule
183
-
184
- sleep 0.3
185
-
186
- expect(job.running?).to eq(false)
187
- expect(job.scheduled?).to eq(false)
188
- end
189
- end
190
-
191
- describe '#call' do
192
-
193
- it 'calls the job (like it were a proc)' do
194
-
195
- counter = 0
196
-
197
- job =
198
- @scheduler.schedule_in('0.5s') do
199
- counter = counter + 1
200
- end
201
- job.call
202
-
203
- sleep 0.8
204
-
205
- expect(counter).to eq(2)
206
- end
207
- end
208
-
209
- describe '#call(true)' do
210
-
211
- it 'calls the job and let the scheduler handle errors' do
212
-
213
- $err = nil
214
-
215
- def @scheduler.on_error(job, err)
216
- $err = "#{job.class} #{job.original} #{err.message}"
217
- rescue
218
- p $!
219
- end
220
-
221
- job =
222
- @scheduler.schedule_in('1d') do
223
- fail 'again'
224
- end
225
-
226
- job.call(true)
227
-
228
- expect($err).to eq('Rufus::Scheduler::InJob 1d again')
229
- end
230
- end
231
-
232
- describe '#call(false)' do
233
-
234
- it 'calls the job and let errors slip through' do
235
-
236
- job =
237
- @scheduler.schedule_in('1d') do
238
- fail 'fast'
239
- end
240
-
241
- begin
242
-
243
- #job.call(false)
244
- job.call # false is the default
245
-
246
- expect(false).to eq(true)
247
-
248
- rescue => ex
249
-
250
- expect(ex.message).to eq('fast')
251
- end
252
- end
253
- end
254
-
255
- context 'job-local variables' do
256
-
257
- describe '#[]=' do
258
-
259
- it 'sets a job-local variable' do
260
-
261
- job =
262
- @scheduler.schedule_every '1s' do |job|
263
- job[:counter] ||= 0
264
- job[:counter] += 1
265
- end
266
-
267
- sleep 3
268
-
269
- expect(job[:counter]).to be > 1
270
- end
271
- end
272
-
273
- describe '#[]' do
274
-
275
- it 'returns nil if there is no such entry' do
276
-
277
- job = @scheduler.schedule_in '1s' do; end
278
-
279
- expect(job[:nada]).to eq(nil)
280
- end
281
-
282
- it 'returns the value of a job-local variable' do
283
-
284
- job = @scheduler.schedule_in '1s' do; end
285
- job[:x] = :y
286
-
287
- expect(job[:x]).to eq(:y)
288
- end
289
- end
290
-
291
- describe '#key?' do
292
-
293
- it 'returns true if there is an entry with the given key' do
294
-
295
- job = @scheduler.schedule_in '1s' do; end
296
- job[:x] = :y
297
-
298
- expect(job.key?(:x)).to eq(true)
299
- end
300
- end
301
-
302
- describe '#keys' do
303
-
304
- it 'returns the array of keys of the job-local variables' do
305
-
306
- job = @scheduler.schedule_in '1s' do; end
307
- job[:x] = :y
308
- job['hello'] = :z
309
- job[123] = {}
310
-
311
- expect(job.keys.sort_by { |k| k.to_s }).to eq([ 123, 'hello', :x ])
312
- end
313
- end
314
- end
315
-
316
- context ':tag / :tags => [ t0, t1 ]' do
317
-
318
- it 'accepts one tag' do
319
-
320
- job = @scheduler.in '10d', :job => true, :tag => 't0' do; end
321
-
322
- expect(job.tags).to eq(%w[ t0 ])
323
- end
324
-
325
- it 'accepts an array of tags' do
326
-
327
- job = @scheduler.in '10d', :job => true, :tag => %w[ t0 t1 ] do; end
328
-
329
- expect(job.tags).to eq(%w[ t0 t1 ])
330
- end
331
-
332
- it 'turns tags into strings' do
333
-
334
- job = @scheduler.in '10d', :job => true, :tags => [ 1, 2 ] do; end
335
-
336
- expect(job.tags).to eq(%w[ 1 2 ])
337
- end
338
- end
339
-
340
- context ':blocking => true' do
341
-
342
- it 'runs the job in the same thread as the scheduler thread' do
343
-
344
- job =
345
- @scheduler.in('0s', :job => true, :blocking => true) do
346
- sleep(1)
347
- end
348
-
349
- sleep 0.4
350
-
351
- expect(job.threads.first).to eq(@scheduler.thread)
352
-
353
- sleep 1.4
354
-
355
- expect(job.threads.size).to eq(0)
356
- end
357
- end
358
-
359
- context 'default one thread per job behaviour' do
360
-
361
- it 'runs the job in a dedicated thread' do
362
-
363
- job =
364
- @scheduler.in('0s', :job => true) do
365
- sleep(1)
366
- end
367
-
368
- sleep 0.4
369
-
370
- expect(job.threads.first).not_to eq(@scheduler.thread)
371
-
372
- sleep 1.4
373
-
374
- expect(job.threads.size).to eq(0)
375
- end
376
- end
377
-
378
- context ':allow_overlapping / :allow_overlap / :overlap' do
379
-
380
- context 'default (:overlap => true)' do
381
-
382
- it 'lets a job overlap itself' do
383
-
384
- job =
385
- @scheduler.every('0.3', :job => true) do
386
- sleep(5)
387
- end
388
-
389
- sleep 3
390
-
391
- expect(job.threads.size).to be > 1
392
- end
393
- end
394
-
395
- context 'when :overlap => false' do
396
-
397
- it 'prevents a job from overlapping itself' do
398
-
399
- job =
400
- @scheduler.every('0.3', :job => true, :overlap => false) do
401
- sleep(5)
402
- end
403
-
404
- sleep 3
405
-
406
- expect(job.threads.size).to eq(1)
407
- end
408
- end
409
- end
410
-
411
- context ':mutex' do
412
-
413
- context ':mutex => "mutex_name"' do
414
-
415
- it 'prevents concurrent executions' do
416
-
417
- j0 =
418
- @scheduler.in('0s', :job => true, :mutex => 'vladivostok') do
419
- sleep(3)
420
- end
421
- j1 =
422
- @scheduler.in('0s', :job => true, :mutex => 'vladivostok') do
423
- sleep(3)
424
- end
425
-
426
- sleep 0.7
427
-
428
- if j0.threads.any?
429
- expect(j0.threads.size).to eq(1)
430
- expect(j1.threads.size).to eq(0)
431
- else
432
- expect(j0.threads.size).to eq(0)
433
- expect(j1.threads.size).to eq(1)
434
- end
435
-
436
- expect(@scheduler.mutexes.keys).to eq(%w[ vladivostok ])
437
- end
438
- end
439
-
440
- context ':mutex => mutex_instance' do
441
-
442
- it 'prevents concurrent executions' do
443
-
444
- m = Mutex.new
445
-
446
- j0 = @scheduler.in('0s', :job => true, :mutex => m) { sleep(3) }
447
- j1 = @scheduler.in('0s', :job => true, :mutex => m) { sleep(3) }
448
-
449
- sleep 0.7
450
-
451
- if j0.threads.any?
452
- expect(j0.threads.size).to eq(1)
453
- expect(j1.threads.size).to eq(0)
454
- else
455
- expect(j0.threads.size).to eq(0)
456
- expect(j1.threads.size).to eq(1)
457
- end
458
-
459
- expect(@scheduler.mutexes.keys).to eq([])
460
- end
461
- end
462
-
463
- context ':mutex => [ array_of_mutex_names_or_instances ]' do
464
-
465
- it 'prevents concurrent executions' do
466
-
467
- j0 =
468
- @scheduler.in('0s', :job => true, :mutex => %w[ a b ]) do
469
- sleep(3)
470
- end
471
- j1 =
472
- @scheduler.in('0s', :job => true, :mutex => %w[ a b ]) do
473
- sleep(3)
474
- end
475
-
476
- sleep 0.7
477
-
478
- if j0.threads.any?
479
- expect(j0.threads.size).to eq(1)
480
- expect(j1.threads.size).to eq(0)
481
- else
482
- expect(j0.threads.size).to eq(0)
483
- expect(j1.threads.size).to eq(1)
484
- end
485
-
486
- expect(@scheduler.mutexes.keys.sort).to eq(%w[ a b ])
487
- end
488
- end
489
- end
490
-
491
- context ':timeout => duration_or_point_in_time' do
492
-
493
- it 'interrupts the job it is stashed to (duration)' do
494
-
495
- counter = 0
496
- toe = nil
497
-
498
- job =
499
- @scheduler.schedule_in '0s', :timeout => '1s' do
500
- begin
501
- counter = counter + 1
502
- sleep 1.5
503
- counter = counter + 1
504
- rescue Rufus::Scheduler::TimeoutError => e
505
- toe = e
506
- end
507
- end
508
-
509
- sleep(3)
510
-
511
- expect(counter).to eq(1)
512
- expect(toe.class).to eq(Rufus::Scheduler::TimeoutError)
513
- end
514
-
515
- it 'interrupts the job it is stashed to (point in time)' do
516
-
517
- counter = 0
518
-
519
- job =
520
- @scheduler.schedule_in '0s', :timeout => Time.now + 1 do
521
- begin
522
- counter = counter + 1
523
- sleep 1.5
524
- counter = counter + 1
525
- rescue Rufus::Scheduler::TimeoutError => e
526
- end
527
- end
528
-
529
- sleep(3)
530
-
531
- expect(counter).to eq(1)
532
- end
533
-
534
- it 'starts timing when the job enters successfully all its mutexes' do
535
-
536
- t0, t1, t2 = nil
537
-
538
- @scheduler.schedule_in '0s', :mutex => 'a' do
539
- sleep 1
540
- t0 = Time.now
541
- end
542
-
543
- job =
544
- @scheduler.schedule_in '0.5s', :mutex => 'a', :timeout => '1s' do
545
- begin
546
- t1 = Time.now
547
- sleep 2
548
- rescue Rufus::Scheduler::TimeoutError => e
549
- t2 = Time.now
550
- end
551
- end
552
-
553
- sleep 3
554
-
555
- expect(t0).to be <= t1
556
-
557
- d = t2 - t1
558
- expect(d).to be >= 1.0
559
- expect(d).to be < 1.5
560
- end
561
-
562
- it 'emits the timeout information to $stderr (default #on_error)' do
563
-
564
- @scheduler.every('1s', :timeout => '0.5s') do
565
- sleep 0.9
566
- end
567
-
568
- sleep 2
569
-
570
- expect($stderr.string).to match(/Rufus::Scheduler::TimeoutError/)
571
- end
572
-
573
- it 'does not prevent a repeat job from recurring' do
574
-
575
- counter = 0
576
-
577
- @scheduler.every('1s', :timeout => '0.5s') do
578
- counter = counter + 1
579
- sleep 0.9
580
- end
581
-
582
- sleep 3
583
-
584
- expect(counter).to be > 1
585
- end
586
- end
587
-
588
- context 'work time' do
589
-
590
- describe '#last_work_time' do
591
-
592
- it 'starts at 0' do
593
-
594
- job = @scheduler.schedule_every '5m' do; end
595
-
596
- expect(job.last_work_time).to eq(0.0)
597
- end
598
-
599
- it 'keeps track of how long the work was upon last trigger' do
600
-
601
- job =
602
- @scheduler.schedule_in '0.5s' do
603
- sleep 0.7
604
- end
605
-
606
- sleep 2
607
-
608
- expect(job.last_work_time).to be >= 0.7
609
- expect(job.last_work_time).to be < 0.8
610
- end
611
- end
612
-
613
- describe '#mean_work_time' do
614
-
615
- it 'starts at 0' do
616
-
617
- job = @scheduler.schedule_every '5m' do; end
618
-
619
- expect(job.mean_work_time).to eq(0.0)
620
- end
621
-
622
- it 'gathers work times and computes the mean' do
623
-
624
- job =
625
- @scheduler.schedule_every '0.5s' do |j|
626
- #p j.last_work_time
627
- #p j.mean_work_time
628
- sleep 0.01 * (j.count + 1)
629
- end
630
-
631
- sleep 4.6
632
-
633
- expect(job.last_work_time).to be >= 0.08
634
- expect(job.last_work_time).to be < 0.099
635
- expect(job.mean_work_time).to be > 0.05
636
- expect(job.mean_work_time).to be < 0.06
637
- end
638
- end
639
- end
640
-
641
- context 'one time job' do
642
-
643
- describe '#determine_id' do
644
-
645
- it 'returns unique ids' do
646
-
647
- ids = []
648
-
649
- 10_000.times { ids << @scheduler.in('1y') {} }
650
-
651
- expect(ids.uniq.length).to eq(ids.length)
652
- end
653
- end
654
- end
655
-
656
- context 'repeat job' do
657
-
658
- describe '#determine_id' do
659
-
660
- it 'returns unique ids' do
661
-
662
- ids = []
663
-
664
- 10_000.times { ids << @scheduler.every('1y') {} }
665
-
666
- expect(ids.uniq.length).to eq(ids.length)
667
- end
668
- end
669
- end
670
- end
671
-
@@ -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
-