rufus-scheduler 2.0.24 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
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