rufus-scheduler 2.0.24 → 3.1.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.
Files changed (63) hide show
  1. data/CHANGELOG.txt +76 -0
  2. data/CREDITS.txt +23 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +1439 -0
  5. data/Rakefile +1 -5
  6. data/TODO.txt +149 -55
  7. data/lib/rufus/{sc → scheduler}/cronline.rb +167 -53
  8. data/lib/rufus/scheduler/job_array.rb +92 -0
  9. data/lib/rufus/scheduler/jobs.rb +633 -0
  10. data/lib/rufus/scheduler/locks.rb +95 -0
  11. data/lib/rufus/scheduler/util.rb +306 -0
  12. data/lib/rufus/scheduler/zones.rb +174 -0
  13. data/lib/rufus/scheduler/zotime.rb +154 -0
  14. data/lib/rufus/scheduler.rb +608 -27
  15. data/rufus-scheduler.gemspec +6 -4
  16. data/spec/basics_spec.rb +54 -0
  17. data/spec/cronline_spec.rb +479 -152
  18. data/spec/error_spec.rb +139 -0
  19. data/spec/job_array_spec.rb +39 -0
  20. data/spec/job_at_spec.rb +58 -0
  21. data/spec/job_cron_spec.rb +128 -0
  22. data/spec/job_every_spec.rb +104 -0
  23. data/spec/job_in_spec.rb +20 -0
  24. data/spec/job_interval_spec.rb +68 -0
  25. data/spec/job_repeat_spec.rb +357 -0
  26. data/spec/job_spec.rb +498 -109
  27. data/spec/lock_custom_spec.rb +47 -0
  28. data/spec/lock_flock_spec.rb +47 -0
  29. data/spec/lock_lockfile_spec.rb +61 -0
  30. data/spec/lock_spec.rb +59 -0
  31. data/spec/parse_spec.rb +263 -0
  32. data/spec/schedule_at_spec.rb +158 -0
  33. data/spec/schedule_cron_spec.rb +66 -0
  34. data/spec/schedule_every_spec.rb +109 -0
  35. data/spec/schedule_in_spec.rb +80 -0
  36. data/spec/schedule_interval_spec.rb +128 -0
  37. data/spec/scheduler_spec.rb +928 -124
  38. data/spec/spec_helper.rb +126 -0
  39. data/spec/threads_spec.rb +96 -0
  40. data/spec/zotime_spec.rb +396 -0
  41. metadata +56 -33
  42. data/README.rdoc +0 -661
  43. data/lib/rufus/otime.rb +0 -3
  44. data/lib/rufus/sc/jobqueues.rb +0 -160
  45. data/lib/rufus/sc/jobs.rb +0 -471
  46. data/lib/rufus/sc/rtime.rb +0 -363
  47. data/lib/rufus/sc/scheduler.rb +0 -636
  48. data/lib/rufus/sc/version.rb +0 -32
  49. data/spec/at_in_spec.rb +0 -47
  50. data/spec/at_spec.rb +0 -125
  51. data/spec/blocking_spec.rb +0 -64
  52. data/spec/cron_spec.rb +0 -134
  53. data/spec/every_spec.rb +0 -304
  54. data/spec/exception_spec.rb +0 -113
  55. data/spec/in_spec.rb +0 -150
  56. data/spec/mutex_spec.rb +0 -159
  57. data/spec/rtime_spec.rb +0 -137
  58. data/spec/schedulable_spec.rb +0 -97
  59. data/spec/spec_base.rb +0 -87
  60. data/spec/stress_schedule_unschedule_spec.rb +0 -159
  61. data/spec/timeout_spec.rb +0 -148
  62. data/test/kjw.rb +0 -113
  63. data/test/t.rb +0 -20
data/spec/job_spec.rb CHANGED
@@ -2,239 +2,628 @@
2
2
  #
3
3
  # Specifying rufus-scheduler
4
4
  #
5
- # Wed Apr 27 00:51:07 JST 2011
5
+ # Wed Apr 17 06:00:59 JST 2013
6
6
  #
7
7
 
8
- require 'spec_base'
8
+ require 'spec_helper'
9
9
 
10
10
 
11
- describe 'job classes' do
11
+ describe Rufus::Scheduler::Job do
12
12
 
13
- before(:each) do
14
- @s = start_scheduler
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
15
24
  end
16
- after(:each) do
17
- stop_scheduler(@s)
25
+
26
+ after :each do
27
+
28
+ @scheduler.shutdown
29
+
30
+ Thread.abort_on_exception = @taoe
31
+
32
+ $stderr = @ose
18
33
  end
19
34
 
20
- describe Rufus::Scheduler::Job do
35
+ describe '#last_time' do
21
36
 
22
- describe '#running' do
37
+ it 'returns nil if the job never fired' do
23
38
 
24
- it 'returns false when the job is inactive' do
39
+ job = @scheduler.schedule_in '10d' do; end
25
40
 
26
- job = @s.in '2d' do
27
- end
41
+ expect(job.last_time).to eq(nil)
42
+ end
28
43
 
29
- job.running.should == false
30
- end
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) {}
31
66
 
32
- it 'returns true when the job is active' do
67
+ sleep 0.8
33
68
 
34
- job = @s.in 0 do
35
- sleep(100)
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)
36
77
  end
37
78
 
38
- wait_next_tick
79
+ sleep 0.4
39
80
 
40
- job.running.should == true
41
- end
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
42
95
 
43
- it 'returns false when the job hits some error' do
96
+ job.kill
44
97
 
45
- $exception = nil
98
+ expect(Thread.list.size).to eq(tls)
99
+ end
100
+
101
+ it 'makes the threads vacant' do
102
+
103
+ counter = 0
46
104
 
47
- def @s.handle_exception(j, e)
48
- #p e
49
- $exception = e
105
+ job =
106
+ @scheduler.schedule_in '0s' do
107
+ sleep 2
108
+ counter = counter + 1
50
109
  end
51
110
 
52
- job = @s.in 0 do
53
- raise "nada"
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
54
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
55
200
 
56
- wait_next_tick
201
+ it 'calls the job and let the scheduler handle errors' do
57
202
 
58
- $exception.should_not == nil
59
- job.running.should == false
203
+ $err = nil
204
+
205
+ def @scheduler.on_error(job, err)
206
+ $err = "#{job.class} #{job.original} #{err.message}"
207
+ rescue
208
+ p $!
60
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')
61
219
  end
220
+ end
62
221
 
63
- describe '#running?' do
222
+ describe '#call(false)' do
64
223
 
65
- it 'is an alias for #running' do
224
+ it 'calls the job and let errors slip through' do
66
225
 
67
- job = @s.in 0 do
68
- sleep(100)
226
+ job =
227
+ @scheduler.schedule_in('1d') do
228
+ fail 'fast'
69
229
  end
70
230
 
71
- wait_next_tick
231
+ begin
232
+
233
+ #job.call(false)
234
+ job.call # false is the default
235
+
236
+ expect(false).to eq(true)
72
237
 
73
- job.running?.should == true
238
+ rescue => ex
239
+
240
+ expect(ex.message).to eq('fast')
74
241
  end
75
242
  end
76
243
  end
77
244
 
78
- describe Rufus::Scheduler::AtJob do
245
+ context 'job-local variables' do
79
246
 
80
- describe '#unschedule' do
247
+ describe '#[]=' do
81
248
 
82
- it 'removes the job from the scheduler' do
249
+ it 'sets a job-local variable' do
83
250
 
84
- job = @s.at Time.now + 3 * 3600 do
85
- end
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
86
262
 
87
- wait_next_tick
263
+ describe '#[]' do
88
264
 
89
- job.unschedule
265
+ it 'returns nil if there is no such entry' do
90
266
 
91
- @s.jobs.size.should == 0
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)
92
278
  end
93
279
  end
94
280
 
95
- describe '#next_time' do
281
+ describe '#key?' do
96
282
 
97
- it 'returns the time when the job will trigger' do
283
+ it 'returns true if there is an entry with the given key' do
98
284
 
99
- t = Time.now + 3 * 3600
285
+ job = @scheduler.schedule_in '1s' do; end
286
+ job[:x] = :y
100
287
 
101
- job = @s.at Time.now + 3 * 3600 do
102
- end
288
+ expect(job.key?(:x)).to eq(true)
289
+ end
290
+ end
291
+
292
+ describe '#keys' do
103
293
 
104
- job.next_time.class.should == Time
105
- job.next_time.to_i.should == t.to_i
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 ])
106
302
  end
107
303
  end
108
304
  end
109
305
 
110
- describe Rufus::Scheduler::InJob do
306
+ context ':tag / :tags => [ t0, t1 ]' do
111
307
 
112
- describe '#unschedule' do
308
+ it 'accepts one tag' do
113
309
 
114
- it 'removes the job from the scheduler' do
310
+ job = @scheduler.in '10d', :job => true, :tag => 't0' do; end
115
311
 
116
- job = @s.in '2d' do
117
- end
312
+ expect(job.tags).to eq(%w[ t0 ])
313
+ end
118
314
 
119
- wait_next_tick
315
+ it 'accepts an array of tags' do
120
316
 
121
- job.unschedule
317
+ job = @scheduler.in '10d', :job => true, :tag => %w[ t0 t1 ] do; end
122
318
 
123
- @s.jobs.size.should == 0
124
- end
319
+ expect(job.tags).to eq(%w[ t0 t1 ])
125
320
  end
126
321
 
127
- describe '#next_time' do
322
+ it 'turns tags into strings' do
323
+
324
+ job = @scheduler.in '10d', :job => true, :tags => [ 1, 2 ] do; end
128
325
 
129
- it 'returns the time when the job will trigger' do
326
+ expect(job.tags).to eq(%w[ 1 2 ])
327
+ end
328
+ end
130
329
 
131
- t = Time.now + 3 * 3600
330
+ context ':blocking => true' do
132
331
 
133
- job = @s.in '3h' do
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)
134
337
  end
135
338
 
136
- job.next_time.class.should == Time
137
- job.next_time.to_i.should == t.to_i
138
- end
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)
139
346
  end
140
347
  end
141
348
 
142
- describe Rufus::Scheduler::EveryJob do
349
+ context 'default one thread per job behaviour' do
143
350
 
144
- describe '#next_time' do
351
+ it 'runs the job in a dedicated thread' do
145
352
 
146
- it 'returns the time when the job will trigger' do
353
+ job =
354
+ @scheduler.in('0s', :job => true) do
355
+ sleep(1)
356
+ end
147
357
 
148
- t = Time.now + 3 * 3600
358
+ sleep 0.4
149
359
 
150
- job = @s.every '3h' do
151
- end
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
152
393
 
153
- job.next_time.class.should == Time
154
- job.next_time.to_i.should == t.to_i
394
+ sleep 3
395
+
396
+ expect(job.threads.size).to eq(1)
155
397
  end
156
398
  end
399
+ end
400
+
401
+ context ':mutex' do
157
402
 
158
- describe '#paused?' do
403
+ context ':mutex => "mutex_name"' do
159
404
 
160
- it 'returns false initially' do
405
+ it 'prevents concurrent executions' do
161
406
 
162
- job = @s.every '3h' do; end
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
163
425
 
164
- job.paused?.should == false
426
+ expect(@scheduler.mutexes.keys).to eq(%w[ vladivostok ])
165
427
  end
166
428
  end
167
429
 
168
- describe '#pause' do
430
+ context ':mutex => mutex_instance' do
169
431
 
170
- it 'pauses the job' do
432
+ it 'prevents concurrent executions' do
171
433
 
172
- job = @s.every '3h' do; end
434
+ m = Mutex.new
173
435
 
174
- job.pause
436
+ j0 = @scheduler.in('0s', :job => true, :mutex => m) { sleep(3) }
437
+ j1 = @scheduler.in('0s', :job => true, :mutex => m) { sleep(3) }
175
438
 
176
- job.paused?.should == true
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([])
177
450
  end
178
451
  end
179
452
 
180
- describe '#resume' do
453
+ context ':mutex => [ array_of_mutex_names_or_instances ]' do
181
454
 
182
- it 'resumes the job' do
455
+ it 'prevents concurrent executions' do
183
456
 
184
- job = @s.every '3h' do; end
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
185
465
 
186
- job.resume
466
+ sleep 0.7
187
467
 
188
- job.paused?.should == false
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 ])
189
477
  end
190
478
  end
191
479
  end
192
480
 
193
- describe Rufus::Scheduler::CronJob do
481
+ context ':timeout => duration_or_point_in_time' do
194
482
 
195
- describe '#next_time' do
483
+ it 'interrupts the job it is stashed to (duration)' do
196
484
 
197
- it 'returns the time when the job will trigger' do
485
+ counter = 0
486
+ toe = nil
198
487
 
199
- job = @s.cron '* * * * *' do
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
200
497
  end
201
498
 
202
- job.next_time.class.should == Time
203
- (job.next_time.to_i - Time.now.to_i).should satisfy { |v| v < 60 }
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
204
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
205
550
  end
206
551
 
207
- describe '#paused?' do
552
+ it 'emits the timeout information to $stderr (default #on_error)' do
208
553
 
209
- it 'returns false initially' do
554
+ @scheduler.every('1s', :timeout => '0.5s') do
555
+ sleep 0.9
556
+ end
210
557
 
211
- job = @s.cron '* * * * *' do; end
558
+ sleep 2
212
559
 
213
- job.paused?.should == false
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
214
570
  end
571
+
572
+ sleep 3
573
+
574
+ expect(counter).to be > 1
215
575
  end
576
+ end
216
577
 
217
- describe '#pause' do
578
+ context 'work time' do
218
579
 
219
- it 'pauses the job' do
580
+ describe '#last_work_time' do
220
581
 
221
- job = @s.cron '* * * * *' do; end
582
+ it 'starts at 0' do
222
583
 
223
- job.pause
584
+ job = @scheduler.schedule_every '5m' do; end
224
585
 
225
- job.paused?.should == true
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
226
600
  end
227
601
  end
228
602
 
229
- describe '#resume' do
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
230
611
 
231
- it 'resumes the job' do
612
+ it 'gathers work times and computes the mean' do
232
613
 
233
- job = @s.cron '* * * * *' do; end
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
234
620
 
235
- job.resume
621
+ sleep 4.6
236
622
 
237
- job.paused?.should == false
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
238
627
  end
239
628
  end
240
629
  end