rufus-scheduler 3.8.1 → 3.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/CREDITS.md +4 -0
- data/LICENSE.txt +1 -1
- data/Makefile +4 -4
- data/README.md +72 -11
- data/lib/rufus/scheduler/jobs_core.rb +22 -3
- data/lib/rufus/scheduler/jobs_one_time.rb +9 -1
- data/lib/rufus/scheduler/jobs_repeat.rb +0 -13
- data/lib/rufus/scheduler.rb +30 -10
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec5b405be33c70ef390f2d8c47be112c7cf05c32eda58a0a764bbf42fae1b5d6
|
4
|
+
data.tar.gz: c03f4dc830c7041a530d899d69d91f7409ba481bbd12241152543b0eae20fc23
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e5d992e7ad0a23530320731348c3c890b90d0184851d7faf807a36e4c6dd5d879579a478478055beab569e14603f129a7ad15022f2bf6b297a3e9f27cb31fb4c
|
7
|
+
data.tar.gz: 85be36f54b76add7704907a3a7d43339a392d49fc05e03b62dc28e20a88eeb03cd132f64e1f3a1378f2e6e3128d57fb7fa4fe6f6ccd89fdd8b1d24fe93312583
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,19 @@
|
|
2
2
|
# CHANGELOG.md
|
3
3
|
|
4
4
|
|
5
|
+
### rufus-scheduler 3.9.0 - released 2023-06-02
|
6
|
+
|
7
|
+
* Add note about Chronic and "Wed at 2pm", gh-340
|
8
|
+
* Let AtJob and InJob accept discard_past:
|
9
|
+
* Enforce discard_past for At and In jobs, gh-339
|
10
|
+
|
11
|
+
|
12
|
+
### rufus-scheduler 3.8.2 - released 2022-07-12
|
13
|
+
|
14
|
+
* Prevent error in shutdown when @thread is current Thread, gh-337
|
15
|
+
* Rescue errors on the scheduling thread, gh-335
|
16
|
+
|
17
|
+
|
5
18
|
### rufus-scheduler 3.8.1 - released 2022-01-11
|
6
19
|
|
7
20
|
* Suppress warning about @resume_discard_past
|
data/CREDITS.md
CHANGED
@@ -4,6 +4,10 @@
|
|
4
4
|
|
5
5
|
## Contributors
|
6
6
|
|
7
|
+
* Bence Monus https://github.com/cromega gh-337 on_error and friends
|
8
|
+
* Talia Wong https://github.com/blowfishpro gh-335 on_error and friends
|
9
|
+
* Konstantin https://github.com/fa11enangel gh-334 nodejitsu link
|
10
|
+
* Olle Jonsson https://github.com/olleolleolle gh-333
|
7
11
|
* Sol Ackerman https://github.com/solarckerman gh-332
|
8
12
|
* John Bachir https://github.com/jjb gh-310 gh-327
|
9
13
|
* Daniel Berger https://github.com/djberg96 gh-300
|
data/LICENSE.txt
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
|
2
|
-
Copyright (c) 2005-
|
2
|
+
Copyright (c) 2005-2023, John Mettraux, jmettraux@gmail.com
|
3
3
|
|
4
4
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
5
|
of this software and associated documentation files (the "Software"), to deal
|
data/Makefile
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
|
2
|
-
NAME
|
3
|
-
|
4
|
-
VERSION
|
5
|
-
|
2
|
+
NAME != \
|
3
|
+
ruby -e "s = eval(File.read(Dir['*.gemspec'][0])); puts s.name"
|
4
|
+
VERSION != \
|
5
|
+
ruby -e "s = eval(File.read(Dir['*.gemspec'][0])); puts s.version"
|
6
6
|
|
7
7
|
count_lines:
|
8
8
|
find lib -name "*.rb" | xargs cat | ruby -e "p STDIN.readlines.count { |l| l = l.strip; l[0, 1] != '#' && l != '' }"
|
data/README.md
CHANGED
@@ -3,7 +3,6 @@
|
|
3
3
|
|
4
4
|
[![tests](https://github.com/jmettraux/rufus-scheduler/workflows/test/badge.svg)](https://github.com/jmettraux/rufus-scheduler/actions)
|
5
5
|
[![Gem Version](https://badge.fury.io/rb/rufus-scheduler.svg)](https://badge.fury.io/rb/rufus-scheduler)
|
6
|
-
[![Join the chat at https://gitter.im/floraison/fugit](https://badges.gitter.im/floraison/fugit.svg)](https://gitter.im/floraison/fugit?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
7
6
|
|
8
7
|
Job scheduler for Ruby (at, cron, in and every jobs).
|
9
8
|
|
@@ -106,7 +105,7 @@ I'll drive you right to the [tracks](#so-rails).
|
|
106
105
|
* Rufus::Scheduler::TimeOutError renamed to Rufus::Scheduler::TimeoutError
|
107
106
|
* Introduction of "interval" jobs. Whereas "every" jobs are like "every 10 minutes, do this", interval jobs are like "do that, then wait for 10 minutes, then do that again, and so on"
|
108
107
|
* Introduction of a lockfile: true/filename mechanism to prevent multiple schedulers from executing
|
109
|
-
* "discard_past" is on by default. If the scheduler (its host) sleeps for 1 hour and a `every '10m'` job is on, it will trigger once at wakeup, not 6 times (discard_past was false by default in rufus-scheduler 2.x).
|
108
|
+
* "discard_past" is on by default. If the scheduler (its host) sleeps for 1 hour and a `every '10m'` job is on, it will trigger once at wakeup, not 6 times (discard_past was false by default in rufus-scheduler 2.x).
|
110
109
|
* Introduction of Scheduler #on_pre_trigger and #on_post_trigger callback points
|
111
110
|
|
112
111
|
|
@@ -120,12 +119,6 @@ Go read [how to report bugs effectively](https://www.chiark.greenend.org.uk/~sgt
|
|
120
119
|
|
121
120
|
Update: [help_help.md](https://gist.github.com/jmettraux/310fed75f568fd731814) might help help you.
|
122
121
|
|
123
|
-
### on Gitter
|
124
|
-
|
125
|
-
You can find help via chat over at [https://gitter.im/floraison/fugit](https://gitter.im/floraison/fugit). It's [fugit](https://github.com/floraison/fugit), [et-orbi](https://github.com/floraison/et-orbi), and rufus-scheduler combined chat room.
|
126
|
-
|
127
|
-
Please be courteous.
|
128
|
-
|
129
122
|
### issues
|
130
123
|
|
131
124
|
Yes, issues can be reported in [rufus-scheduler issues](https://github.com/jmettraux/rufus-scheduler/issues), I'd actually prefer bugs in there. If there is nothing wrong with rufus-scheduler, a [Stack Overflow question](https://stackoverflow.com/questions/ask?tags=rufus-scheduler+ruby) is better.
|
@@ -133,7 +126,7 @@ Yes, issues can be reported in [rufus-scheduler issues](https://github.com/jmett
|
|
133
126
|
### faq
|
134
127
|
|
135
128
|
* [It doesn't work...](https://www.chiark.greenend.org.uk/~sgtatham/bugs.html)
|
136
|
-
* [I want a refund](https://blog.nodejitsu.com/getting-refunds-on-open-source-projects)
|
129
|
+
* [I want a refund](https://web.archive.org/web/20160425034214/http://blog.nodejitsu.com/getting-refunds-on-open-source-projects/)
|
137
130
|
* [Passenger and rufus-scheduler](https://stackoverflow.com/questions/18108719/debugging-rufus-scheduler/18156180#18156180)
|
138
131
|
* [Passenger and rufus-scheduler (2)](https://stackoverflow.com/questions/21861387/rufus-cron-job-not-working-in-apache-passenger#answer-21868555)
|
139
132
|
* [Passenger in-depth spawn methods](https://www.phusionpassenger.com/library/indepth/ruby/spawn_methods/)
|
@@ -198,7 +191,34 @@ Interval jobs trigger, execute and then trigger again after the interval elapsed
|
|
198
191
|
|
199
192
|
Cron jobs are based on the venerable cron utility (```man 5 crontab```). They trigger following a pattern given in (almost) the same language cron uses.
|
200
193
|
|
201
|
-
|
194
|
+
### Chronic and "Wed at 2pm"
|
195
|
+
|
196
|
+
By default, rufus-scheduler relies on Ruby to parse strings like "Wed at 2pm". But most of the time, when calling this on Thursday, the day before is "invoked". Relying on [Chronic](https://github.com/mojombo/chronic) might solve the issue.
|
197
|
+
|
198
|
+
Compare
|
199
|
+
|
200
|
+
```ruby
|
201
|
+
require 'rufus-scheduler'
|
202
|
+
|
203
|
+
scheduler = Rufus::Scheduler.new
|
204
|
+
|
205
|
+
scheduler.at('Wed at 2pm') do
|
206
|
+
# ... might point in the past and thus get triggered immediately
|
207
|
+
end
|
208
|
+
```
|
209
|
+
|
210
|
+
with
|
211
|
+
|
212
|
+
```ruby
|
213
|
+
require 'chronic'
|
214
|
+
require 'rufus-scheduler'
|
215
|
+
|
216
|
+
scheduler = Rufus::Scheduler.new
|
217
|
+
|
218
|
+
scheduler.at('Wed at 2pm') do
|
219
|
+
# ... will point to a time in the future and trigger appropriately
|
220
|
+
end
|
221
|
+
```
|
202
222
|
|
203
223
|
### #schedule_x vs #x
|
204
224
|
|
@@ -561,6 +581,43 @@ job.times = 10
|
|
561
581
|
# 10 days and it will be over
|
562
582
|
```
|
563
583
|
|
584
|
+
### discard_past: false/true/:fail
|
585
|
+
|
586
|
+
`in` and `at` accept a `discard_past:` option since rufus-scheduler 3.9.0:
|
587
|
+
|
588
|
+
```ruby
|
589
|
+
require 'rufus-scheduler'
|
590
|
+
|
591
|
+
scheduler = Rufus::Scheduler.new
|
592
|
+
|
593
|
+
scheduler.in(-3600, discard_past: true) {}
|
594
|
+
# the job will never get scheduled
|
595
|
+
|
596
|
+
scheduler.in(-3600, discard_past: false) {}
|
597
|
+
# the job will trigger immediately
|
598
|
+
|
599
|
+
scheduler.in(-3600, discard_past: :fail) {}
|
600
|
+
# will raise an error...
|
601
|
+
```
|
602
|
+
|
603
|
+
Please note that `discard_past` can be set at the scheduler level:
|
604
|
+
|
605
|
+
```ruby
|
606
|
+
require 'rufus-scheduler'
|
607
|
+
|
608
|
+
s0 = Rufus::Scheduler.new(discard_past: true) # default
|
609
|
+
|
610
|
+
s1 = Rufus::Scheduler.new(discard_past: false)
|
611
|
+
# or
|
612
|
+
s1 = Rufus::Scheduler.new
|
613
|
+
s1.discard_past = false
|
614
|
+
|
615
|
+
s2 = Rufus::Scheduler.new(discard_past: :fail)
|
616
|
+
# or
|
617
|
+
s2 = Rufus::Scheduler.new
|
618
|
+
s2.discard_past = :fail
|
619
|
+
```
|
620
|
+
|
564
621
|
|
565
622
|
## Job methods
|
566
623
|
|
@@ -860,7 +917,11 @@ require 'rufus-scheduler'
|
|
860
917
|
s = Rufus::Scheduler.new
|
861
918
|
|
862
919
|
def s.on_error(job, err)
|
863
|
-
|
920
|
+
if job
|
921
|
+
p [ 'error in scheduled job', job.class, job.original, err.message ]
|
922
|
+
else
|
923
|
+
p [ 'error while scheduling', err.message ]
|
924
|
+
end
|
864
925
|
rescue
|
865
926
|
p $!
|
866
927
|
end
|
@@ -67,6 +67,8 @@ class Rufus::Scheduler::Job
|
|
67
67
|
@unscheduled_at = nil
|
68
68
|
@last_time = nil
|
69
69
|
|
70
|
+
@discard_past = opts[:discard_past]
|
71
|
+
|
70
72
|
@locals = opts[:locals] || opts[:l] || {}
|
71
73
|
@local_mutex = Mutex.new
|
72
74
|
|
@@ -74,9 +76,7 @@ class Rufus::Scheduler::Job
|
|
74
76
|
@name = opts[:name] || opts[:n]
|
75
77
|
|
76
78
|
fail(
|
77
|
-
ArgumentError,
|
78
|
-
'missing block or callable to schedule',
|
79
|
-
caller[2..-1]
|
79
|
+
ArgumentError, 'missing block or callable to schedule', caller[2..-1]
|
80
80
|
) unless @callable
|
81
81
|
|
82
82
|
@tags = Array(opts[:tag] || opts[:tags]).collect { |t| t.to_s }
|
@@ -103,6 +103,14 @@ class Rufus::Scheduler::Job
|
|
103
103
|
end
|
104
104
|
alias location source_location
|
105
105
|
|
106
|
+
# Returns true if the job is scheduled in the past.
|
107
|
+
# Used for OneTimeJob when discard_past == true
|
108
|
+
#
|
109
|
+
def past?
|
110
|
+
|
111
|
+
false # by default
|
112
|
+
end
|
113
|
+
|
106
114
|
# Will fail with an ArgumentError if the job frequency is higher than
|
107
115
|
# the scheduler frequency.
|
108
116
|
#
|
@@ -365,5 +373,16 @@ class Rufus::Scheduler::Job
|
|
365
373
|
|
366
374
|
@scheduler.work_queue << [ self, time ]
|
367
375
|
end
|
376
|
+
|
377
|
+
# Scheduler level < Job level < this resume()'s level
|
378
|
+
#
|
379
|
+
def discard_past?
|
380
|
+
|
381
|
+
dp = @scheduler.discard_past
|
382
|
+
dp = @discard_past if @discard_past != nil
|
383
|
+
dp = @resume_discard_past if @resume_discard_past != nil
|
384
|
+
|
385
|
+
dp
|
386
|
+
end
|
368
387
|
end
|
369
388
|
|
@@ -8,6 +8,14 @@ class Rufus::Scheduler::OneTimeJob < Rufus::Scheduler::Job
|
|
8
8
|
(time >= time0 && time <= time1) ? [ time ] : []
|
9
9
|
end
|
10
10
|
|
11
|
+
# Used when discard_past? is set to true or :fail at scheduler or job level...
|
12
|
+
#
|
13
|
+
def past?
|
14
|
+
|
15
|
+
@next_time &&
|
16
|
+
@next_time < Time.now - @scheduler.frequency
|
17
|
+
end
|
18
|
+
|
11
19
|
protected
|
12
20
|
|
13
21
|
def determine_id
|
@@ -20,7 +28,7 @@ class Rufus::Scheduler::OneTimeJob < Rufus::Scheduler::Job
|
|
20
28
|
].map(&:to_s).join('_')
|
21
29
|
end
|
22
30
|
|
23
|
-
# There is no
|
31
|
+
# There is no "next time" for one time jobs, hence the false.
|
24
32
|
#
|
25
33
|
def set_next_time(trigger_time, is_post=false, now=nil)
|
26
34
|
|
@@ -93,7 +93,6 @@ class Rufus::Scheduler::RepeatJob < Rufus::Scheduler::Job
|
|
93
93
|
def resume(opts={})
|
94
94
|
|
95
95
|
@resume_discard_past = opts[:discard_past]
|
96
|
-
#p [ :@resume_discard_past, @resume_discard_past ]
|
97
96
|
@paused_at = nil
|
98
97
|
end
|
99
98
|
|
@@ -145,17 +144,6 @@ class Rufus::Scheduler::RepeatJob < Rufus::Scheduler::Job
|
|
145
144
|
a << next_time_from(a.last)
|
146
145
|
a }
|
147
146
|
end
|
148
|
-
|
149
|
-
protected
|
150
|
-
|
151
|
-
def discard_past?
|
152
|
-
|
153
|
-
dp = @scheduler.discard_past
|
154
|
-
dp = @discard_past if @discard_past != nil
|
155
|
-
dp = @resume_discard_past if @resume_discard_past != nil
|
156
|
-
|
157
|
-
dp
|
158
|
-
end
|
159
147
|
end
|
160
148
|
|
161
149
|
#
|
@@ -180,7 +168,6 @@ class Rufus::Scheduler::EveryJob < Rufus::Scheduler::EvInJob
|
|
180
168
|
super(scheduler, duration, opts, block)
|
181
169
|
|
182
170
|
@frequency = Rufus::Scheduler.parse_in(@original)
|
183
|
-
@discard_past = opts[:discard_past]
|
184
171
|
|
185
172
|
fail ArgumentError.new(
|
186
173
|
"cannot schedule #{self.class} with a frequency " +
|
data/lib/rufus/scheduler.rb
CHANGED
@@ -9,7 +9,7 @@ module Rufus; end
|
|
9
9
|
|
10
10
|
class Rufus::Scheduler
|
11
11
|
|
12
|
-
VERSION = '3.
|
12
|
+
VERSION = '3.9.0'
|
13
13
|
|
14
14
|
EoTime = ::EtOrbi::EoTime
|
15
15
|
|
@@ -443,10 +443,14 @@ class Rufus::Scheduler
|
|
443
443
|
ms = {}; mutexes.each { |k, v| ms[k] = v.locked? }
|
444
444
|
|
445
445
|
stderr.puts("{ #{pre} rufus-scheduler intercepted an error:")
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
446
|
+
if job
|
447
|
+
stderr.puts(" #{pre} job:")
|
448
|
+
stderr.puts(" #{pre} #{job.class} #{job.original.inspect} #{job.opts.inspect}")
|
449
|
+
stderr.puts(" #{pre} #{job.source_location.inspect}")
|
450
|
+
# TODO: eventually use a Job#detail or something like that
|
451
|
+
else
|
452
|
+
stderr.puts(" #{pre} job: (error did not occur in a job)")
|
453
|
+
end
|
450
454
|
stderr.puts(" #{pre} error:")
|
451
455
|
stderr.puts(" #{pre} #{err.object_id}")
|
452
456
|
stderr.puts(" #{pre} #{err.class}")
|
@@ -530,7 +534,7 @@ class Rufus::Scheduler
|
|
530
534
|
|
531
535
|
unlock
|
532
536
|
|
533
|
-
@thread.join
|
537
|
+
@thread.join unless @thread == Thread.current
|
534
538
|
end
|
535
539
|
alias stop shutdown
|
536
540
|
|
@@ -630,12 +634,20 @@ class Rufus::Scheduler
|
|
630
634
|
Thread.new do
|
631
635
|
|
632
636
|
while @started_at do
|
637
|
+
begin
|
638
|
+
|
639
|
+
unschedule_jobs
|
640
|
+
trigger_jobs unless @paused_at
|
641
|
+
timeout_jobs
|
633
642
|
|
634
|
-
|
635
|
-
trigger_jobs unless @paused_at
|
636
|
-
timeout_jobs
|
643
|
+
sleep(@frequency)
|
637
644
|
|
638
|
-
|
645
|
+
rescue => err
|
646
|
+
#
|
647
|
+
# for `blocking: true` jobs mostly
|
648
|
+
#
|
649
|
+
on_error(nil, err)
|
650
|
+
end
|
639
651
|
end
|
640
652
|
|
641
653
|
rejoin
|
@@ -710,6 +722,14 @@ class Rufus::Scheduler
|
|
710
722
|
end
|
711
723
|
|
712
724
|
job = job_class.new(self, t, opts, block || callable)
|
725
|
+
|
726
|
+
if job.past? && (d = job.send(:discard_past?))
|
727
|
+
fail ArgumentError.new(
|
728
|
+
"scheduling in the past and discard_past set to :fail"
|
729
|
+
) if d == :fail
|
730
|
+
return
|
731
|
+
end
|
732
|
+
|
713
733
|
job.check_frequency
|
714
734
|
|
715
735
|
@jobs.push(job)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rufus-scheduler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Mettraux
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-06-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fugit
|
@@ -88,7 +88,7 @@ metadata:
|
|
88
88
|
bug_tracker_uri: https://github.com/jmettraux/rufus-scheduler/issues
|
89
89
|
homepage_uri: https://github.com/jmettraux/rufus-scheduler
|
90
90
|
source_code_uri: https://github.com/jmettraux/rufus-scheduler
|
91
|
-
post_install_message:
|
91
|
+
post_install_message:
|
92
92
|
rdoc_options: []
|
93
93
|
require_paths:
|
94
94
|
- lib
|
@@ -103,8 +103,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
103
103
|
- !ruby/object:Gem::Version
|
104
104
|
version: '0'
|
105
105
|
requirements: []
|
106
|
-
rubygems_version: 3.
|
107
|
-
signing_key:
|
106
|
+
rubygems_version: 3.2.33
|
107
|
+
signing_key:
|
108
108
|
specification_version: 4
|
109
109
|
summary: job scheduler for Ruby (at, cron, in and every jobs)
|
110
110
|
test_files: []
|