sidekiq-cron 1.6.0 → 1.8.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 +21 -7
- data/README.md +20 -10
- data/lib/sidekiq/cron/job.rb +104 -91
- data/lib/sidekiq/cron/launcher.rb +15 -13
- data/lib/sidekiq/cron/locales/it.yml +23 -0
- data/lib/sidekiq/cron/poller.rb +14 -18
- data/lib/sidekiq/cron/schedule_loader.rb +12 -4
- data/lib/sidekiq/cron/support.rb +0 -1
- data/lib/sidekiq/cron/version.rb +1 -1
- data/lib/sidekiq/cron/views/cron.erb +1 -1
- data/lib/sidekiq/cron/web_extension.rb +6 -9
- data/lib/sidekiq/options.rb +18 -0
- data/sidekiq-cron.gemspec +5 -7
- data/test/integration/performance_test.rb +1 -1
- data/test/test_helper.rb +1 -0
- data/test/unit/fixtures/schedule_array.yml +13 -0
- data/test/unit/fixtures/schedule_hash.yml +12 -0
- data/test/unit/fixtures/schedule_string.yml +1 -0
- data/test/unit/job_test.rb +115 -21
- data/test/unit/launcher_test.rb +33 -0
- data/test/unit/poller_test.rb +6 -6
- data/test/unit/schedule_loader_test.rb +45 -0
- data/test/unit/web_extension_test.rb +2 -2
- metadata +13 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7df934577b0740b3e977ffd0e361f6333de6958921659d78bf4c4e4a0015aad9
|
4
|
+
data.tar.gz: 6ae3317c56ff984bf0b651df9117121b4cf67cf36d715eee56a7521f47fe0770
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8948ce194538c052c1761b921a4df485bc99ab5ce9b2e4c12b576d90e10bb6bb1691d7fe111d8ecc6b54e3324d53b8c5c45c0be561d58c4adb4414f08db576b8
|
7
|
+
data.tar.gz: 2fcccab9c996fe7a6c79c0090875dd81fca30ba6de130af3cf300d1d745e0212e056afe4ea05a8912191703cddf47800f5e3ea6092e1e751091ecf4a3baffc15
|
data/CHANGELOG.md
CHANGED
@@ -2,10 +2,25 @@
|
|
2
2
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
4
4
|
|
5
|
+
## 1.8.0
|
6
|
+
|
7
|
+
- Fix deprecation warnings with redis-rb v4.8.0 (https://github.com/ondrejbartas/sidekiq-cron/pull/356)
|
8
|
+
- Fix poller affecting Sidekiq scheduled set poller (https://github.com/ondrejbartas/sidekiq-cron/pull/359)
|
9
|
+
- Fix default polling interval (https://github.com/ondrejbartas/sidekiq-cron/pull/362)
|
10
|
+
- Add italian locale (https://github.com/ondrejbartas/sidekiq-cron/pull/367)
|
11
|
+
- Allow disabling of cron polling (https://github.com/ondrejbartas/sidekiq-cron/pull/368)
|
12
|
+
|
13
|
+
## 1.7.0
|
14
|
+
|
15
|
+
- Enable to use cron notation in natural language (ie `every 30 minutes`) (https://github.com/ondrejbartas/sidekiq-cron/pull/312)
|
16
|
+
- Fix `date_as_argument` feature to add timestamp argument at every cron job execution (https://github.com/ondrejbartas/sidekiq-cron/pull/329)
|
17
|
+
- Introduce `Sidekiq::Options` to centralize reading/writing options from different Sidekiq versions (https://github.com/ondrejbartas/sidekiq-cron/pull/341)
|
18
|
+
- Make auto schedule loading compatible with Array format (https://github.com/ondrejbartas/sidekiq-cron/pull/345)
|
19
|
+
|
5
20
|
## 1.6.0
|
6
21
|
|
7
|
-
- Adds support for auto-loading the config/schedule.yml file (https://github.com/ondrejbartas/sidekiq-cron/pull/337)
|
8
|
-
- Fix Sidekiq.options deprecation warning (https://github.com/ondrejbartas/sidekiq-cron/pull/338)
|
22
|
+
- Adds support for auto-loading the `config/schedule.yml` file (https://github.com/ondrejbartas/sidekiq-cron/pull/337)
|
23
|
+
- Fix `Sidekiq.options` deprecation warning (https://github.com/ondrejbartas/sidekiq-cron/pull/338)
|
9
24
|
|
10
25
|
## 1.5.1
|
11
26
|
|
@@ -30,7 +45,6 @@ All notable changes to this project will be documented in this file.
|
|
30
45
|
|
31
46
|
- Add confirmation dialog when enquing jobs from UI
|
32
47
|
- Start to support Sidekiq `average_scheduled_poll_interval` option (replaced `poll_interval`)
|
33
|
-
- Enable to use latest fugit to parse cron notation alowing use of natural language (ie `"every 30 minutes"`)
|
34
48
|
- Fix deprecation warning for Redis 4.6.x
|
35
49
|
- Fix different response from Redis#exists in different Redis versions
|
36
50
|
- All PRs:
|
@@ -52,7 +66,7 @@ All notable changes to this project will be documented in this file.
|
|
52
66
|
|
53
67
|
- Updated readme
|
54
68
|
- Fix unit tests - changed argument error when getting invalid cron format
|
55
|
-
- When fallbacking old job enqueued time use `Time.parse` without format (so
|
69
|
+
- When fallbacking old job enqueued time use `Time.parse` without format (so Ruby can decide best method to parse it)
|
56
70
|
- Add option `date_as_argument` which will add to your job arguments on last place `Time.now.to_f` when it was eneuqued
|
57
71
|
- Add option `description` which will allow you to add notes to your jobs so in web view you can see it
|
58
72
|
- Fixed translations
|
@@ -76,8 +90,8 @@ All notable changes to this project will be documented in this file.
|
|
76
90
|
- Fix poller to enqueu all jobs in poll start time
|
77
91
|
- Add performance test for enqueue of jobs (10 000 jobs in less than 19s)
|
78
92
|
- Fix problem with default queue
|
79
|
-
- Remove redis-namespace from dependencies
|
80
|
-
- Update
|
93
|
+
- Remove `redis-namespace` from dependencies
|
94
|
+
- Update Ruby versions in Travis
|
81
95
|
|
82
96
|
## 0.5.0
|
83
97
|
|
@@ -89,7 +103,7 @@ All notable changes to this project will be documented in this file.
|
|
89
103
|
- Add Russian locale
|
90
104
|
- User Rack.env in tests
|
91
105
|
- Faster enqueue of jobs
|
92
|
-
- Permit to use ActiveJob::Base.queue_name_delimiter
|
106
|
+
- Permit to use `ActiveJob::Base.queue_name_delimiter`
|
93
107
|
- Fix problem with multiple times enqueue #84
|
94
108
|
- Fix problem with enqueue of unknown class
|
95
109
|
|
data/README.md
CHANGED
@@ -64,10 +64,10 @@ gem "sidekiq-cron"
|
|
64
64
|
'queue' => 'name of queue',
|
65
65
|
'args' => '[Array or Hash] of arguments which will be passed to perform method',
|
66
66
|
'date_as_argument' => true, # add the time of execution as last argument of the perform method
|
67
|
-
'active_job' => true, # enqueue job through
|
68
|
-
'queue_name_prefix' => 'prefix', #
|
69
|
-
'queue_name_delimiter' => '.',
|
70
|
-
'description' => 'A sentence describing what work this job performs
|
67
|
+
'active_job' => true, # enqueue job through Rails 4.2+ Active Job interface
|
68
|
+
'queue_name_prefix' => 'prefix', # Rails 4.2+ Active Job queue with prefix
|
69
|
+
'queue_name_delimiter' => '.', # Rails 4.2+ Active Job queue with custom delimiter
|
70
|
+
'description' => 'A sentence describing what work this job performs'
|
71
71
|
'status' => 'disabled' # default: enabled
|
72
72
|
}
|
73
73
|
```
|
@@ -83,6 +83,17 @@ If using Rails, this is evaluated against the timezone configured in Rails, othe
|
|
83
83
|
If you want to have your jobs enqueued based on a different time zone you can specify a timezone in the cronline,
|
84
84
|
like this `'0 22 * * 1-5 America/Chicago'`.
|
85
85
|
|
86
|
+
#### Natural-language formats
|
87
|
+
|
88
|
+
Since sidekiq-cron `v1.7.0`, you can use the natural-language formats supported by Fugit, such as:
|
89
|
+
|
90
|
+
```rb
|
91
|
+
"every day at five" # => '0 5 * * *'
|
92
|
+
"every 3 hours" # => '0 */3 * * *'
|
93
|
+
```
|
94
|
+
|
95
|
+
See [the relevant part of Fugit documentation](https://github.com/floraison/fugit#fugitnat) for details.
|
96
|
+
|
86
97
|
#### Second-precision (sub-minute) cronlines
|
87
98
|
|
88
99
|
In addition to the standard 5-parameter cronline format, sidekiq-cron supports scheduling jobs with second-precision using a modified 6-parameter cronline format:
|
@@ -94,7 +105,7 @@ For example: `"*/30 * * * * *"` would schedule a job to run every 30 seconds.
|
|
94
105
|
Note that if you plan to schedule jobs with second precision you may need to override the default schedule poll interval so it is lower than the interval of your jobs:
|
95
106
|
|
96
107
|
```ruby
|
97
|
-
Sidekiq[:
|
108
|
+
Sidekiq[:cron_poll_interval] = 10
|
98
109
|
```
|
99
110
|
|
100
111
|
The default value at time of writing is 30 seconds. See [under the hood](#under-the-hood) for more details.
|
@@ -248,8 +259,6 @@ Sidekiq.configure_server do |config|
|
|
248
259
|
end
|
249
260
|
```
|
250
261
|
|
251
|
-
Or you can use for loading jobs from yml file [sidekiq-cron-tasks](https://github.com/coverhound/sidekiq-cron-tasks) which will add rake task `bundle exec rake sidekiq_cron:load` to your rails application.
|
252
|
-
|
253
262
|
### Finding jobs
|
254
263
|
|
255
264
|
```ruby
|
@@ -312,8 +321,7 @@ add `require 'sidekiq/cron/web'` after `require 'sidekiq/web'`.
|
|
312
321
|
|
313
322
|
With this, you will get:
|
314
323
|
|
315
|
-
![Web UI](examples/web-cron-ui.
|
316
|
-
|
324
|
+
![Web UI](examples/web-cron-ui.jpeg)
|
317
325
|
|
318
326
|
## Under the hood
|
319
327
|
|
@@ -324,11 +332,13 @@ Sidekiq-Cron adds itself into this start procedure and starts another thread wit
|
|
324
332
|
Sidekiq-Cron is checking jobs to be enqueued every 30s by default, you can change it by setting:
|
325
333
|
|
326
334
|
```ruby
|
327
|
-
Sidekiq[:
|
335
|
+
Sidekiq[:cron_poll_interval] = 10
|
328
336
|
```
|
329
337
|
|
330
338
|
Sidekiq-Cron is safe to use with multiple Sidekiq processes or nodes. It uses a Redis sorted set to determine that only the first process who asks can enqueue scheduled jobs into the queue.
|
331
339
|
|
340
|
+
When running with many Sidekiq processes, the polling can add significant load to Redis. You can disable polling on some processes by setting `Sidekiq[:cron_poll_interval] = 0` on these processes.
|
341
|
+
|
332
342
|
## Contributing
|
333
343
|
|
334
344
|
**Thanks to all [contributors](https://github.com/ondrejbartas/sidekiq-cron/graphs/contributors), you’re awesome and this wouldn’t be possible without you!**
|
data/lib/sidekiq/cron/job.rb
CHANGED
@@ -1,18 +1,21 @@
|
|
1
1
|
require 'fugit'
|
2
2
|
require 'sidekiq'
|
3
3
|
require 'sidekiq/cron/support'
|
4
|
+
require 'sidekiq/options'
|
4
5
|
|
5
6
|
module Sidekiq
|
6
7
|
module Cron
|
7
8
|
class Job
|
8
|
-
#
|
9
|
+
# How long we would like to store informations about previous enqueues.
|
9
10
|
REMEMBER_THRESHOLD = 24 * 60 * 60
|
11
|
+
|
12
|
+
# Time format for enqueued jobs.
|
10
13
|
LAST_ENQUEUE_TIME_FORMAT = '%Y-%m-%d %H:%M:%S %z'
|
11
14
|
|
12
|
-
# Use the exists? method if we're on a newer version of
|
15
|
+
# Use the exists? method if we're on a newer version of Redis.
|
13
16
|
REDIS_EXISTS_METHOD = Gem.loaded_specs['redis'].version < Gem::Version.new('4.2') ? :exists : :exists?
|
14
17
|
|
15
|
-
#
|
18
|
+
# Crucial part of whole enqueuing job.
|
16
19
|
def should_enque? time
|
17
20
|
enqueue = false
|
18
21
|
enqueue = Sidekiq.redis do |conn|
|
@@ -24,18 +27,16 @@ module Sidekiq
|
|
24
27
|
enqueue
|
25
28
|
end
|
26
29
|
|
27
|
-
#
|
28
|
-
# this will clear
|
29
|
-
# not overflow with memory
|
30
|
+
# Remove previous information about run times,
|
31
|
+
# this will clear Redis and make sure that Redis will not overflow with memory.
|
30
32
|
def remove_previous_enques time
|
31
33
|
Sidekiq.redis do |conn|
|
32
34
|
conn.zremrangebyscore(job_enqueued_key, 0, "(#{(time.to_f - REMEMBER_THRESHOLD).to_s}")
|
33
35
|
end
|
34
36
|
end
|
35
37
|
|
36
|
-
#
|
38
|
+
# Test if job should be enqueued.
|
37
39
|
def test_and_enque_for_time! time
|
38
|
-
#should this job be enqued?
|
39
40
|
if should_enque?(time)
|
40
41
|
enque!
|
41
42
|
|
@@ -43,7 +44,7 @@ module Sidekiq
|
|
43
44
|
end
|
44
45
|
end
|
45
46
|
|
46
|
-
#
|
47
|
+
# Enqueue cron job to queue.
|
47
48
|
def enque! time = Time.now.utc
|
48
49
|
@last_enqueue_time = time.strftime(LAST_ENQUEUE_TIME_FORMAT)
|
49
50
|
|
@@ -80,17 +81,27 @@ module Sidekiq
|
|
80
81
|
false
|
81
82
|
end
|
82
83
|
|
84
|
+
def date_as_argument?
|
85
|
+
!!@date_as_argument
|
86
|
+
end
|
87
|
+
|
88
|
+
def enqueue_args
|
89
|
+
date_as_argument? ? @args + [Time.now.to_f] : @args
|
90
|
+
end
|
91
|
+
|
83
92
|
def enqueue_active_job(klass_const)
|
84
|
-
klass_const.set(queue: @queue).perform_later(
|
93
|
+
klass_const.set(queue: @queue).perform_later(*enqueue_args)
|
85
94
|
end
|
86
95
|
|
87
96
|
def enqueue_sidekiq_worker(klass_const)
|
88
|
-
klass_const.set(queue: queue_name_with_prefix).perform_async(
|
97
|
+
klass_const.set(queue: queue_name_with_prefix).perform_async(*enqueue_args)
|
89
98
|
end
|
90
99
|
|
91
|
-
#
|
100
|
+
# Sidekiq worker message.
|
92
101
|
def sidekiq_worker_message
|
93
|
-
@message.is_a?(String) ? Sidekiq.load_json(@message) : @message
|
102
|
+
message = @message.is_a?(String) ? Sidekiq.load_json(@message) : @message
|
103
|
+
message["args"] = enqueue_args
|
104
|
+
message
|
94
105
|
end
|
95
106
|
|
96
107
|
def queue_name_with_prefix
|
@@ -115,8 +126,8 @@ module Sidekiq
|
|
115
126
|
queue_name
|
116
127
|
end
|
117
128
|
|
118
|
-
#
|
119
|
-
# queue, it
|
129
|
+
# Active Job has different structure how it is loading data from Sidekiq
|
130
|
+
# queue, it creates a wrapper around job.
|
120
131
|
def active_job_message
|
121
132
|
{
|
122
133
|
'class' => 'ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper',
|
@@ -127,13 +138,13 @@ module Sidekiq
|
|
127
138
|
'job_class' => @klass,
|
128
139
|
'job_id' => SecureRandom.uuid,
|
129
140
|
'queue_name' => @queue_name_with_prefix,
|
130
|
-
'arguments' =>
|
141
|
+
'arguments' => enqueue_args
|
131
142
|
}]
|
132
143
|
}
|
133
144
|
end
|
134
145
|
|
135
|
-
#
|
136
|
-
#
|
146
|
+
# Load cron jobs from Hash.
|
147
|
+
# Input structure should look like:
|
137
148
|
# {
|
138
149
|
# 'name_of_job' => {
|
139
150
|
# 'class' => 'MyClass',
|
@@ -155,15 +166,15 @@ module Sidekiq
|
|
155
166
|
load_from_array array
|
156
167
|
end
|
157
168
|
|
158
|
-
#
|
159
|
-
# If exists old jobs in
|
169
|
+
# Like #load_from_hash.
|
170
|
+
# If exists old jobs in Redis but removed from args, destroy old jobs.
|
160
171
|
def self.load_from_hash! hash
|
161
172
|
destroy_removed_jobs(hash.keys)
|
162
173
|
load_from_hash(hash)
|
163
174
|
end
|
164
175
|
|
165
|
-
#
|
166
|
-
#
|
176
|
+
# Load cron jobs from Array.
|
177
|
+
# Input structure should look like:
|
167
178
|
# [
|
168
179
|
# {
|
169
180
|
# 'name' => 'name_of_job',
|
@@ -188,15 +199,15 @@ module Sidekiq
|
|
188
199
|
errors
|
189
200
|
end
|
190
201
|
|
191
|
-
#
|
192
|
-
# If exists old jobs in
|
202
|
+
# Like #load_from_array.
|
203
|
+
# If exists old jobs in Redis but removed from args, destroy old jobs.
|
193
204
|
def self.load_from_array! array
|
194
205
|
job_names = array.map { |job| job["name"] }
|
195
206
|
destroy_removed_jobs(job_names)
|
196
207
|
load_from_array(array)
|
197
208
|
end
|
198
209
|
|
199
|
-
#
|
210
|
+
# Get all cron jobs.
|
200
211
|
def self.all
|
201
212
|
job_hashes = nil
|
202
213
|
Sidekiq.redis do |conn|
|
@@ -208,7 +219,7 @@ module Sidekiq
|
|
208
219
|
end
|
209
220
|
end
|
210
221
|
job_hashes.compact.reject(&:empty?).collect do |h|
|
211
|
-
#
|
222
|
+
# No need to fetch missing args from Redis since we just got this hash from there
|
212
223
|
Sidekiq::Cron::Job.new(h.merge(fetch_missing_args: false))
|
213
224
|
end
|
214
225
|
end
|
@@ -222,7 +233,7 @@ module Sidekiq
|
|
222
233
|
end
|
223
234
|
|
224
235
|
def self.find name
|
225
|
-
#
|
236
|
+
# If name is hash try to get name from it.
|
226
237
|
name = name[:name] || name['name'] if name.is_a?(Hash)
|
227
238
|
|
228
239
|
output = nil
|
@@ -234,14 +245,14 @@ module Sidekiq
|
|
234
245
|
output if output && output.valid?
|
235
246
|
end
|
236
247
|
|
237
|
-
#
|
248
|
+
# Create new instance of cron job.
|
238
249
|
def self.create hash
|
239
250
|
new(hash).save
|
240
251
|
end
|
241
252
|
|
242
|
-
#
|
253
|
+
# Destroy job by name.
|
243
254
|
def self.destroy name
|
244
|
-
#
|
255
|
+
# If name is hash try to get name from it.
|
245
256
|
name = name[:name] || name['name'] if name.is_a?(Hash)
|
246
257
|
|
247
258
|
if job = find(name)
|
@@ -263,23 +274,24 @@ module Sidekiq
|
|
263
274
|
@cron = args["cron"]
|
264
275
|
@description = args["description"] if args["description"]
|
265
276
|
|
266
|
-
#
|
277
|
+
# Get class from klass or class.
|
267
278
|
@klass = args["klass"] || args["class"]
|
268
279
|
|
269
|
-
#
|
280
|
+
# Set status of job.
|
270
281
|
@status = args['status'] || status_from_redis
|
271
282
|
|
272
|
-
#
|
283
|
+
# Set last enqueue time - from args or from existing job.
|
273
284
|
if args['last_enqueue_time'] && !args['last_enqueue_time'].empty?
|
274
285
|
@last_enqueue_time = parse_enqueue_time(args['last_enqueue_time'])
|
275
286
|
else
|
276
287
|
@last_enqueue_time = last_enqueue_time_from_redis
|
277
288
|
end
|
278
289
|
|
279
|
-
#
|
290
|
+
# Get right arguments for job.
|
280
291
|
@symbolize_args = args["symbolize_args"] == true || ("#{args["symbolize_args"]}" =~ (/^(true|t|yes|y|1)$/i)) == 0 || false
|
281
292
|
@args = args["args"].nil? ? [] : parse_args( args["args"] )
|
282
|
-
|
293
|
+
|
294
|
+
@date_as_argument = args["date_as_argument"] == true || ("#{args["date_as_argument"]}" =~ (/^(true|t|yes|y|1)$/i)) == 0 || false
|
283
295
|
|
284
296
|
@active_job = args["active_job"] == true || ("#{args["active_job"]}" =~ (/^(true|t|yes|y|1)$/i)) == 0 || false
|
285
297
|
@active_job_queue_name_prefix = args["queue_name_prefix"]
|
@@ -295,8 +307,8 @@ module Sidekiq
|
|
295
307
|
"args" => @args,
|
296
308
|
}
|
297
309
|
|
298
|
-
#
|
299
|
-
#only if message wasn't specified before
|
310
|
+
# Get right data for message,
|
311
|
+
# only if message wasn't specified before.
|
300
312
|
klass_data = case @klass
|
301
313
|
when Class
|
302
314
|
@klass.get_sidekiq_options
|
@@ -304,21 +316,21 @@ module Sidekiq
|
|
304
316
|
begin
|
305
317
|
Sidekiq::Cron::Support.constantize(@klass).get_sidekiq_options
|
306
318
|
rescue Exception => e
|
307
|
-
#Unknown class
|
319
|
+
# Unknown class
|
308
320
|
{"queue"=>"default"}
|
309
321
|
end
|
310
322
|
end
|
311
323
|
|
312
324
|
message_data = klass_data.merge(message_data)
|
313
|
-
|
314
|
-
#
|
325
|
+
|
326
|
+
# Override queue if setted in config,
|
327
|
+
# only if message is hash - can be string (dumped JSON).
|
315
328
|
if args['queue']
|
316
329
|
@queue = message_data['queue'] = args['queue']
|
317
330
|
else
|
318
331
|
@queue = message_data['queue'] || "default"
|
319
332
|
end
|
320
333
|
|
321
|
-
#dump message as json
|
322
334
|
@message = message_data
|
323
335
|
end
|
324
336
|
|
@@ -380,13 +392,12 @@ module Sidekiq
|
|
380
392
|
conn.lrange(jid_history_key, 0, -1) rescue nil
|
381
393
|
end
|
382
394
|
|
383
|
-
# returns nil if out nil
|
384
395
|
out && out.map do |jid_history_raw|
|
385
396
|
Sidekiq.load_json jid_history_raw
|
386
397
|
end
|
387
398
|
end
|
388
399
|
|
389
|
-
#
|
400
|
+
# Export job data to hash.
|
390
401
|
def to_hash
|
391
402
|
{
|
392
403
|
name: @name,
|
@@ -394,6 +405,7 @@ module Sidekiq
|
|
394
405
|
cron: @cron,
|
395
406
|
description: @description,
|
396
407
|
args: @args.is_a?(String) ? @args : Sidekiq.dump_json(@args || []),
|
408
|
+
date_as_argument: @date_as_argument,
|
397
409
|
message: @message.is_a?(String) ? @message : Sidekiq.dump_json(@message || {}),
|
398
410
|
status: @status,
|
399
411
|
active_job: @active_job,
|
@@ -409,7 +421,7 @@ module Sidekiq
|
|
409
421
|
end
|
410
422
|
|
411
423
|
def valid?
|
412
|
-
#
|
424
|
+
# Clear previous errors.
|
413
425
|
@errors = []
|
414
426
|
|
415
427
|
errors << "'name' must be set" if @name.nil? || @name.size == 0
|
@@ -417,7 +429,15 @@ module Sidekiq
|
|
417
429
|
errors << "'cron' must be set"
|
418
430
|
else
|
419
431
|
begin
|
420
|
-
|
432
|
+
c = Fugit.do_parse(@cron)
|
433
|
+
|
434
|
+
# Since `Fugit.do_parse` might yield a Fugit::Duration or an EtOrbi::EoTime
|
435
|
+
# https://github.com/floraison/fugit#fugitparses
|
436
|
+
if c.is_a?(Fugit::Cron)
|
437
|
+
@parsed_cron = c
|
438
|
+
else
|
439
|
+
errors << "'cron' -> #{@cron.inspect} -> not a cron but a #{c.class}"
|
440
|
+
end
|
421
441
|
rescue => e
|
422
442
|
errors << "'cron' -> #{@cron.inspect} -> #{e.class}: #{e.message}"
|
423
443
|
end
|
@@ -438,28 +458,19 @@ module Sidekiq
|
|
438
458
|
end
|
439
459
|
end
|
440
460
|
|
441
|
-
# add job to cron jobs
|
442
|
-
# input:
|
443
|
-
# name: (string) - name of job
|
444
|
-
# cron: (string: '* * * * *' - cron specification when to run job
|
445
|
-
# class: (string|class) - which class to perform
|
446
|
-
# optional input:
|
447
|
-
# queue: (string) - which queue to use for enquing (will override class queue)
|
448
|
-
# args: (array|hash|nil) - arguments for permorm method
|
449
|
-
|
450
461
|
def save
|
451
|
-
#
|
462
|
+
# If job is invalid, return false.
|
452
463
|
return false unless valid?
|
453
464
|
|
454
465
|
Sidekiq.redis do |conn|
|
455
466
|
|
456
|
-
#
|
457
|
-
conn.sadd self.class.jobs_key, redis_key
|
467
|
+
# Add to set of all jobs
|
468
|
+
conn.sadd self.class.jobs_key, [redis_key]
|
458
469
|
|
459
|
-
#
|
470
|
+
# Add informations for this job!
|
460
471
|
conn.hmset redis_key, *hash_to_redis(to_hash)
|
461
472
|
|
462
|
-
#
|
473
|
+
# Add information about last time! - don't enque right after scheduler poller starts!
|
463
474
|
time = Time.now.utc
|
464
475
|
conn.zadd(job_enqueued_key, time.to_f.to_s, formated_last_time(time).to_s) unless conn.public_send(REDIS_EXISTS_METHOD, job_enqueued_key)
|
465
476
|
end
|
@@ -468,7 +479,7 @@ module Sidekiq
|
|
468
479
|
|
469
480
|
def save_last_enqueue_time
|
470
481
|
Sidekiq.redis do |conn|
|
471
|
-
#
|
482
|
+
# Update last enqueue time.
|
472
483
|
conn.hset redis_key, 'last_enqueue_time', @last_enqueue_time
|
473
484
|
end
|
474
485
|
end
|
@@ -478,37 +489,35 @@ module Sidekiq
|
|
478
489
|
jid: jid,
|
479
490
|
enqueued: @last_enqueue_time
|
480
491
|
}
|
481
|
-
|
482
|
-
@history_size ||= (cron_history_size || 10).to_i - 1
|
492
|
+
|
493
|
+
@history_size ||= (Sidekiq::Options[:cron_history_size] || 10).to_i - 1
|
483
494
|
Sidekiq.redis do |conn|
|
484
495
|
conn.lpush jid_history_key,
|
485
496
|
Sidekiq.dump_json(jid_history)
|
486
|
-
#
|
497
|
+
# Keep only last 10 entries in a fifo manner.
|
487
498
|
conn.ltrim jid_history_key, 0, @history_size
|
488
499
|
end
|
489
500
|
end
|
490
501
|
|
491
|
-
# remove job from cron jobs by name
|
492
|
-
# input:
|
493
|
-
# first arg: name (string) - name of job (must be same - case sensitive)
|
494
502
|
def destroy
|
495
503
|
Sidekiq.redis do |conn|
|
496
|
-
#
|
497
|
-
conn.srem self.class.jobs_key, redis_key
|
504
|
+
# Delete from set.
|
505
|
+
conn.srem self.class.jobs_key, [redis_key]
|
498
506
|
|
499
|
-
#
|
507
|
+
# Delete runned timestamps.
|
500
508
|
conn.del job_enqueued_key
|
501
509
|
|
502
|
-
#
|
510
|
+
# Delete jid_history.
|
503
511
|
conn.del jid_history_key
|
504
512
|
|
505
|
-
#
|
513
|
+
# Delete main job.
|
506
514
|
conn.del redis_key
|
507
515
|
end
|
516
|
+
|
508
517
|
Sidekiq.logger.info { "Cron Jobs - deleted job with name: #{@name}" }
|
509
518
|
end
|
510
519
|
|
511
|
-
#
|
520
|
+
# Remove all job from cron.
|
512
521
|
def self.destroy_all!
|
513
522
|
all.each do |job|
|
514
523
|
job.destroy
|
@@ -516,7 +525,7 @@ module Sidekiq
|
|
516
525
|
Sidekiq.logger.info { "Cron Jobs - deleted all jobs" }
|
517
526
|
end
|
518
527
|
|
519
|
-
#
|
528
|
+
# Remove "removed jobs" between current jobs and new jobs
|
520
529
|
def self.destroy_removed_jobs new_job_names
|
521
530
|
current_job_names = Sidekiq::Cron::Job.all.map(&:name)
|
522
531
|
removed_job_names = current_job_names - new_job_names
|
@@ -557,7 +566,19 @@ module Sidekiq
|
|
557
566
|
private
|
558
567
|
|
559
568
|
def parsed_cron
|
560
|
-
@parsed_cron ||=
|
569
|
+
@parsed_cron ||= begin
|
570
|
+
c = Fugit.parse(@cron)
|
571
|
+
|
572
|
+
# Since `Fugit.parse` might yield a Fugit::Duration or an EtOrbi::EoTime
|
573
|
+
# https://github.com/floraison/fugit#fugitparses
|
574
|
+
if c.is_a?(Fugit::Cron)
|
575
|
+
c
|
576
|
+
else
|
577
|
+
errors << "'cron' -> #{@cron.inspect} -> not a cron but a #{c.class}"
|
578
|
+
end
|
579
|
+
rescue => e
|
580
|
+
errors << "'cron' -> #{@cron.inspect} -> #{e.class}: #{e.message}"
|
581
|
+
end
|
561
582
|
end
|
562
583
|
|
563
584
|
def not_enqueued_after?(time)
|
@@ -565,9 +586,8 @@ module Sidekiq
|
|
565
586
|
end
|
566
587
|
|
567
588
|
# Try parsing inbound args into an array.
|
568
|
-
#
|
569
|
-
# try to load JSON, then failover
|
570
|
-
# to string array.
|
589
|
+
# Args from Redis will be encoded JSON,
|
590
|
+
# try to load JSON, then failover to string array.
|
571
591
|
def parse_args(args)
|
572
592
|
case args
|
573
593
|
when String
|
@@ -575,14 +595,14 @@ module Sidekiq
|
|
575
595
|
parsed_args = Sidekiq.load_json(args)
|
576
596
|
symbolize_args? ? symbolize_args(parsed_args) : parsed_args
|
577
597
|
rescue JSON::ParserError
|
578
|
-
[*args]
|
598
|
+
[*args]
|
579
599
|
end
|
580
600
|
when Hash
|
581
601
|
symbolize_args? ? [symbolize_args(args)] : [args]
|
582
602
|
when Array
|
583
603
|
symbolize_args? ? symbolize_args(args) : args
|
584
604
|
else
|
585
|
-
[*args]
|
605
|
+
[*args]
|
586
606
|
end
|
587
607
|
end
|
588
608
|
|
@@ -614,29 +634,26 @@ module Sidekiq
|
|
614
634
|
|
615
635
|
def not_past_scheduled_time?(current_time)
|
616
636
|
last_cron_time = parsed_cron.previous_time(current_time).utc
|
617
|
-
# or could it be?
|
618
|
-
#last_cron_time = last_time(current_time)
|
619
637
|
return false if (current_time.to_i - last_cron_time.to_i) > 60
|
620
638
|
true
|
621
639
|
end
|
622
640
|
|
623
|
-
# Redis key for set of all cron jobs
|
641
|
+
# Redis key for set of all cron jobs.
|
624
642
|
def self.jobs_key
|
625
643
|
"cron_jobs"
|
626
644
|
end
|
627
645
|
|
628
|
-
# Redis key for storing one cron job
|
646
|
+
# Redis key for storing one cron job.
|
629
647
|
def self.redis_key name
|
630
648
|
"cron_job:#{name}"
|
631
649
|
end
|
632
650
|
|
633
|
-
# Redis key for storing one cron job
|
651
|
+
# Redis key for storing one cron job.
|
634
652
|
def redis_key
|
635
653
|
self.class.redis_key @name
|
636
654
|
end
|
637
655
|
|
638
|
-
# Redis key for storing one cron job run times
|
639
|
-
# (when poller added job to queue)
|
656
|
+
# Redis key for storing one cron job run times (when poller added job to queue)
|
640
657
|
def self.job_enqueued_key name
|
641
658
|
"cron_job:#{name}:enqueued"
|
642
659
|
end
|
@@ -645,8 +662,6 @@ module Sidekiq
|
|
645
662
|
"cron_job:#{name}:jid_history"
|
646
663
|
end
|
647
664
|
|
648
|
-
# Redis key for storing one cron job run times
|
649
|
-
# (when poller added job to queue)
|
650
665
|
def job_enqueued_key
|
651
666
|
self.class.job_enqueued_key @name
|
652
667
|
end
|
@@ -655,12 +670,10 @@ module Sidekiq
|
|
655
670
|
self.class.jid_history_key @name
|
656
671
|
end
|
657
672
|
|
658
|
-
# Give Hash
|
659
|
-
# returns array for using it for redis.hmset
|
673
|
+
# Give Hash returns array for using it for redis.hmset
|
660
674
|
def hash_to_redis hash
|
661
675
|
hash.inject([]){ |arr,kv| arr + [kv[0], kv[1]] }
|
662
676
|
end
|
663
|
-
|
664
677
|
end
|
665
678
|
end
|
666
679
|
end
|