rufus-scheduler 3.5.2 → 3.8.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +32 -0
- data/CREDITS.md +10 -0
- data/LICENSE.txt +1 -1
- data/Makefile +1 -1
- data/README.md +179 -85
- data/lib/rufus/scheduler/job_array.rb +37 -47
- data/lib/rufus/scheduler/jobs_core.rb +369 -0
- data/lib/rufus/scheduler/jobs_one_time.rb +53 -0
- data/lib/rufus/scheduler/jobs_repeat.rb +335 -0
- data/lib/rufus/scheduler/locks.rb +41 -44
- data/lib/rufus/scheduler/util.rb +166 -150
- data/lib/rufus/scheduler.rb +529 -432
- data/rufus-scheduler.gemspec +2 -3
- metadata +13 -12
- data/lib/rufus/scheduler/jobs.rb +0 -682
data/lib/rufus/scheduler/jobs.rb
DELETED
|
@@ -1,682 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
module Rufus
|
|
3
|
-
|
|
4
|
-
class Scheduler
|
|
5
|
-
|
|
6
|
-
#--
|
|
7
|
-
# job classes
|
|
8
|
-
#++
|
|
9
|
-
|
|
10
|
-
class Job
|
|
11
|
-
|
|
12
|
-
#
|
|
13
|
-
# Used by Job#kill
|
|
14
|
-
#
|
|
15
|
-
class KillSignal < StandardError; end
|
|
16
|
-
|
|
17
|
-
attr_reader :id
|
|
18
|
-
attr_reader :opts
|
|
19
|
-
attr_reader :original
|
|
20
|
-
attr_reader :scheduled_at
|
|
21
|
-
attr_reader :last_time
|
|
22
|
-
attr_reader :unscheduled_at
|
|
23
|
-
attr_reader :tags
|
|
24
|
-
attr_reader :count
|
|
25
|
-
attr_reader :last_work_time
|
|
26
|
-
attr_reader :mean_work_time
|
|
27
|
-
|
|
28
|
-
# next trigger time
|
|
29
|
-
#
|
|
30
|
-
attr_accessor :next_time
|
|
31
|
-
|
|
32
|
-
# previous "next trigger time"
|
|
33
|
-
#
|
|
34
|
-
attr_accessor :previous_time
|
|
35
|
-
|
|
36
|
-
# anything with a #call(job[, timet]) method,
|
|
37
|
-
# what gets actually triggered
|
|
38
|
-
#
|
|
39
|
-
attr_reader :callable
|
|
40
|
-
|
|
41
|
-
# a reference to the instance whose call method is the @callable
|
|
42
|
-
#
|
|
43
|
-
attr_reader :handler
|
|
44
|
-
|
|
45
|
-
def initialize(scheduler, original, opts, block)
|
|
46
|
-
|
|
47
|
-
@scheduler = scheduler
|
|
48
|
-
@original = original
|
|
49
|
-
@opts = opts
|
|
50
|
-
|
|
51
|
-
@handler = block
|
|
52
|
-
|
|
53
|
-
@callable =
|
|
54
|
-
if block.respond_to?(:arity)
|
|
55
|
-
block
|
|
56
|
-
elsif block.respond_to?(:call)
|
|
57
|
-
block.method(:call)
|
|
58
|
-
elsif block.is_a?(Class)
|
|
59
|
-
@handler = block.new
|
|
60
|
-
@handler.method(:call) rescue nil
|
|
61
|
-
else
|
|
62
|
-
nil
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
@scheduled_at = EoTime.now
|
|
66
|
-
@unscheduled_at = nil
|
|
67
|
-
@last_time = nil
|
|
68
|
-
|
|
69
|
-
@locals = {}
|
|
70
|
-
@local_mutex = Mutex.new
|
|
71
|
-
|
|
72
|
-
@id = determine_id
|
|
73
|
-
|
|
74
|
-
fail(
|
|
75
|
-
ArgumentError,
|
|
76
|
-
'missing block or callable to schedule',
|
|
77
|
-
caller[2..-1]
|
|
78
|
-
) unless @callable
|
|
79
|
-
|
|
80
|
-
@tags = Array(opts[:tag] || opts[:tags]).collect { |t| t.to_s }
|
|
81
|
-
|
|
82
|
-
@count = 0
|
|
83
|
-
@last_work_time = 0.0
|
|
84
|
-
@mean_work_time = 0.0
|
|
85
|
-
|
|
86
|
-
# tidy up options
|
|
87
|
-
|
|
88
|
-
if @opts[:allow_overlap] == false || @opts[:allow_overlapping] == false
|
|
89
|
-
@opts[:overlap] = false
|
|
90
|
-
end
|
|
91
|
-
if m = @opts[:mutex]
|
|
92
|
-
@opts[:mutex] = Array(m)
|
|
93
|
-
end
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
alias job_id id
|
|
97
|
-
|
|
98
|
-
# Will fail with an ArgumentError if the job frequency is higher than
|
|
99
|
-
# the scheduler frequency.
|
|
100
|
-
#
|
|
101
|
-
def check_frequency
|
|
102
|
-
|
|
103
|
-
# this parent implementation never fails
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
def trigger(time)
|
|
107
|
-
|
|
108
|
-
@previous_time = @next_time
|
|
109
|
-
set_next_time(time)
|
|
110
|
-
|
|
111
|
-
do_trigger(time)
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
# Trigger the job right now, off of its schedule.
|
|
115
|
-
#
|
|
116
|
-
# Done in collaboration with Piavka in
|
|
117
|
-
# https://github.com/jmettraux/rufus-scheduler/issues/214
|
|
118
|
-
#
|
|
119
|
-
def trigger_off_schedule(time=EoTime.now)
|
|
120
|
-
|
|
121
|
-
do_trigger(time)
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
def unschedule
|
|
125
|
-
|
|
126
|
-
@unscheduled_at = EoTime.now
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
def threads
|
|
130
|
-
|
|
131
|
-
Thread.list.select { |t| t[:rufus_scheduler_job] == self }
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
# Kills all the threads this Job currently has going on.
|
|
135
|
-
#
|
|
136
|
-
def kill
|
|
137
|
-
|
|
138
|
-
threads.each { |t| t.raise(KillSignal) }
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
def running?
|
|
142
|
-
|
|
143
|
-
threads.any?
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
def scheduled?
|
|
147
|
-
|
|
148
|
-
@scheduler.scheduled?(self)
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
def []=(key, value)
|
|
152
|
-
|
|
153
|
-
@local_mutex.synchronize { @locals[key] = value }
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
def [](key)
|
|
157
|
-
|
|
158
|
-
@local_mutex.synchronize { @locals[key] }
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
def key?(key)
|
|
162
|
-
|
|
163
|
-
@local_mutex.synchronize { @locals.key?(key) }
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
def keys
|
|
167
|
-
|
|
168
|
-
@local_mutex.synchronize { @locals.keys }
|
|
169
|
-
end
|
|
170
|
-
|
|
171
|
-
#def hash
|
|
172
|
-
# self.object_id
|
|
173
|
-
#end
|
|
174
|
-
#def eql?(o)
|
|
175
|
-
# o.class == self.class && o.hash == self.hash
|
|
176
|
-
#end
|
|
177
|
-
#
|
|
178
|
-
# might be necessary at some point
|
|
179
|
-
|
|
180
|
-
# Calls the callable (usually a block) wrapped in this Job instance.
|
|
181
|
-
#
|
|
182
|
-
# Warning: error rescueing is the responsibity of the caller.
|
|
183
|
-
#
|
|
184
|
-
def call(do_rescue=false)
|
|
185
|
-
|
|
186
|
-
do_call(EoTime.now, do_rescue)
|
|
187
|
-
end
|
|
188
|
-
|
|
189
|
-
protected
|
|
190
|
-
|
|
191
|
-
def callback(meth, time)
|
|
192
|
-
|
|
193
|
-
return true unless @scheduler.respond_to?(meth)
|
|
194
|
-
|
|
195
|
-
arity = @scheduler.method(meth).arity
|
|
196
|
-
args = [ self, time ][0, (arity < 0 ? 2 : arity)]
|
|
197
|
-
|
|
198
|
-
@scheduler.send(meth, *args)
|
|
199
|
-
end
|
|
200
|
-
|
|
201
|
-
def compute_timeout
|
|
202
|
-
|
|
203
|
-
if to = @opts[:timeout]
|
|
204
|
-
Rufus::Scheduler.parse(to)
|
|
205
|
-
else
|
|
206
|
-
nil
|
|
207
|
-
end
|
|
208
|
-
end
|
|
209
|
-
|
|
210
|
-
def mutex(m)
|
|
211
|
-
|
|
212
|
-
m.is_a?(Mutex) ? m : (@scheduler.mutexes[m.to_s] ||= Mutex.new)
|
|
213
|
-
end
|
|
214
|
-
|
|
215
|
-
def do_call(time, do_rescue)
|
|
216
|
-
|
|
217
|
-
args = [ self, time ][0, @callable.arity]
|
|
218
|
-
@callable.call(*args)
|
|
219
|
-
|
|
220
|
-
rescue StandardError => se
|
|
221
|
-
|
|
222
|
-
fail se unless do_rescue
|
|
223
|
-
|
|
224
|
-
return if se.is_a?(KillSignal) # discard
|
|
225
|
-
|
|
226
|
-
@scheduler.on_error(self, se)
|
|
227
|
-
|
|
228
|
-
# exceptions above StandardError do pass through
|
|
229
|
-
end
|
|
230
|
-
|
|
231
|
-
def do_trigger(time)
|
|
232
|
-
|
|
233
|
-
return if (
|
|
234
|
-
opts[:overlap] == false &&
|
|
235
|
-
running?
|
|
236
|
-
)
|
|
237
|
-
return if (
|
|
238
|
-
callback(:confirm_lock, time) &&
|
|
239
|
-
callback(:on_pre_trigger, time)
|
|
240
|
-
) == false
|
|
241
|
-
|
|
242
|
-
@count += 1
|
|
243
|
-
|
|
244
|
-
if opts[:blocking]
|
|
245
|
-
trigger_now(time)
|
|
246
|
-
else
|
|
247
|
-
trigger_queue(time)
|
|
248
|
-
end
|
|
249
|
-
end
|
|
250
|
-
|
|
251
|
-
def trigger_now(time)
|
|
252
|
-
|
|
253
|
-
t = EoTime.now
|
|
254
|
-
# if there are mutexes, t might be really bigger than time
|
|
255
|
-
|
|
256
|
-
Thread.current[:rufus_scheduler_job] = self
|
|
257
|
-
Thread.current[:rufus_scheduler_time] = t
|
|
258
|
-
Thread.current[:rufus_scheduler_timeout] = compute_timeout
|
|
259
|
-
|
|
260
|
-
@last_time = t
|
|
261
|
-
|
|
262
|
-
do_call(time, true)
|
|
263
|
-
|
|
264
|
-
ensure
|
|
265
|
-
|
|
266
|
-
@last_work_time =
|
|
267
|
-
EoTime.now - Thread.current[:rufus_scheduler_time]
|
|
268
|
-
@mean_work_time =
|
|
269
|
-
((@count - 1) * @mean_work_time + @last_work_time) / @count
|
|
270
|
-
|
|
271
|
-
post_trigger(time)
|
|
272
|
-
|
|
273
|
-
Thread.current[:rufus_scheduler_job] = nil
|
|
274
|
-
Thread.current[:rufus_scheduler_time] = nil
|
|
275
|
-
Thread.current[:rufus_scheduler_timeout] = nil
|
|
276
|
-
end
|
|
277
|
-
|
|
278
|
-
def post_trigger(time)
|
|
279
|
-
|
|
280
|
-
set_next_time(time, true)
|
|
281
|
-
|
|
282
|
-
callback(:on_post_trigger, time)
|
|
283
|
-
end
|
|
284
|
-
|
|
285
|
-
def start_work_thread
|
|
286
|
-
|
|
287
|
-
thread =
|
|
288
|
-
Thread.new do
|
|
289
|
-
|
|
290
|
-
Thread.current[:rufus_scheduler_job] = true
|
|
291
|
-
# indicates that the thread is going to be assigned immediately
|
|
292
|
-
|
|
293
|
-
Thread.current[@scheduler.thread_key] = true
|
|
294
|
-
Thread.current[:rufus_scheduler_work_thread] = true
|
|
295
|
-
|
|
296
|
-
loop do
|
|
297
|
-
|
|
298
|
-
job, time = @scheduler.work_queue.pop
|
|
299
|
-
|
|
300
|
-
break if @scheduler.started_at == nil
|
|
301
|
-
|
|
302
|
-
next if job.unscheduled_at
|
|
303
|
-
|
|
304
|
-
begin
|
|
305
|
-
|
|
306
|
-
(job.opts[:mutex] || []).reduce(
|
|
307
|
-
lambda { job.trigger_now(time) }
|
|
308
|
-
) do |b, m|
|
|
309
|
-
lambda { mutex(m).synchronize { b.call } }
|
|
310
|
-
end.call
|
|
311
|
-
|
|
312
|
-
rescue KillSignal
|
|
313
|
-
|
|
314
|
-
# simply go on looping
|
|
315
|
-
end
|
|
316
|
-
end
|
|
317
|
-
end
|
|
318
|
-
|
|
319
|
-
thread[@scheduler.thread_key] = true
|
|
320
|
-
thread[:rufus_scheduler_work_thread] = true
|
|
321
|
-
#
|
|
322
|
-
# same as above (in the thead block),
|
|
323
|
-
# but since it has to be done as quickly as possible.
|
|
324
|
-
# So, whoever is running first (scheduler thread vs job thread)
|
|
325
|
-
# sets this information
|
|
326
|
-
|
|
327
|
-
thread
|
|
328
|
-
end
|
|
329
|
-
|
|
330
|
-
def trigger_queue(time)
|
|
331
|
-
|
|
332
|
-
threads = @scheduler.work_threads
|
|
333
|
-
|
|
334
|
-
vac = threads.select { |t| t[:rufus_scheduler_job] == nil }.size
|
|
335
|
-
que = @scheduler.work_queue.size
|
|
336
|
-
|
|
337
|
-
cur = threads.size
|
|
338
|
-
max = @scheduler.max_work_threads
|
|
339
|
-
|
|
340
|
-
start_work_thread if vac - que < 1 && cur < max
|
|
341
|
-
|
|
342
|
-
@scheduler.work_queue << [ self, time ]
|
|
343
|
-
end
|
|
344
|
-
end
|
|
345
|
-
|
|
346
|
-
class OneTimeJob < Job
|
|
347
|
-
|
|
348
|
-
alias time next_time
|
|
349
|
-
|
|
350
|
-
def occurrences(time0, time1)
|
|
351
|
-
|
|
352
|
-
(time >= time0 && time <= time1) ? [ time ] : []
|
|
353
|
-
end
|
|
354
|
-
|
|
355
|
-
protected
|
|
356
|
-
|
|
357
|
-
def determine_id
|
|
358
|
-
|
|
359
|
-
[
|
|
360
|
-
self.class.name.split(':').last.downcase[0..-4],
|
|
361
|
-
@scheduled_at.to_f,
|
|
362
|
-
@next_time.to_f,
|
|
363
|
-
(self.object_id < 0 ? 'm' : '') + self.object_id.to_s
|
|
364
|
-
].map(&:to_s).join('_')
|
|
365
|
-
end
|
|
366
|
-
|
|
367
|
-
# There is no next_time for one time jobs, hence the false.
|
|
368
|
-
#
|
|
369
|
-
def set_next_time(trigger_time, is_post=false)
|
|
370
|
-
|
|
371
|
-
@next_time = is_post ? nil : false
|
|
372
|
-
end
|
|
373
|
-
end
|
|
374
|
-
|
|
375
|
-
class AtJob < OneTimeJob
|
|
376
|
-
|
|
377
|
-
def initialize(scheduler, time, opts, block)
|
|
378
|
-
|
|
379
|
-
super(scheduler, time, opts, block)
|
|
380
|
-
|
|
381
|
-
@next_time =
|
|
382
|
-
opts[:_t] || Rufus::Scheduler.parse_at(time, opts)
|
|
383
|
-
end
|
|
384
|
-
end
|
|
385
|
-
|
|
386
|
-
class InJob < OneTimeJob
|
|
387
|
-
|
|
388
|
-
def initialize(scheduler, duration, opts, block)
|
|
389
|
-
|
|
390
|
-
super(scheduler, duration, opts, block)
|
|
391
|
-
|
|
392
|
-
@next_time =
|
|
393
|
-
@scheduled_at +
|
|
394
|
-
opts[:_t] || Rufus::Scheduler.parse_in(duration, opts)
|
|
395
|
-
end
|
|
396
|
-
end
|
|
397
|
-
|
|
398
|
-
class RepeatJob < Job
|
|
399
|
-
|
|
400
|
-
attr_reader :paused_at
|
|
401
|
-
|
|
402
|
-
attr_reader :first_at
|
|
403
|
-
attr_reader :last_at
|
|
404
|
-
attr_accessor :times
|
|
405
|
-
|
|
406
|
-
def initialize(scheduler, duration, opts, block)
|
|
407
|
-
|
|
408
|
-
super
|
|
409
|
-
|
|
410
|
-
@paused_at = nil
|
|
411
|
-
|
|
412
|
-
@times = opts[:times]
|
|
413
|
-
|
|
414
|
-
fail ArgumentError.new(
|
|
415
|
-
"cannot accept :times => #{@times.inspect}, not nil or an int"
|
|
416
|
-
) unless @times == nil || @times.is_a?(Integer)
|
|
417
|
-
|
|
418
|
-
self.first_at =
|
|
419
|
-
opts[:first] || opts[:first_time] ||
|
|
420
|
-
opts[:first_at] || opts[:first_in] ||
|
|
421
|
-
nil
|
|
422
|
-
self.last_at =
|
|
423
|
-
opts[:last] || opts[:last_at] || opts[:last_in]
|
|
424
|
-
end
|
|
425
|
-
|
|
426
|
-
def first_at=(first)
|
|
427
|
-
|
|
428
|
-
return (@first_at = nil) if first == nil
|
|
429
|
-
|
|
430
|
-
n0 = EoTime.now
|
|
431
|
-
n1 = n0 + 0.003
|
|
432
|
-
|
|
433
|
-
first = n0 if first == :now || first == :immediately || first == 0
|
|
434
|
-
fdur = Rufus::Scheduler.parse_duration(first, no_error: true)
|
|
435
|
-
|
|
436
|
-
@first_at = (fdur && (EoTime.now + fdur)) || EoTime.make(first)
|
|
437
|
-
@first_at = n1 if @first_at >= n0 && @first_at < n1
|
|
438
|
-
|
|
439
|
-
fail ArgumentError.new(
|
|
440
|
-
"cannot set first[_at|_in] in the past: " +
|
|
441
|
-
"#{first.inspect} -> #{@first_at.inspect}"
|
|
442
|
-
) if @first_at < n0
|
|
443
|
-
|
|
444
|
-
@first_at
|
|
445
|
-
end
|
|
446
|
-
|
|
447
|
-
def last_at=(last)
|
|
448
|
-
|
|
449
|
-
@last_at =
|
|
450
|
-
if last
|
|
451
|
-
ldur = Rufus::Scheduler.parse_duration(last, no_error: true)
|
|
452
|
-
(ldur && (EoTime.now + ldur)) || EoTime.make(last)
|
|
453
|
-
else
|
|
454
|
-
nil
|
|
455
|
-
end
|
|
456
|
-
|
|
457
|
-
fail ArgumentError.new(
|
|
458
|
-
"cannot set last[_at|_in] in the past: " +
|
|
459
|
-
"#{last.inspect} -> #{@last_at.inspect}"
|
|
460
|
-
) if last && @last_at < EoTime.now
|
|
461
|
-
|
|
462
|
-
@last_at
|
|
463
|
-
end
|
|
464
|
-
|
|
465
|
-
def trigger(time)
|
|
466
|
-
|
|
467
|
-
return if @paused_at
|
|
468
|
-
|
|
469
|
-
return (@next_time = nil) if @times && @times < 1
|
|
470
|
-
return (@next_time = nil) if @last_at && time >= @last_at
|
|
471
|
-
#
|
|
472
|
-
# It keeps jobs one step too much in @jobs, but it's OK
|
|
473
|
-
|
|
474
|
-
super
|
|
475
|
-
|
|
476
|
-
@times -= 1 if @times
|
|
477
|
-
end
|
|
478
|
-
|
|
479
|
-
def pause
|
|
480
|
-
|
|
481
|
-
@paused_at = EoTime.now
|
|
482
|
-
end
|
|
483
|
-
|
|
484
|
-
def resume
|
|
485
|
-
|
|
486
|
-
@paused_at = nil
|
|
487
|
-
end
|
|
488
|
-
|
|
489
|
-
def paused?
|
|
490
|
-
|
|
491
|
-
@paused_at != nil
|
|
492
|
-
end
|
|
493
|
-
|
|
494
|
-
def determine_id
|
|
495
|
-
|
|
496
|
-
[
|
|
497
|
-
self.class.name.split(':').last.downcase[0..-4],
|
|
498
|
-
@scheduled_at.to_f,
|
|
499
|
-
(self.object_id < 0 ? 'm' : '') + self.object_id.to_s
|
|
500
|
-
].map(&:to_s).join('_')
|
|
501
|
-
end
|
|
502
|
-
|
|
503
|
-
def occurrences(time0, time1)
|
|
504
|
-
|
|
505
|
-
a = []
|
|
506
|
-
|
|
507
|
-
nt = @next_time
|
|
508
|
-
ts = @times
|
|
509
|
-
|
|
510
|
-
loop do
|
|
511
|
-
|
|
512
|
-
break if nt > time1
|
|
513
|
-
break if ts && ts <= 0
|
|
514
|
-
|
|
515
|
-
a << nt if nt >= time0
|
|
516
|
-
|
|
517
|
-
nt = next_time_from(nt)
|
|
518
|
-
ts = ts - 1 if ts
|
|
519
|
-
end
|
|
520
|
-
|
|
521
|
-
a
|
|
522
|
-
end
|
|
523
|
-
end
|
|
524
|
-
|
|
525
|
-
#
|
|
526
|
-
# A parent class of EveryJob and IntervalJob
|
|
527
|
-
#
|
|
528
|
-
class EvInJob < RepeatJob
|
|
529
|
-
|
|
530
|
-
def first_at=(first)
|
|
531
|
-
|
|
532
|
-
@next_time = super
|
|
533
|
-
end
|
|
534
|
-
end
|
|
535
|
-
|
|
536
|
-
class EveryJob < EvInJob
|
|
537
|
-
|
|
538
|
-
attr_reader :frequency
|
|
539
|
-
|
|
540
|
-
def initialize(scheduler, duration, opts, block)
|
|
541
|
-
|
|
542
|
-
super(scheduler, duration, opts, block)
|
|
543
|
-
|
|
544
|
-
@frequency = Rufus::Scheduler.parse_in(@original)
|
|
545
|
-
|
|
546
|
-
fail ArgumentError.new(
|
|
547
|
-
"cannot schedule #{self.class} with a frequency " +
|
|
548
|
-
"of #{@frequency.inspect} (#{@original.inspect})"
|
|
549
|
-
) if @frequency <= 0
|
|
550
|
-
|
|
551
|
-
set_next_time(nil)
|
|
552
|
-
end
|
|
553
|
-
|
|
554
|
-
def check_frequency
|
|
555
|
-
|
|
556
|
-
fail ArgumentError.new(
|
|
557
|
-
"job frequency (#{@frequency}s) is higher than " +
|
|
558
|
-
"scheduler frequency (#{@scheduler.frequency}s)"
|
|
559
|
-
) if @frequency < @scheduler.frequency
|
|
560
|
-
end
|
|
561
|
-
|
|
562
|
-
protected
|
|
563
|
-
|
|
564
|
-
def set_next_time(trigger_time, is_post=false)
|
|
565
|
-
|
|
566
|
-
return if is_post
|
|
567
|
-
|
|
568
|
-
n = EoTime.now
|
|
569
|
-
|
|
570
|
-
@next_time =
|
|
571
|
-
if @first_at && (trigger_time == nil || @first_at > n)
|
|
572
|
-
@first_at
|
|
573
|
-
else
|
|
574
|
-
(@next_time || n) + @frequency
|
|
575
|
-
end
|
|
576
|
-
end
|
|
577
|
-
|
|
578
|
-
def next_time_from(time)
|
|
579
|
-
|
|
580
|
-
time + @frequency
|
|
581
|
-
end
|
|
582
|
-
end
|
|
583
|
-
|
|
584
|
-
class IntervalJob < EvInJob
|
|
585
|
-
|
|
586
|
-
attr_reader :interval
|
|
587
|
-
|
|
588
|
-
def initialize(scheduler, interval, opts, block)
|
|
589
|
-
|
|
590
|
-
super(scheduler, interval, opts, block)
|
|
591
|
-
|
|
592
|
-
@interval = Rufus::Scheduler.parse_in(@original)
|
|
593
|
-
|
|
594
|
-
fail ArgumentError.new(
|
|
595
|
-
"cannot schedule #{self.class} with an interval " +
|
|
596
|
-
"of #{@interval.inspect} (#{@original.inspect})"
|
|
597
|
-
) if @interval <= 0
|
|
598
|
-
|
|
599
|
-
set_next_time(nil)
|
|
600
|
-
end
|
|
601
|
-
|
|
602
|
-
protected
|
|
603
|
-
|
|
604
|
-
def set_next_time(trigger_time, is_post=false)
|
|
605
|
-
|
|
606
|
-
@next_time =
|
|
607
|
-
if is_post
|
|
608
|
-
EoTime.now + @interval
|
|
609
|
-
elsif trigger_time.nil?
|
|
610
|
-
if @first_at == nil || @first_at < Time.now
|
|
611
|
-
EoTime.now + @interval
|
|
612
|
-
else
|
|
613
|
-
@first_at
|
|
614
|
-
end
|
|
615
|
-
else
|
|
616
|
-
false
|
|
617
|
-
end
|
|
618
|
-
end
|
|
619
|
-
|
|
620
|
-
def next_time_from(time)
|
|
621
|
-
|
|
622
|
-
time + @mean_work_time + @interval
|
|
623
|
-
end
|
|
624
|
-
end
|
|
625
|
-
|
|
626
|
-
class CronJob < RepeatJob
|
|
627
|
-
|
|
628
|
-
attr_reader :cron_line
|
|
629
|
-
|
|
630
|
-
def initialize(scheduler, cronline, opts, block)
|
|
631
|
-
|
|
632
|
-
super(scheduler, cronline, opts, block)
|
|
633
|
-
|
|
634
|
-
@cron_line = opts[:_t] || ::Fugit::Cron.parse(cronline)
|
|
635
|
-
|
|
636
|
-
set_next_time(nil)
|
|
637
|
-
end
|
|
638
|
-
|
|
639
|
-
def check_frequency
|
|
640
|
-
|
|
641
|
-
return if @scheduler.frequency <= 1
|
|
642
|
-
#
|
|
643
|
-
# The minimum time delta in a cron job is 1 second, so if the
|
|
644
|
-
# scheduler frequency is less than that, no worries.
|
|
645
|
-
|
|
646
|
-
f = @cron_line.rough_frequency
|
|
647
|
-
|
|
648
|
-
fail ArgumentError.new(
|
|
649
|
-
"job frequency (min ~#{f}s) is higher than " +
|
|
650
|
-
"scheduler frequency (#{@scheduler.frequency}s)"
|
|
651
|
-
) if f < @scheduler.frequency
|
|
652
|
-
end
|
|
653
|
-
|
|
654
|
-
def brute_frequency
|
|
655
|
-
|
|
656
|
-
@cron_line.brute_frequency
|
|
657
|
-
end
|
|
658
|
-
|
|
659
|
-
def rough_frequency
|
|
660
|
-
|
|
661
|
-
@cron_line.rough_frequency
|
|
662
|
-
end
|
|
663
|
-
|
|
664
|
-
protected
|
|
665
|
-
|
|
666
|
-
def set_next_time(trigger_time, is_post=false)
|
|
667
|
-
|
|
668
|
-
@next_time = next_time_from(trigger_time || Time.now)
|
|
669
|
-
end
|
|
670
|
-
|
|
671
|
-
def next_time_from(time)
|
|
672
|
-
|
|
673
|
-
if @first_at == nil || @first_at <= time
|
|
674
|
-
@cron_line.next_time(time)
|
|
675
|
-
else
|
|
676
|
-
@first_at
|
|
677
|
-
end
|
|
678
|
-
end
|
|
679
|
-
end
|
|
680
|
-
end
|
|
681
|
-
end
|
|
682
|
-
|