fugit 1.1.8 → 1.1.9
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of fugit might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/CREDITS.md +2 -1
- data/README.md +2 -1
- data/lib/fugit.rb +1 -1
- data/lib/fugit/cron.rb +61 -54
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 35836e95c82a113fe2e5222a02522ab2bf36f1b0
|
4
|
+
data.tar.gz: 0fb6db1cb77893af937354da715b2eb8b14403f5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7de61477e96c9612542641787346fb154394d8388eccccaeb1be257cb57410abe4e23d1377148539d92852674df3c58d0a44c9cc4816c50cd157515f185d59da
|
7
|
+
data.tar.gz: c1f23c4a8395ddc29a85415300608fbc45d5900cbb42c502fd51f02f7f8c5f6fe945fe9b010349e9bde6fc1df6f3ec105a977c8705722820be41c65b47656ff7
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,14 @@
|
|
2
2
|
# CHANGELOG.md
|
3
3
|
|
4
4
|
|
5
|
+
## fugit 1.1.9 released 2019-03-26
|
6
|
+
|
7
|
+
* Fix cron `"0 9 29 feb *"` endless loop, gh-18
|
8
|
+
* Fix cron endless loop when #previous_time(t) and t matches, gh-15
|
9
|
+
* Simplify Cron #next_time / #previous_time breaker system, gh-15
|
10
|
+
Thanks @godfat and @conet
|
11
|
+
|
12
|
+
|
5
13
|
## fugit 1.1.8 released 2019-01-17
|
6
14
|
|
7
15
|
* Ensure Cron#next_time happens in cron's time zone, gh-12
|
data/CREDITS.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
|
2
2
|
# fugit credits
|
3
3
|
|
4
|
+
* Cristian Oneț https://githbu.com/conet #previous_time vs 1/-1 endless loop #15
|
4
5
|
* Wenhui Wang https://github.com/w11th #next_time vs Chronic+ActiveSupport #11
|
5
6
|
* Lin-Jen Shin https://github.com/godfat #next_time untamed loop, #13
|
6
7
|
* Nils Mueller https://github.com/Tolsto missing Olson timezone names, #9
|
@@ -17,5 +18,5 @@
|
|
17
18
|
As fugit originates in rufus-scheduler, many thanks to all the
|
18
19
|
rufus-scheduler contributors and people who gave feedback.
|
19
20
|
|
20
|
-
https://github.com/jmettraux/rufus-scheduler/blob/master/CREDITS.
|
21
|
+
https://github.com/jmettraux/rufus-scheduler/blob/master/CREDITS.md
|
21
22
|
|
data/README.md
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
|
4
4
|
[![Build Status](https://secure.travis-ci.org/floraison/fugit.svg)](http://travis-ci.org/floraison/fugit)
|
5
5
|
[![Gem Version](https://badge.fury.io/rb/fugit.svg)](http://badge.fury.io/rb/fugit)
|
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)
|
6
7
|
|
7
8
|
Time tools for [flor](https://github.com/floraison/flor) and the floraison group.
|
8
9
|
|
@@ -34,9 +35,9 @@ The intersection of those two projects is where fugit is born:
|
|
34
35
|
* [sideqik-cron](https://github.com/ondrejbartas/sidekiq-cron) - recent versions of Sideqik-Cron use fugit to parse cron strings
|
35
36
|
* [rufus-scheduler](https://github.com/jmettraux/rufus-scheduler) -
|
36
37
|
* [flor](https://github.com/floraison/flor) - used in the [cron](https://github.com/floraison/flor/blob/master/doc/procedures/cron.md) procedure
|
38
|
+
* [que-scheduler](https://github.com/hlascelles/que-scheduler) - a reliable job scheduler for [que](https://github.com/chanks/que)
|
37
39
|
* ...
|
38
40
|
|
39
|
-
|
40
41
|
## `Fugit.parse(s)`
|
41
42
|
|
42
43
|
The simplest way to use fugit is via `Fugit.parse(s)`.
|
data/lib/fugit.rb
CHANGED
data/lib/fugit/cron.rb
CHANGED
@@ -64,7 +64,8 @@ module Fugit
|
|
64
64
|
|
65
65
|
class TimeCursor
|
66
66
|
|
67
|
-
def initialize(t)
|
67
|
+
def initialize(cron, t)
|
68
|
+
@cron = cron
|
68
69
|
@t = t.is_a?(TimeCursor) ? t.time : t
|
69
70
|
@t.seconds = @t.seconds.to_i
|
70
71
|
end
|
@@ -88,28 +89,49 @@ module Fugit
|
|
88
89
|
@t = ::EtOrbi.make(y, m, @t.zone)
|
89
90
|
self
|
90
91
|
end
|
91
|
-
def inc_day; inc((24 - @t.hour) * 3600 - @t.min * 60 - @t.sec); end
|
92
|
-
def inc_hour; inc((60 - @t.min) * 60 - @t.sec); end
|
93
|
-
def inc_min; inc(60 - @t.sec); end
|
94
92
|
|
95
|
-
def
|
96
|
-
|
93
|
+
def inc_day
|
94
|
+
inc((24 - @t.hour) * 3600 - @t.min * 60 - @t.sec)
|
95
|
+
end
|
96
|
+
def inc_hour
|
97
|
+
inc((60 - @t.min) * 60 - @t.sec)
|
98
|
+
end
|
99
|
+
def inc_min
|
100
|
+
inc(60 - @t.sec)
|
101
|
+
end
|
102
|
+
|
103
|
+
def inc_sec
|
104
|
+
if sec = @cron.seconds.find { |s| s > @t.sec }
|
97
105
|
inc(sec - @t.sec)
|
98
106
|
else
|
99
|
-
inc(60 - @t.sec + seconds.first)
|
107
|
+
inc(60 - @t.sec + @cron.seconds.first)
|
100
108
|
end
|
101
109
|
end
|
102
110
|
|
103
111
|
def dec_month
|
104
|
-
|
112
|
+
|
113
|
+
#dec(@t.day * 24 * 3600 + @t.hour * 3600 + @t.min * 60 + @t.sec + 1)
|
114
|
+
#
|
115
|
+
# gh-18, so that '0 9 29 feb *' doesn't get skipped (over and over)
|
116
|
+
#
|
117
|
+
dec(@t.day * 24 * 3600 + 1)
|
118
|
+
end
|
119
|
+
|
120
|
+
def dec_day
|
121
|
+
dec(@t.hour * 3600 + @t.min * 60 + @t.sec + 1)
|
122
|
+
end
|
123
|
+
def dec_hour
|
124
|
+
dec(@t.min * 60 + @t.sec + 1)
|
125
|
+
end
|
126
|
+
def dec_min
|
127
|
+
dec(@t.sec + 1)
|
105
128
|
end
|
106
|
-
def dec_day; dec(@t.hour * 3600 + @t.min * 60 + @t.sec + 1); end
|
107
|
-
def dec_hour; dec(@t.min * 60 + @t.sec + 1); end
|
108
|
-
def dec_min; dec(@t.sec + 1); end
|
109
129
|
|
110
|
-
def dec_sec
|
111
|
-
target =
|
112
|
-
|
130
|
+
def dec_sec
|
131
|
+
target =
|
132
|
+
@cron.seconds.reverse.find { |s| s < @t.sec } ||
|
133
|
+
@cron.seconds.last
|
134
|
+
inc(target - @t.sec - (@t.sec > target ? 0 : 60))
|
113
135
|
end
|
114
136
|
end
|
115
137
|
|
@@ -140,7 +162,7 @@ module Fugit
|
|
140
162
|
|
141
163
|
return true if @monthdays.nil?
|
142
164
|
|
143
|
-
last = (TimeCursor.new(nt).inc_month.time - 24 * 3600).day + 1
|
165
|
+
last = (TimeCursor.new(self, nt).inc_month.time - 24 * 3600).day + 1
|
144
166
|
|
145
167
|
@monthdays
|
146
168
|
.collect { |d| d < 1 ? last + d : d }
|
@@ -166,47 +188,43 @@ module Fugit
|
|
166
188
|
hour_match?(t) && min_match?(t) && sec_match?(t)
|
167
189
|
end
|
168
190
|
|
169
|
-
|
170
|
-
#
|
191
|
+
MAX_ITERATION_COUNT = 2048
|
192
|
+
#
|
193
|
+
# See gh-15 and tst/iteration_count.rb
|
194
|
+
#
|
195
|
+
# Initially set to 1024 after seeing the worst case for #next_time
|
196
|
+
# at 167 iterations, I placed it at 2048 after experimenting with
|
197
|
+
# gh-18 and noticing some > 1024 for some experiments. 2048 should
|
198
|
+
# be ok.
|
171
199
|
|
172
200
|
def next_time(from=::EtOrbi::EoTime.now)
|
173
201
|
|
174
202
|
from = ::EtOrbi.make_time(from)
|
175
|
-
sfrom = from.strftime('%F
|
203
|
+
sfrom = from.strftime('%F|%T')
|
176
204
|
ifrom = from.to_i
|
177
205
|
|
178
|
-
|
206
|
+
i = 0
|
207
|
+
t = TimeCursor.new(self, from.translate(@timezone))
|
179
208
|
#
|
180
209
|
# the translation occurs in the timezone of
|
181
210
|
# this Fugit::Cron instance
|
182
211
|
|
183
|
-
ti = 0
|
184
|
-
stalling = false
|
185
|
-
|
186
212
|
loop do
|
187
213
|
|
188
|
-
ti1 = t.to_i
|
189
|
-
|
190
|
-
fail RuntimeError.new(
|
191
|
-
"loop stalled for #{@original.inspect} #next_time, breaking"
|
192
|
-
) if stalling && ti == ti1
|
193
|
-
|
194
|
-
stalling = (ti == ti1)
|
195
|
-
ti = ti1
|
196
|
-
|
197
214
|
fail RuntimeError.new(
|
198
|
-
"too many loops for #{@original.inspect} #next_time, breaking"
|
199
|
-
|
215
|
+
"too many loops for #{@original.inspect} #next_time, breaking, " +
|
216
|
+
"please fill an issue at https://git.io/fjJC9"
|
217
|
+
) if (i += 1) > MAX_ITERATION_COUNT
|
200
218
|
|
201
|
-
(ifrom ==
|
219
|
+
(ifrom == t.to_i) && (t.inc(1); next)
|
202
220
|
month_match?(t) || (t.inc_month; next)
|
203
221
|
day_match?(t) || (t.inc_day; next)
|
204
222
|
hour_match?(t) || (t.inc_hour; next)
|
205
223
|
min_match?(t) || (t.inc_min; next)
|
206
|
-
sec_match?(t) || (t.inc_sec
|
224
|
+
sec_match?(t) || (t.inc_sec; next)
|
207
225
|
|
208
|
-
st = t.time.strftime('%F
|
209
|
-
(from, sfrom, ifrom = t.time, st, t.
|
226
|
+
st = t.time.strftime('%F|%T')
|
227
|
+
(from, sfrom, ifrom = t.time, st, t.to_i; next) if st == sfrom
|
210
228
|
#
|
211
229
|
# when transitioning out of DST, this prevents #next_time from
|
212
230
|
# yielding the same literal time twice in a row, see gh-6
|
@@ -223,33 +241,22 @@ module Fugit
|
|
223
241
|
def previous_time(from=::EtOrbi::EoTime.now)
|
224
242
|
|
225
243
|
from = ::EtOrbi.make_time(from)
|
226
|
-
ti = 0
|
227
|
-
ifrom = from.to_i
|
228
244
|
|
229
|
-
|
230
|
-
|
245
|
+
i = 0
|
246
|
+
t = TimeCursor.new(self, (from - 1).translate(@timezone))
|
231
247
|
|
232
248
|
loop do
|
233
249
|
|
234
|
-
ti1 = t.to_i
|
235
|
-
|
236
|
-
fail RuntimeError.new(
|
237
|
-
"loop stalled for #{@original.inspect} #previous_time, breaking"
|
238
|
-
) if stalling && ti == ti1
|
239
|
-
|
240
|
-
stalling = (ti == ti1)
|
241
|
-
ti = ti1
|
242
|
-
|
243
250
|
fail RuntimeError.new(
|
244
|
-
"too many loops for #{@original.inspect} #previous_time, breaking"
|
245
|
-
|
251
|
+
"too many loops for #{@original.inspect} #previous_time, breaking, " +
|
252
|
+
"please fill an issue at https://git.io/fjJCQ"
|
253
|
+
) if (i += 1) > MAX_ITERATION_COUNT
|
246
254
|
|
247
|
-
(ifrom == ti) && (t.inc(-1); next)
|
248
255
|
month_match?(t) || (t.dec_month; next)
|
249
256
|
day_match?(t) || (t.dec_day; next)
|
250
257
|
hour_match?(t) || (t.dec_hour; next)
|
251
258
|
min_match?(t) || (t.dec_min; next)
|
252
|
-
sec_match?(t) || (t.dec_sec
|
259
|
+
sec_match?(t) || (t.dec_sec; next)
|
253
260
|
break
|
254
261
|
end
|
255
262
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fugit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Mettraux
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-03-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: raabro
|