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.
- data/CHANGELOG.txt +76 -0
- data/CREDITS.txt +23 -0
- data/LICENSE.txt +1 -1
- data/README.md +1439 -0
- data/Rakefile +1 -5
- data/TODO.txt +149 -55
- data/lib/rufus/{sc → scheduler}/cronline.rb +167 -53
- data/lib/rufus/scheduler/job_array.rb +92 -0
- data/lib/rufus/scheduler/jobs.rb +633 -0
- data/lib/rufus/scheduler/locks.rb +95 -0
- data/lib/rufus/scheduler/util.rb +306 -0
- data/lib/rufus/scheduler/zones.rb +174 -0
- data/lib/rufus/scheduler/zotime.rb +154 -0
- data/lib/rufus/scheduler.rb +608 -27
- data/rufus-scheduler.gemspec +6 -4
- data/spec/basics_spec.rb +54 -0
- data/spec/cronline_spec.rb +479 -152
- data/spec/error_spec.rb +139 -0
- data/spec/job_array_spec.rb +39 -0
- data/spec/job_at_spec.rb +58 -0
- data/spec/job_cron_spec.rb +128 -0
- data/spec/job_every_spec.rb +104 -0
- data/spec/job_in_spec.rb +20 -0
- data/spec/job_interval_spec.rb +68 -0
- data/spec/job_repeat_spec.rb +357 -0
- data/spec/job_spec.rb +498 -109
- data/spec/lock_custom_spec.rb +47 -0
- data/spec/lock_flock_spec.rb +47 -0
- data/spec/lock_lockfile_spec.rb +61 -0
- data/spec/lock_spec.rb +59 -0
- data/spec/parse_spec.rb +263 -0
- data/spec/schedule_at_spec.rb +158 -0
- data/spec/schedule_cron_spec.rb +66 -0
- data/spec/schedule_every_spec.rb +109 -0
- data/spec/schedule_in_spec.rb +80 -0
- data/spec/schedule_interval_spec.rb +128 -0
- data/spec/scheduler_spec.rb +928 -124
- data/spec/spec_helper.rb +126 -0
- data/spec/threads_spec.rb +96 -0
- data/spec/zotime_spec.rb +396 -0
- metadata +56 -33
- data/README.rdoc +0 -661
- data/lib/rufus/otime.rb +0 -3
- data/lib/rufus/sc/jobqueues.rb +0 -160
- data/lib/rufus/sc/jobs.rb +0 -471
- data/lib/rufus/sc/rtime.rb +0 -363
- data/lib/rufus/sc/scheduler.rb +0 -636
- data/lib/rufus/sc/version.rb +0 -32
- data/spec/at_in_spec.rb +0 -47
- data/spec/at_spec.rb +0 -125
- data/spec/blocking_spec.rb +0 -64
- data/spec/cron_spec.rb +0 -134
- data/spec/every_spec.rb +0 -304
- data/spec/exception_spec.rb +0 -113
- data/spec/in_spec.rb +0 -150
- data/spec/mutex_spec.rb +0 -159
- data/spec/rtime_spec.rb +0 -137
- data/spec/schedulable_spec.rb +0 -97
- data/spec/spec_base.rb +0 -87
- data/spec/stress_schedule_unschedule_spec.rb +0 -159
- data/spec/timeout_spec.rb +0 -148
- data/test/kjw.rb +0 -113
- 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
|
5
|
+
# Wed Apr 17 06:00:59 JST 2013
|
6
6
|
#
|
7
7
|
|
8
|
-
require '
|
8
|
+
require 'spec_helper'
|
9
9
|
|
10
10
|
|
11
|
-
describe
|
11
|
+
describe Rufus::Scheduler::Job do
|
12
12
|
|
13
|
-
|
14
|
-
|
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
|
-
|
17
|
-
|
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
|
35
|
+
describe '#last_time' do
|
21
36
|
|
22
|
-
|
37
|
+
it 'returns nil if the job never fired' do
|
23
38
|
|
24
|
-
|
39
|
+
job = @scheduler.schedule_in '10d' do; end
|
25
40
|
|
26
|
-
|
27
|
-
|
41
|
+
expect(job.last_time).to eq(nil)
|
42
|
+
end
|
28
43
|
|
29
|
-
|
30
|
-
|
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
|
-
|
67
|
+
sleep 0.8
|
33
68
|
|
34
|
-
|
35
|
-
|
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
|
-
|
79
|
+
sleep 0.4
|
39
80
|
|
40
|
-
|
41
|
-
|
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
|
-
|
96
|
+
job.kill
|
44
97
|
|
45
|
-
|
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
|
-
|
48
|
-
|
49
|
-
|
105
|
+
job =
|
106
|
+
@scheduler.schedule_in '0s' do
|
107
|
+
sleep 2
|
108
|
+
counter = counter + 1
|
50
109
|
end
|
51
110
|
|
52
|
-
|
53
|
-
|
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
|
-
|
201
|
+
it 'calls the job and let the scheduler handle errors' do
|
57
202
|
|
58
|
-
|
59
|
-
|
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
|
-
|
222
|
+
describe '#call(false)' do
|
64
223
|
|
65
|
-
|
224
|
+
it 'calls the job and let errors slip through' do
|
66
225
|
|
67
|
-
|
68
|
-
|
226
|
+
job =
|
227
|
+
@scheduler.schedule_in('1d') do
|
228
|
+
fail 'fast'
|
69
229
|
end
|
70
230
|
|
71
|
-
|
231
|
+
begin
|
232
|
+
|
233
|
+
#job.call(false)
|
234
|
+
job.call # false is the default
|
235
|
+
|
236
|
+
expect(false).to eq(true)
|
72
237
|
|
73
|
-
|
238
|
+
rescue => ex
|
239
|
+
|
240
|
+
expect(ex.message).to eq('fast')
|
74
241
|
end
|
75
242
|
end
|
76
243
|
end
|
77
244
|
|
78
|
-
|
245
|
+
context 'job-local variables' do
|
79
246
|
|
80
|
-
describe '#
|
247
|
+
describe '#[]=' do
|
81
248
|
|
82
|
-
it '
|
249
|
+
it 'sets a job-local variable' do
|
83
250
|
|
84
|
-
job =
|
85
|
-
|
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
|
-
|
263
|
+
describe '#[]' do
|
88
264
|
|
89
|
-
|
265
|
+
it 'returns nil if there is no such entry' do
|
90
266
|
|
91
|
-
@
|
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 '#
|
281
|
+
describe '#key?' do
|
96
282
|
|
97
|
-
it 'returns
|
283
|
+
it 'returns true if there is an entry with the given key' do
|
98
284
|
|
99
|
-
|
285
|
+
job = @scheduler.schedule_in '1s' do; end
|
286
|
+
job[:x] = :y
|
100
287
|
|
101
|
-
job
|
102
|
-
|
288
|
+
expect(job.key?(:x)).to eq(true)
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
describe '#keys' do
|
103
293
|
|
104
|
-
|
105
|
-
|
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
|
-
|
306
|
+
context ':tag / :tags => [ t0, t1 ]' do
|
111
307
|
|
112
|
-
|
308
|
+
it 'accepts one tag' do
|
113
309
|
|
114
|
-
|
310
|
+
job = @scheduler.in '10d', :job => true, :tag => 't0' do; end
|
115
311
|
|
116
|
-
|
117
|
-
|
312
|
+
expect(job.tags).to eq(%w[ t0 ])
|
313
|
+
end
|
118
314
|
|
119
|
-
|
315
|
+
it 'accepts an array of tags' do
|
120
316
|
|
121
|
-
|
317
|
+
job = @scheduler.in '10d', :job => true, :tag => %w[ t0 t1 ] do; end
|
122
318
|
|
123
|
-
|
124
|
-
end
|
319
|
+
expect(job.tags).to eq(%w[ t0 t1 ])
|
125
320
|
end
|
126
321
|
|
127
|
-
|
322
|
+
it 'turns tags into strings' do
|
323
|
+
|
324
|
+
job = @scheduler.in '10d', :job => true, :tags => [ 1, 2 ] do; end
|
128
325
|
|
129
|
-
|
326
|
+
expect(job.tags).to eq(%w[ 1 2 ])
|
327
|
+
end
|
328
|
+
end
|
130
329
|
|
131
|
-
|
330
|
+
context ':blocking => true' do
|
132
331
|
|
133
|
-
|
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
|
-
|
137
|
-
|
138
|
-
|
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
|
-
|
349
|
+
context 'default one thread per job behaviour' do
|
143
350
|
|
144
|
-
|
351
|
+
it 'runs the job in a dedicated thread' do
|
145
352
|
|
146
|
-
|
353
|
+
job =
|
354
|
+
@scheduler.in('0s', :job => true) do
|
355
|
+
sleep(1)
|
356
|
+
end
|
147
357
|
|
148
|
-
|
358
|
+
sleep 0.4
|
149
359
|
|
150
|
-
|
151
|
-
|
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
|
-
|
154
|
-
|
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
|
-
|
403
|
+
context ':mutex => "mutex_name"' do
|
159
404
|
|
160
|
-
it '
|
405
|
+
it 'prevents concurrent executions' do
|
161
406
|
|
162
|
-
|
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
|
-
|
426
|
+
expect(@scheduler.mutexes.keys).to eq(%w[ vladivostok ])
|
165
427
|
end
|
166
428
|
end
|
167
429
|
|
168
|
-
|
430
|
+
context ':mutex => mutex_instance' do
|
169
431
|
|
170
|
-
it '
|
432
|
+
it 'prevents concurrent executions' do
|
171
433
|
|
172
|
-
|
434
|
+
m = Mutex.new
|
173
435
|
|
174
|
-
job
|
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
|
-
|
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
|
-
|
453
|
+
context ':mutex => [ array_of_mutex_names_or_instances ]' do
|
181
454
|
|
182
|
-
it '
|
455
|
+
it 'prevents concurrent executions' do
|
183
456
|
|
184
|
-
|
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
|
-
|
466
|
+
sleep 0.7
|
187
467
|
|
188
|
-
|
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
|
-
|
481
|
+
context ':timeout => duration_or_point_in_time' do
|
194
482
|
|
195
|
-
|
483
|
+
it 'interrupts the job it is stashed to (duration)' do
|
196
484
|
|
197
|
-
|
485
|
+
counter = 0
|
486
|
+
toe = nil
|
198
487
|
|
199
|
-
|
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
|
-
|
203
|
-
|
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
|
-
|
552
|
+
it 'emits the timeout information to $stderr (default #on_error)' do
|
208
553
|
|
209
|
-
|
554
|
+
@scheduler.every('1s', :timeout => '0.5s') do
|
555
|
+
sleep 0.9
|
556
|
+
end
|
210
557
|
|
211
|
-
|
558
|
+
sleep 2
|
212
559
|
|
213
|
-
|
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
|
-
|
578
|
+
context 'work time' do
|
218
579
|
|
219
|
-
|
580
|
+
describe '#last_work_time' do
|
220
581
|
|
221
|
-
|
582
|
+
it 'starts at 0' do
|
222
583
|
|
223
|
-
job.
|
584
|
+
job = @scheduler.schedule_every '5m' do; end
|
224
585
|
|
225
|
-
job.
|
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 '#
|
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 '
|
612
|
+
it 'gathers work times and computes the mean' do
|
232
613
|
|
233
|
-
job =
|
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
|
-
|
621
|
+
sleep 4.6
|
236
622
|
|
237
|
-
job.
|
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
|