rufus-scheduler 3.0.8 → 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 +13 -0
- data/CREDITS.txt +5 -0
- data/LICENSE.txt +1 -1
- data/README.md +73 -13
- data/lib/rufus/scheduler/cronline.rb +78 -74
- data/lib/rufus/scheduler/job_array.rb +2 -1
- data/lib/rufus/scheduler/jobs.rb +30 -28
- data/lib/rufus/scheduler/locks.rb +95 -0
- data/lib/rufus/scheduler/util.rb +2 -25
- data/lib/rufus/scheduler/zones.rb +174 -0
- data/lib/rufus/scheduler/zotime.rb +154 -0
- data/lib/rufus/scheduler.rb +61 -61
- data/rufus-scheduler.gemspec +2 -27
- data/spec/basics_spec.rb +16 -11
- data/spec/cronline_spec.rb +152 -103
- data/spec/job_cron_spec.rb +22 -0
- data/spec/job_every_spec.rb +14 -0
- data/spec/job_repeat_spec.rb +1 -0
- data/spec/lock_flock_spec.rb +47 -0
- data/spec/lock_spec.rb +59 -0
- data/spec/parse_spec.rb +29 -27
- data/spec/schedule_at_spec.rb +1 -1
- data/spec/scheduler_spec.rb +5 -2
- data/spec/spec_helper.rb +1 -1
- data/spec/zotime_spec.rb +396 -0
- metadata +20 -20
- /data/spec/{custom_locks_spec.rb → lock_custom_spec.rb} +0 -0
- /data/spec/{lockfile_spec.rb → lock_lockfile_spec.rb} +0 -0
data/CHANGELOG.txt
CHANGED
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
= rufus-scheduler CHANGELOG.txt
|
|
3
3
|
|
|
4
4
|
|
|
5
|
+
== rufus-scheduler - 3.1.0 released 2015/04/18
|
|
6
|
+
|
|
7
|
+
- go without tzinfo (and its dependencies)
|
|
8
|
+
- include @ketan's #next_time improvements
|
|
9
|
+
- remove 2.x warning message on install
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
== rufus-scheduler - 3.0.9 released 2014/08/30
|
|
13
|
+
|
|
14
|
+
- fix TZ with underscores, thanks https://github.com/gnilrets
|
|
15
|
+
- integrate https://github.com/ecin Lock mecha
|
|
16
|
+
|
|
17
|
+
|
|
5
18
|
== rufus-scheduler - 3.0.8 released 2014/06/09
|
|
6
19
|
|
|
7
20
|
- handle TZInfo errors on DST transitions, thanks https://github.com/junhanamaki
|
data/CREDITS.txt
CHANGED
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
== Contributors
|
|
6
6
|
|
|
7
|
+
- Ketan Padegaonkar (https://github.com/ketan) .brute_frequency improvement
|
|
8
|
+
- Gabriel Gilder (https://github.com/ggilder) LA DST specs
|
|
9
|
+
- Sterling Paramore (https://github.com/gnilrets) underscore TZ fix
|
|
10
|
+
- ecin (https://github.com/ecin) new lock mecha
|
|
7
11
|
- Adam Jonas (https://github.com/adamjonas) migrate specs to "expect"
|
|
8
12
|
- Yassen Bantchev (https://github.com/yassenb) CronLine#previous_time rewrite
|
|
9
13
|
- Eric Lindvall (https://github.com/eric) Zookeeper locked example
|
|
@@ -31,6 +35,7 @@
|
|
|
31
35
|
|
|
32
36
|
== Feedback
|
|
33
37
|
|
|
38
|
+
- Michael Guymon - https://github.com/mguymon - #next_time vs :first_at
|
|
34
39
|
- junhanamaki - https://github.com/junhanamaki - #next_time and dst ambiguities
|
|
35
40
|
- kreynolds (tossrock) - inspiration for #occurrences
|
|
36
41
|
- Matteo - https://github.com/m4ce - dst and cron issue
|
data/LICENSE.txt
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
Copyright (c) 2005-
|
|
2
|
+
Copyright (c) 2005-2015, 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/README.md
CHANGED
|
@@ -61,6 +61,7 @@ It does not persist your schedules. When the process is gone and the scheduler i
|
|
|
61
61
|
|
|
62
62
|
* [whenever](https://github.com/javan/whenever) - let cron call back your Ruby code, trusted and reliable cron drives your schedule
|
|
63
63
|
* [clockwork](https://github.com/tomykaira/clockwork) - rufus-scheduler inspired gem
|
|
64
|
+
* [crono](https://github.com/plashchynski/crono) - an in-Rails cron scheduler
|
|
64
65
|
|
|
65
66
|
(please note: rufus-scheduler is not a cron replacement)
|
|
66
67
|
|
|
@@ -72,6 +73,11 @@ It's a complete rewrite of rufus-scheduler.
|
|
|
72
73
|
There is no EventMachine-based scheduler anymore.
|
|
73
74
|
|
|
74
75
|
|
|
76
|
+
## I don't know what this Ruby thing is, where are my Rails?
|
|
77
|
+
|
|
78
|
+
Sir, I'll drive you right to the [tracks](#so-rails).
|
|
79
|
+
|
|
80
|
+
|
|
75
81
|
## Notables changes:
|
|
76
82
|
|
|
77
83
|
* As said, no more EventMachine-based scheduler
|
|
@@ -89,6 +95,8 @@ There is no EventMachine-based scheduler anymore.
|
|
|
89
95
|
|
|
90
96
|
So you need help. People can help you, but first help them help you, and don't waste their time. Provide a complete description of the issue. If it works on A but not on B and others have to ask you: "so what is different between A and B" you are wasting everyone's time.
|
|
91
97
|
|
|
98
|
+
"hello" and "thanks" are not swear words.
|
|
99
|
+
|
|
92
100
|
Go read [how to report bugs effectively](http://www.chiark.greenend.org.uk/~sgtatham/bugs.html), twice.
|
|
93
101
|
|
|
94
102
|
Update: [help_help.md](https://gist.github.com/jmettraux/310fed75f568fd731814) might help help you.
|
|
@@ -1097,6 +1105,57 @@ This is useful in environments where the Ruby process holding the scheduler gets
|
|
|
1097
1105
|
|
|
1098
1106
|
If the lockfile mechanism here is not sufficient, you can plug your custom mechanism. It's explained in [advanced lock schemes](#advanced-lock-schemes) below.
|
|
1099
1107
|
|
|
1108
|
+
### :scheduler_lock
|
|
1109
|
+
|
|
1110
|
+
(since rufus-scheduler 3.0.9)
|
|
1111
|
+
|
|
1112
|
+
The scheduler lock is an object that responds to `#lock` and `#unlock`. The scheduler calls `#lock` when starting up. If the answer is `false`, the scheduler stops its initialization work and won't schedule anything.
|
|
1113
|
+
|
|
1114
|
+
Here is a sample of a scheduler lock that only lets the scheduler on host "coffee.example.com" start:
|
|
1115
|
+
```ruby
|
|
1116
|
+
class HostLock
|
|
1117
|
+
def initialize(lock_name)
|
|
1118
|
+
@lock_name = lock_name
|
|
1119
|
+
end
|
|
1120
|
+
def lock
|
|
1121
|
+
@lock_name == `hostname -f`.strip
|
|
1122
|
+
end
|
|
1123
|
+
def unlock
|
|
1124
|
+
true
|
|
1125
|
+
end
|
|
1126
|
+
end
|
|
1127
|
+
|
|
1128
|
+
scheduler =
|
|
1129
|
+
Rufus::Scheduler.new(:scheduler_lock => HostLock.new('coffee.example.com'))
|
|
1130
|
+
```
|
|
1131
|
+
|
|
1132
|
+
By default, the scheduler_lock is an instance of `Rufus::Scheduler::NullLock`, with a `#lock` that returns true.
|
|
1133
|
+
|
|
1134
|
+
### :trigger_lock
|
|
1135
|
+
|
|
1136
|
+
(since rufus-scheduler 3.0.9)
|
|
1137
|
+
|
|
1138
|
+
The trigger lock in an object that responds to `#lock`. The scheduler calls that method on the job lock right before triggering any job. If the answer is false, the trigger doesn't happen, the job is not done (at least not in this scheduler).
|
|
1139
|
+
|
|
1140
|
+
Here is a (stupid) PingLock example, it'll only trigger if an "other host" is not responding to ping. Do not use that in production, you don't want to fork a ping process for each trigger attempt...
|
|
1141
|
+
```ruby
|
|
1142
|
+
class PingLock
|
|
1143
|
+
def initialize(other_host)
|
|
1144
|
+
@other_host = other_host
|
|
1145
|
+
end
|
|
1146
|
+
def lock
|
|
1147
|
+
! system("ping -c 1 #{@other_host}")
|
|
1148
|
+
end
|
|
1149
|
+
end
|
|
1150
|
+
|
|
1151
|
+
scheduler =
|
|
1152
|
+
Rufus::Scheduler.new(:trigger_lock => PingLock.new('main.example.com'))
|
|
1153
|
+
```
|
|
1154
|
+
|
|
1155
|
+
By default, the trigger_lock is an instance of `Rufus::Scheduler::NullLock`, with a `#lock` that always returns true.
|
|
1156
|
+
|
|
1157
|
+
As explained in [advanced lock schemes](#advanced-lock-schemes), another way to tune that behaviour is by overriding the scheduler's `#confirm_lock` method. (You could also do that with an `#on_pre_trigger` callback).
|
|
1158
|
+
|
|
1100
1159
|
### :max_work_threads
|
|
1101
1160
|
|
|
1102
1161
|
In rufus-scheduler 2.x, by default, each job triggering received its own, brand new, thread of execution. In rufus-scheduler 3.x, execution happens in a pooled work thread. The max work thread count (the pool size) defaults to 28.
|
|
@@ -1183,6 +1242,20 @@ to make sure that the lock is still valid.
|
|
|
1183
1242
|
|
|
1184
1243
|
The #confirm_lock method is called right before a job triggers (if it is provided). The more generic callback #on_pre_trigger is called right after #confirm_lock.
|
|
1185
1244
|
|
|
1245
|
+
### :scheduler_lock and :trigger_lock
|
|
1246
|
+
|
|
1247
|
+
(introduced in rufus-scheduler 3.0.9).
|
|
1248
|
+
|
|
1249
|
+
Another way of prodiving `#lock`, `#unlock` and `#confirm_lock` to a rufus-scheduler is by using the `:scheduler_lock` and `:trigger_lock` options.
|
|
1250
|
+
|
|
1251
|
+
See [:trigger_lock](#trigger_lock) and [:scheduler_lock](#scheduler_lock).
|
|
1252
|
+
|
|
1253
|
+
The scheduler lock may be used to prevent a scheduler from starting, while a trigger lock prevents individual jobs from triggering (the scheduler goes on scheduling).
|
|
1254
|
+
|
|
1255
|
+
One has to be careful with what goes in `#confirm_lock` or in a trigger lock, as it gets called before each trigger.
|
|
1256
|
+
|
|
1257
|
+
Warning: you may think you're heading towards "high availability" by using a trigger lock and having lots of schedulers at hand. It may be so if you limit yourself to scheduling the same set of jobs at scheduler startup. But if you add schedules at runtime, they stay local to their scheduler. There is no magic that propagates the jobs to all the schedulers in your pack.
|
|
1258
|
+
|
|
1186
1259
|
|
|
1187
1260
|
## parsing cronlines and time strings
|
|
1188
1261
|
|
|
@@ -1303,19 +1376,6 @@ Rufus::Scheduler.parse("2013-12-12 14:00 Pacific/Saipan")
|
|
|
1303
1376
|
# => 2013-12-12 04:00:00 UTC
|
|
1304
1377
|
```
|
|
1305
1378
|
|
|
1306
|
-
Behind the scenes, rufus-scheduler uses [tzinfo](http://tzinfo.github.io/) to deal with timezones.
|
|
1307
|
-
|
|
1308
|
-
Here is a [list of timezones](misc/tz_all.txt) known to my Debian GNU/Linux 7. It was generated with this script:
|
|
1309
|
-
|
|
1310
|
-
```ruby
|
|
1311
|
-
require 'tzinfo'
|
|
1312
|
-
TZInfo::Timezone.all.each { |tz| puts tz.name }
|
|
1313
|
-
```
|
|
1314
|
-
|
|
1315
|
-
Unknown timezones, typos, will be rejected by tzinfo thus rufus-scheduler.
|
|
1316
|
-
|
|
1317
|
-
On its own tzinfo derives the timezones from the system's information. On some system it needs some help, one can install the 'tzinfo-data' gem to provide the missing information.
|
|
1318
|
-
|
|
1319
1379
|
|
|
1320
1380
|
## so Rails?
|
|
1321
1381
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#--
|
|
2
|
-
# Copyright (c) 2006-
|
|
2
|
+
# Copyright (c) 2006-2015, 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
|
|
@@ -22,6 +22,8 @@
|
|
|
22
22
|
# Made in Japan.
|
|
23
23
|
#++
|
|
24
24
|
|
|
25
|
+
require 'set'
|
|
26
|
+
|
|
25
27
|
|
|
26
28
|
class Rufus::Scheduler
|
|
27
29
|
|
|
@@ -54,8 +56,7 @@ class Rufus::Scheduler
|
|
|
54
56
|
|
|
55
57
|
items = line.split
|
|
56
58
|
|
|
57
|
-
@timezone =
|
|
58
|
-
items.pop if @timezone
|
|
59
|
+
@timezone = items.pop if ZoTime.is_timezone?(items.last)
|
|
59
60
|
|
|
60
61
|
raise ArgumentError.new(
|
|
61
62
|
"not a valid cronline : '#{line}'"
|
|
@@ -82,9 +83,7 @@ class Rufus::Scheduler
|
|
|
82
83
|
#
|
|
83
84
|
def matches?(time)
|
|
84
85
|
|
|
85
|
-
time =
|
|
86
|
-
|
|
87
|
-
time = @timezone.utc_to_local(time.getutc) if @timezone
|
|
86
|
+
time = ZoTime.new(time.to_f, @timezone || ENV['TZ']).time
|
|
88
87
|
|
|
89
88
|
return false unless sub_match?(time, :sec, @seconds)
|
|
90
89
|
return false unless sub_match?(time, :min, @minutes)
|
|
@@ -122,37 +121,34 @@ class Rufus::Scheduler
|
|
|
122
121
|
#
|
|
123
122
|
def next_time(from=Time.now)
|
|
124
123
|
|
|
125
|
-
time =
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
# start at the next second
|
|
129
|
-
time = time + 1
|
|
124
|
+
time = nil
|
|
125
|
+
zotime = ZoTime.new(from.to_i + 1, @timezone || ENV['TZ'])
|
|
130
126
|
|
|
131
127
|
loop do
|
|
128
|
+
|
|
129
|
+
time = zotime.time
|
|
130
|
+
|
|
132
131
|
unless date_match?(time)
|
|
133
|
-
|
|
134
|
-
time += (24 - time.hour) * 3600 - time.min * 60 - time.sec
|
|
135
|
-
time -= 3600 if time.isdst != dst # not necessary for winter, but...
|
|
132
|
+
zotime.add((24 - time.hour) * 3600 - time.min * 60 - time.sec)
|
|
136
133
|
next
|
|
137
134
|
end
|
|
138
135
|
unless sub_match?(time, :hour, @hours)
|
|
139
|
-
|
|
136
|
+
zotime.add((60 - time.min) * 60 - time.sec)
|
|
137
|
+
next
|
|
140
138
|
end
|
|
141
139
|
unless sub_match?(time, :min, @minutes)
|
|
142
|
-
|
|
140
|
+
zotime.add(60 - time.sec)
|
|
141
|
+
next
|
|
143
142
|
end
|
|
144
143
|
unless sub_match?(time, :sec, @seconds)
|
|
145
|
-
time
|
|
144
|
+
zotime.add(next_second(time))
|
|
145
|
+
next
|
|
146
146
|
end
|
|
147
147
|
|
|
148
148
|
break
|
|
149
149
|
end
|
|
150
150
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
rescue TZInfo::PeriodNotFound
|
|
154
|
-
|
|
155
|
-
next_time(from + 3600)
|
|
151
|
+
time
|
|
156
152
|
end
|
|
157
153
|
|
|
158
154
|
# Returns the previous time the cronline matched. It's like next_time, but
|
|
@@ -160,35 +156,48 @@ class Rufus::Scheduler
|
|
|
160
156
|
#
|
|
161
157
|
def previous_time(from=Time.now)
|
|
162
158
|
|
|
163
|
-
time =
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
# start at the previous second
|
|
167
|
-
time = time - 1
|
|
159
|
+
time = nil
|
|
160
|
+
zotime = ZoTime.new(from.to_i - 1, @timezone || ENV['TZ'])
|
|
168
161
|
|
|
169
162
|
loop do
|
|
163
|
+
|
|
164
|
+
time = zotime.time
|
|
165
|
+
|
|
170
166
|
unless date_match?(time)
|
|
171
|
-
time
|
|
167
|
+
zotime.substract(time.hour * 3600 + time.min * 60 + time.sec + 1)
|
|
168
|
+
next
|
|
172
169
|
end
|
|
173
170
|
unless sub_match?(time, :hour, @hours)
|
|
174
|
-
time
|
|
171
|
+
zotime.substract(time.min * 60 + time.sec + 1)
|
|
172
|
+
next
|
|
175
173
|
end
|
|
176
174
|
unless sub_match?(time, :min, @minutes)
|
|
177
|
-
time
|
|
175
|
+
zotime.substract(time.sec + 1)
|
|
176
|
+
next
|
|
178
177
|
end
|
|
179
178
|
unless sub_match?(time, :sec, @seconds)
|
|
180
|
-
time
|
|
179
|
+
zotime.substract(prev_second(time))
|
|
180
|
+
next
|
|
181
181
|
end
|
|
182
182
|
|
|
183
183
|
break
|
|
184
184
|
end
|
|
185
185
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
rescue TZInfo::PeriodNotFound
|
|
186
|
+
time
|
|
187
|
+
end
|
|
189
188
|
|
|
190
|
-
|
|
189
|
+
if RUBY_VERSION >= '1.9'
|
|
190
|
+
def toa(item)
|
|
191
|
+
item == nil ? nil : item.to_a
|
|
192
|
+
end
|
|
193
|
+
else
|
|
194
|
+
def toi(item); item.is_a?(String) ? item.hash.abs : item.to_i; end
|
|
195
|
+
protected :toi
|
|
196
|
+
def toa(item)
|
|
197
|
+
item.is_a?(Set) ? item.to_a.sort_by { |e| toi(e) } : item
|
|
198
|
+
end
|
|
191
199
|
end
|
|
200
|
+
protected :toa
|
|
192
201
|
|
|
193
202
|
# Returns an array of 6 arrays (seconds, minutes, hours, days,
|
|
194
203
|
# months, weekdays).
|
|
@@ -197,14 +206,14 @@ class Rufus::Scheduler
|
|
|
197
206
|
def to_array
|
|
198
207
|
|
|
199
208
|
[
|
|
200
|
-
@seconds,
|
|
201
|
-
@minutes,
|
|
202
|
-
@hours,
|
|
203
|
-
@days,
|
|
204
|
-
@months,
|
|
205
|
-
@weekdays,
|
|
206
|
-
@monthdays,
|
|
207
|
-
@timezone
|
|
209
|
+
toa(@seconds),
|
|
210
|
+
toa(@minutes),
|
|
211
|
+
toa(@hours),
|
|
212
|
+
toa(@days),
|
|
213
|
+
toa(@months),
|
|
214
|
+
toa(@weekdays),
|
|
215
|
+
toa(@monthdays),
|
|
216
|
+
@timezone
|
|
208
217
|
]
|
|
209
218
|
end
|
|
210
219
|
|
|
@@ -212,7 +221,7 @@ class Rufus::Scheduler
|
|
|
212
221
|
# cron line.
|
|
213
222
|
#
|
|
214
223
|
# #brute_frequency, on the other hand, will compute the frequency by
|
|
215
|
-
# examining a whole, that can take more than seconds for a seconds
|
|
224
|
+
# examining a whole year, that can take more than seconds for a seconds
|
|
216
225
|
# level cron...
|
|
217
226
|
#
|
|
218
227
|
def frequency
|
|
@@ -220,9 +229,10 @@ class Rufus::Scheduler
|
|
|
220
229
|
return brute_frequency unless @seconds && @seconds.length > 1
|
|
221
230
|
|
|
222
231
|
delta = 60
|
|
223
|
-
|
|
232
|
+
secs = toa(@seconds)
|
|
233
|
+
prev = secs[0]
|
|
224
234
|
|
|
225
|
-
|
|
235
|
+
secs[1..-1].each do |sec|
|
|
226
236
|
d = sec - prev
|
|
227
237
|
delta = d if d < delta
|
|
228
238
|
end
|
|
@@ -270,7 +280,7 @@ class Rufus::Scheduler
|
|
|
270
280
|
delta = d if d < delta
|
|
271
281
|
|
|
272
282
|
break if @months == nil && t1.month == 2
|
|
273
|
-
break if t1.year
|
|
283
|
+
break if t1.year >= 2001
|
|
274
284
|
|
|
275
285
|
t0 = t1
|
|
276
286
|
end
|
|
@@ -280,6 +290,26 @@ class Rufus::Scheduler
|
|
|
280
290
|
|
|
281
291
|
protected
|
|
282
292
|
|
|
293
|
+
def next_second(time)
|
|
294
|
+
|
|
295
|
+
secs = @seconds.sort
|
|
296
|
+
|
|
297
|
+
return secs.last + 60 - time.sec if time.sec > secs.last
|
|
298
|
+
|
|
299
|
+
secs.shift while secs.first < time.sec
|
|
300
|
+
|
|
301
|
+
secs.first - time.sec
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
def prev_second(time)
|
|
305
|
+
|
|
306
|
+
secs = @seconds.sort
|
|
307
|
+
|
|
308
|
+
secs.pop while time.sec < secs.last
|
|
309
|
+
|
|
310
|
+
time.sec - secs.last
|
|
311
|
+
end
|
|
312
|
+
|
|
283
313
|
WEEKDAYS = %w[ sun mon tue wed thu fri sat ]
|
|
284
314
|
DAY_S = 24 * 3600
|
|
285
315
|
WEEK_S = 7 * DAY_S
|
|
@@ -336,7 +366,7 @@ class Rufus::Scheduler
|
|
|
336
366
|
"found duplicates in #{item.inspect}"
|
|
337
367
|
) if r.uniq.size < r.size
|
|
338
368
|
|
|
339
|
-
r
|
|
369
|
+
Set.new(r)
|
|
340
370
|
end
|
|
341
371
|
|
|
342
372
|
RANGE_REGEX = /^(\*|\d{1,2})(?:-(\d{1,2}))?(?:\/(\d{1,2}))?$/
|
|
@@ -435,32 +465,6 @@ class Rufus::Scheduler
|
|
|
435
465
|
|
|
436
466
|
[ "#{WEEKDAYS[date.wday]}##{pos}", "#{WEEKDAYS[date.wday]}##{neg}" ]
|
|
437
467
|
end
|
|
438
|
-
|
|
439
|
-
def local_time(time)
|
|
440
|
-
|
|
441
|
-
@timezone ? @timezone.utc_to_local(time.getutc) : time
|
|
442
|
-
end
|
|
443
|
-
|
|
444
|
-
def global_time(time, from_in_utc)
|
|
445
|
-
|
|
446
|
-
if @timezone
|
|
447
|
-
time =
|
|
448
|
-
begin
|
|
449
|
-
@timezone.local_to_utc(time)
|
|
450
|
-
rescue TZInfo::AmbiguousTime
|
|
451
|
-
@timezone.local_to_utc(time, time.isdst)
|
|
452
|
-
end
|
|
453
|
-
time = time.getlocal unless from_in_utc
|
|
454
|
-
end
|
|
455
|
-
|
|
456
|
-
time
|
|
457
|
-
end
|
|
458
|
-
|
|
459
|
-
def round_to_seconds(time)
|
|
460
|
-
|
|
461
|
-
# Ruby 1.8 doesn't have #round
|
|
462
|
-
time.respond_to?(:round) ? time.round : time - time.usec * 1e-6
|
|
463
|
-
end
|
|
464
468
|
end
|
|
465
469
|
end
|
|
466
470
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#--
|
|
2
|
-
# Copyright (c) 2006-
|
|
2
|
+
# Copyright (c) 2006-2015, 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
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
# Made in Japan.
|
|
23
23
|
#++
|
|
24
24
|
|
|
25
|
+
|
|
25
26
|
module Rufus
|
|
26
27
|
|
|
27
28
|
class Scheduler
|
data/lib/rufus/scheduler/jobs.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#--
|
|
2
|
-
# Copyright (c) 2006-
|
|
2
|
+
# Copyright (c) 2006-2015, 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
|
|
@@ -117,15 +117,16 @@ module Rufus
|
|
|
117
117
|
|
|
118
118
|
def trigger(time)
|
|
119
119
|
|
|
120
|
-
set_next_time(
|
|
120
|
+
set_next_time(time)
|
|
121
121
|
|
|
122
|
-
return if
|
|
123
|
-
|
|
124
|
-
|
|
122
|
+
return if (
|
|
123
|
+
opts[:overlap] == false &&
|
|
124
|
+
running?
|
|
125
|
+
)
|
|
126
|
+
return if (
|
|
125
127
|
callback(:confirm_lock, time) &&
|
|
126
128
|
callback(:on_pre_trigger, time)
|
|
127
|
-
|
|
128
|
-
return if r == false
|
|
129
|
+
) == false
|
|
129
130
|
|
|
130
131
|
@count += 1
|
|
131
132
|
|
|
@@ -272,7 +273,7 @@ module Rufus
|
|
|
272
273
|
|
|
273
274
|
def post_trigger(time)
|
|
274
275
|
|
|
275
|
-
set_next_time(
|
|
276
|
+
set_next_time(time, true)
|
|
276
277
|
|
|
277
278
|
callback(:on_post_trigger, time)
|
|
278
279
|
end
|
|
@@ -339,7 +340,7 @@ module Rufus
|
|
|
339
340
|
|
|
340
341
|
def occurrences(time0, time1)
|
|
341
342
|
|
|
342
|
-
time >= time0 && time <= time1 ? [ time ] : []
|
|
343
|
+
(time >= time0 && time <= time1) ? [ time ] : []
|
|
343
344
|
end
|
|
344
345
|
|
|
345
346
|
protected
|
|
@@ -356,7 +357,7 @@ module Rufus
|
|
|
356
357
|
|
|
357
358
|
# There is no next_time for one time jobs, hence the false.
|
|
358
359
|
#
|
|
359
|
-
def set_next_time(
|
|
360
|
+
def set_next_time(trigger_time, is_post=false)
|
|
360
361
|
|
|
361
362
|
@next_time = is_post ? nil : false
|
|
362
363
|
end
|
|
@@ -408,15 +409,17 @@ module Rufus
|
|
|
408
409
|
self.first_at =
|
|
409
410
|
opts[:first] || opts[:first_time] ||
|
|
410
411
|
opts[:first_at] || opts[:first_in] ||
|
|
411
|
-
|
|
412
|
+
nil
|
|
412
413
|
self.last_at =
|
|
413
414
|
opts[:last] || opts[:last_at] || opts[:last_in]
|
|
414
415
|
end
|
|
415
416
|
|
|
416
417
|
def first_at=(first)
|
|
417
418
|
|
|
419
|
+
return @first_at = nil if first == nil
|
|
420
|
+
|
|
418
421
|
n = Time.now
|
|
419
|
-
first = n + 0.
|
|
422
|
+
first = n + 0.003 if first == :now || first == :immediately
|
|
420
423
|
|
|
421
424
|
@first_at = Rufus::Scheduler.parse_to_time(first)
|
|
422
425
|
|
|
@@ -439,9 +442,6 @@ module Rufus
|
|
|
439
442
|
def trigger(time)
|
|
440
443
|
|
|
441
444
|
return if @paused_at
|
|
442
|
-
return if time < @first_at
|
|
443
|
-
#
|
|
444
|
-
# TODO: remove me when @first_at gets reworked
|
|
445
445
|
|
|
446
446
|
return (@next_time = nil) if @times && @times < 1
|
|
447
447
|
return (@next_time = nil) if @last_at && time >= @last_at
|
|
@@ -527,20 +527,18 @@ module Rufus
|
|
|
527
527
|
"of #{@frequency.inspect} (#{@original.inspect})"
|
|
528
528
|
) if @frequency <= 0
|
|
529
529
|
|
|
530
|
-
set_next_time(
|
|
530
|
+
set_next_time(nil)
|
|
531
531
|
end
|
|
532
532
|
|
|
533
533
|
protected
|
|
534
534
|
|
|
535
|
-
def set_next_time(
|
|
535
|
+
def set_next_time(trigger_time, is_post=false)
|
|
536
536
|
|
|
537
537
|
return if is_post
|
|
538
538
|
|
|
539
539
|
@next_time =
|
|
540
|
-
if
|
|
541
|
-
trigger_time + @frequency
|
|
542
|
-
elsif @first_at < Time.now
|
|
543
|
-
Time.now + @frequency
|
|
540
|
+
if @first_at == nil || @first_at < Time.now
|
|
541
|
+
(trigger_time || Time.now) + @frequency
|
|
544
542
|
else
|
|
545
543
|
@first_at
|
|
546
544
|
end
|
|
@@ -567,18 +565,18 @@ module Rufus
|
|
|
567
565
|
"of #{@interval.inspect} (#{@original.inspect})"
|
|
568
566
|
) if @interval <= 0
|
|
569
567
|
|
|
570
|
-
set_next_time(
|
|
568
|
+
set_next_time(nil)
|
|
571
569
|
end
|
|
572
570
|
|
|
573
571
|
protected
|
|
574
572
|
|
|
575
|
-
def set_next_time(
|
|
573
|
+
def set_next_time(trigger_time, is_post=false)
|
|
576
574
|
|
|
577
575
|
@next_time =
|
|
578
576
|
if is_post
|
|
579
577
|
Time.now + @interval
|
|
580
578
|
elsif trigger_time.nil?
|
|
581
|
-
if @first_at < Time.now
|
|
579
|
+
if @first_at == nil || @first_at < Time.now
|
|
582
580
|
Time.now + @interval
|
|
583
581
|
else
|
|
584
582
|
@first_at
|
|
@@ -601,7 +599,7 @@ module Rufus
|
|
|
601
599
|
super(scheduler, cronline, opts, block)
|
|
602
600
|
|
|
603
601
|
@cron_line = opts[:_t] || CronLine.new(cronline)
|
|
604
|
-
|
|
602
|
+
set_next_time(nil)
|
|
605
603
|
end
|
|
606
604
|
|
|
607
605
|
def frequency
|
|
@@ -616,14 +614,18 @@ module Rufus
|
|
|
616
614
|
|
|
617
615
|
protected
|
|
618
616
|
|
|
619
|
-
def set_next_time(
|
|
617
|
+
def set_next_time(trigger_time, is_post=false)
|
|
620
618
|
|
|
621
|
-
@next_time =
|
|
619
|
+
@next_time = next_time_from(trigger_time || Time.now)
|
|
622
620
|
end
|
|
623
621
|
|
|
624
622
|
def next_time_from(time)
|
|
625
623
|
|
|
626
|
-
@
|
|
624
|
+
if @first_at == nil || @first_at < time
|
|
625
|
+
@cron_line.next_time(time)
|
|
626
|
+
else
|
|
627
|
+
@first_at
|
|
628
|
+
end
|
|
627
629
|
end
|
|
628
630
|
end
|
|
629
631
|
end
|