resque-scheduler 3.0.0 → 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.
Potentially problematic release.
This version of resque-scheduler might be problematic. Click here for more details.
- checksums.yaml +13 -5
- data/.rubocop.yml +3 -21
- data/.rubocop_todo.yml +37 -9
- data/.travis.yml +16 -7
- data/HISTORY.md +9 -0
- data/README.md +10 -2
- data/Rakefile +1 -1
- data/lib/resque/scheduler.rb +2 -2
- data/lib/resque/scheduler/delaying_extensions.rb +38 -25
- data/lib/resque/scheduler/env.rb +57 -21
- data/lib/resque/scheduler/lock/base.rb +5 -0
- data/lib/resque/scheduler/locking.rb +8 -0
- data/lib/resque/scheduler/scheduling_extensions.rb +39 -24
- data/lib/resque/scheduler/server.rb +3 -3
- data/lib/resque/scheduler/tasks.rb +0 -1
- data/lib/resque/scheduler/version.rb +1 -1
- data/resque-scheduler.gemspec +10 -5
- data/test/cli_test.rb +2 -2
- data/test/delayed_queue_test.rb +69 -0
- data/test/env_test.rb +11 -5
- data/test/multi_process_test.rb +37 -0
- data/test/resque-web_test.rb +5 -5
- data/test/scheduler_locking_test.rb +6 -0
- data/test/scheduler_task_test.rb +3 -3
- data/test/scheduler_test.rb +2 -2
- data/test/support/redis_instance.rb +1 -1
- metadata +54 -54
checksums.yaml
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
YzhjNDEyNjkyZWQ5MGY0YWUxNWNmN2JiMTAzODdhOGUyZTAyZTA1YQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
NTQzOWY4MDliZjUxZDhlMTZjYTc4OWM0NWVjMTA5MTVmZmJkYzQ1ZA==
|
5
7
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
ZDE1ZTBlZjlkOWM1MDEwMjc3Y2I2MWExNTNiNjFlMDUyNjY1YzZlMmYxYWQ0
|
10
|
+
MjdkMjQ3OTA0N2FhYjk4NWI5NTdkZmM2ODYwNTMzNGM4OTExNDdkMjA5ZjI1
|
11
|
+
MWI2Y2ExOWZkM2EyZjkxNTVlNTViODExNDYwZjk4OTAyMWM5YWI=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
YzE3OTNjODE1YWI5NWQwNmNjZDJlMDM0Yjg2ZTAwZGRkMzA2NzY3NTc4ZjI4
|
14
|
+
NGQ4Y2Q4ZDM1NWUxNDViYjk3YmI1M2E5ZDMwYjAzMTk4MWYwZjMzNGVmNmE5
|
15
|
+
YTAyYWI4NGI1Zjc1M2U1MzgxZTk4NWNiODYzZDQyODFkM2M2MWM=
|
data/.rubocop.yml
CHANGED
@@ -7,28 +7,10 @@ AllCops:
|
|
7
7
|
- resque-scheduler.gemspec
|
8
8
|
- bin/resque-scheduler
|
9
9
|
|
10
|
-
# Offence count: 1
|
11
|
-
CaseEquality:
|
12
|
-
Enabled: false
|
13
|
-
|
14
|
-
# Offence count: 2
|
15
|
-
# Configuration parameters: CountComments.
|
16
|
-
ClassLength:
|
17
|
-
Max: 130
|
18
|
-
|
19
|
-
# Offence count: 3
|
20
|
-
CyclomaticComplexity:
|
21
|
-
Max: 21
|
22
|
-
|
23
|
-
# Offence count: 29
|
24
10
|
Documentation:
|
25
11
|
Enabled: false
|
26
12
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
Max: 145
|
31
|
-
|
32
|
-
# Offence count: 1
|
33
|
-
RescueException:
|
13
|
+
Style/DoubleNegation:
|
14
|
+
Enabled: false
|
15
|
+
Metrics/PerceivedComplexity:
|
34
16
|
Enabled: false
|
data/.rubocop_todo.yml
CHANGED
@@ -1,29 +1,57 @@
|
|
1
1
|
# This configuration was generated by `rubocop --auto-gen-config`
|
2
|
-
# on 2014-
|
2
|
+
# on 2014-12-21 12:37:35 -0500 using RuboCop version 0.28.0.
|
3
3
|
# The point is for the user to remove these configuration records
|
4
4
|
# one by one as the offenses are removed from the code base.
|
5
5
|
# Note that changes in the inspected code, or installation of new
|
6
6
|
# versions of RuboCop, may require this file to be generated again.
|
7
7
|
|
8
|
-
# Offense count:
|
9
|
-
|
8
|
+
# Offense count: 2
|
9
|
+
# Configuration parameters: AllowSafeAssignment.
|
10
|
+
Lint/AssignmentInCondition:
|
10
11
|
Enabled: false
|
11
12
|
|
13
|
+
# Offense count: 16
|
14
|
+
Metrics/AbcSize:
|
15
|
+
Max: 42
|
16
|
+
|
17
|
+
# Offense count: 2
|
18
|
+
# Configuration parameters: CountComments.
|
19
|
+
Metrics/ClassLength:
|
20
|
+
Max: 105
|
21
|
+
|
22
|
+
# Offense count: 4
|
23
|
+
Metrics/CyclomaticComplexity:
|
24
|
+
Max: 12
|
25
|
+
|
26
|
+
# Offense count: 18
|
27
|
+
# Configuration parameters: CountComments.
|
28
|
+
Metrics/MethodLength:
|
29
|
+
Max: 34
|
30
|
+
|
12
31
|
# Offense count: 1
|
13
|
-
|
32
|
+
Style/CaseEquality:
|
33
|
+
Enabled: false
|
34
|
+
|
35
|
+
# Offense count: 1
|
36
|
+
Style/EachWithObject:
|
14
37
|
Enabled: false
|
15
38
|
|
16
39
|
# Offense count: 3
|
17
40
|
# Configuration parameters: Exclude.
|
18
|
-
FileName:
|
41
|
+
Style/FileName:
|
19
42
|
Enabled: false
|
20
43
|
|
21
|
-
# Offense count:
|
44
|
+
# Offense count: 6
|
22
45
|
# Configuration parameters: MinBodyLength.
|
23
|
-
GuardClause:
|
46
|
+
Style/GuardClause:
|
47
|
+
Enabled: false
|
48
|
+
|
49
|
+
# Offense count: 6
|
50
|
+
# Configuration parameters: MaxLineLength.
|
51
|
+
Style/IfUnlessModifier:
|
24
52
|
Enabled: false
|
25
53
|
|
26
54
|
# Offense count: 1
|
27
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
28
|
-
Next:
|
55
|
+
# Configuration parameters: EnforcedStyle, MinBodyLength, SupportedStyles.
|
56
|
+
Style/Next:
|
29
57
|
Enabled: false
|
data/.travis.yml
CHANGED
@@ -1,23 +1,31 @@
|
|
1
1
|
language: ruby
|
2
|
+
sudo: false
|
2
3
|
rvm:
|
3
|
-
-
|
4
|
-
-
|
5
|
-
-
|
6
|
-
-
|
4
|
+
- 1.9.3
|
5
|
+
- 2.1.5
|
6
|
+
- jruby-19mode
|
7
|
+
- rbx
|
7
8
|
env:
|
8
9
|
global:
|
9
10
|
- RESQUE_SCHEDULER_DISABLE_TEST_REDIS_SERVER=1
|
10
11
|
- JRUBY_OPTS='-Xcext.enabled=true'
|
11
12
|
matrix:
|
12
13
|
allow_failures:
|
13
|
-
- rvm:
|
14
|
-
- rvm:
|
14
|
+
- rvm: jruby-19mode
|
15
|
+
- rvm: rbx
|
15
16
|
services:
|
16
17
|
- redis-server
|
17
18
|
notifications:
|
18
19
|
email:
|
19
20
|
recipients:
|
20
21
|
- daniel.buch+resque-scheduler@gmail.com
|
22
|
+
on_success: change
|
23
|
+
on_failure: change
|
24
|
+
irc:
|
25
|
+
channels:
|
26
|
+
- 'chat.freenode.net#resque'
|
27
|
+
on_success: change
|
28
|
+
on_failure: change
|
21
29
|
deploy:
|
22
30
|
provider: rubygems
|
23
31
|
api_key:
|
@@ -26,4 +34,5 @@ deploy:
|
|
26
34
|
on:
|
27
35
|
tags: true
|
28
36
|
repo: resque/resque-scheduler
|
29
|
-
rvm:
|
37
|
+
rvm: 2.1.5
|
38
|
+
all_branches: true
|
data/HISTORY.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
# Resque Scheduler History / ChangeLog / Release Notes
|
2
2
|
|
3
|
+
## 3.1.0 (2014-12-21)
|
4
|
+
* Note in README.md about production redis deployment configuration
|
5
|
+
* Bugfix to only override configuration options if provided
|
6
|
+
* Avoid use of redis `KEYS` command in `Resque.remove_delayed_selection`
|
7
|
+
* Better PID file cleanup
|
8
|
+
* Added option to filter by job class in `Resque.remove_delayed_selection`
|
9
|
+
* Bugfix to only release master lock if it belongs to us
|
10
|
+
* Tell-don't-ask with `Resque.schedule` to enable atomic clear & set
|
11
|
+
|
3
12
|
## 3.0.0 (2014-05-27)
|
4
13
|
* The grand re-namespacing of
|
5
14
|
`resque_scheduler/(.*)` => `resque/scheduler/\1`
|
data/README.md
CHANGED
@@ -44,7 +44,7 @@ To install:
|
|
44
44
|
|
45
45
|
gem install resque-scheduler
|
46
46
|
|
47
|
-
If you use a Gemfile
|
47
|
+
If you use a Gemfile:
|
48
48
|
|
49
49
|
```ruby
|
50
50
|
gem 'resque-scheduler'
|
@@ -151,7 +151,7 @@ default `'text'`)
|
|
151
151
|
of `MonoLogger::DEBUG`, default `false`)
|
152
152
|
|
153
153
|
|
154
|
-
### Resque Pool integration
|
154
|
+
### Resque Pool integration
|
155
155
|
|
156
156
|
For normal work with the
|
157
157
|
[resque-pool](https://github.com/nevans/resque-pool) gem, add the
|
@@ -599,6 +599,14 @@ provisioners:
|
|
599
599
|
vagrant up
|
600
600
|
```
|
601
601
|
|
602
|
+
### Deployment Notes
|
603
|
+
|
604
|
+
It is recommended that a production deployment of resque_scheduler be hosted on
|
605
|
+
a dedicated Redis database. While making and managing scheduled tasks,
|
606
|
+
resque_scheudler currently scans the entire Redis keyspace, which may cause latency
|
607
|
+
and stability issues if resque_scheduler is hosted on a Redis instance storing a large
|
608
|
+
number of keys (such as those written by a different system hosted on the same Redis instance).
|
609
|
+
|
602
610
|
### Contributing
|
603
611
|
|
604
612
|
See [CONTRIBUTING.md](CONTRIBUTING.md)
|
data/Rakefile
CHANGED
data/lib/resque/scheduler.rb
CHANGED
@@ -206,7 +206,7 @@ module Resque
|
|
206
206
|
|
207
207
|
def handle_errors
|
208
208
|
yield
|
209
|
-
rescue
|
209
|
+
rescue => e
|
210
210
|
log_error "#{e.class.name}: #{e.message}"
|
211
211
|
end
|
212
212
|
|
@@ -336,7 +336,7 @@ module Resque
|
|
336
336
|
rescue Interrupt
|
337
337
|
if @shutdown
|
338
338
|
Resque.clean_schedules
|
339
|
-
release_master_lock
|
339
|
+
release_master_lock
|
340
340
|
end
|
341
341
|
break
|
342
342
|
end
|
@@ -105,12 +105,7 @@ module Resque
|
|
105
105
|
# Returns the next delayed queue timestamp
|
106
106
|
# (don't call directly)
|
107
107
|
def next_delayed_timestamp(at_time = nil)
|
108
|
-
|
109
|
-
:delayed_queue_schedule, '-inf', (at_time || Time.now).to_i,
|
110
|
-
limit: [0, 1]
|
111
|
-
)
|
112
|
-
timestamp = items.nil? ? nil : Array(items).first
|
113
|
-
timestamp.to_i unless timestamp.nil?
|
108
|
+
search_first_delayed_timestamp_in_range(nil, at_time || Time.now)
|
114
109
|
end
|
115
110
|
|
116
111
|
# Returns the next item to be processed for a given timestamp, nil if
|
@@ -145,17 +140,7 @@ module Resque
|
|
145
140
|
# Given an encoded item, remove it from the delayed_queue
|
146
141
|
def remove_delayed(klass, *args)
|
147
142
|
search = encode(job_to_hash(klass, args))
|
148
|
-
|
149
|
-
|
150
|
-
replies = redis.pipelined do
|
151
|
-
timestamps.each do |key|
|
152
|
-
redis.lrem(key, 0, search)
|
153
|
-
redis.srem("timestamps:#{search}", key)
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
return 0 if replies.nil? || replies.empty?
|
158
|
-
replies.each_slice(2).map(&:first).inject(:+)
|
143
|
+
remove_delayed_job(search)
|
159
144
|
end
|
160
145
|
|
161
146
|
# Given an encoded item, enqueue it now
|
@@ -170,21 +155,22 @@ module Resque
|
|
170
155
|
#
|
171
156
|
# This allows for removal of delayed jobs that have arguments matching
|
172
157
|
# certain criteria
|
173
|
-
def remove_delayed_selection
|
158
|
+
def remove_delayed_selection(klass = nil)
|
174
159
|
fail ArgumentError, 'Please supply a block' unless block_given?
|
175
160
|
|
176
161
|
destroyed = 0
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
jobs.each do |job|
|
162
|
+
start = nil
|
163
|
+
while start = search_first_delayed_timestamp_in_range(start, nil)
|
164
|
+
job = "delayed:#{start}"
|
165
|
+
start += 1
|
182
166
|
index = Resque.redis.llen(job) - 1
|
183
167
|
while index >= 0
|
184
168
|
payload = Resque.redis.lindex(job, index)
|
185
169
|
decoded_payload = decode(payload)
|
186
|
-
|
187
|
-
|
170
|
+
job_class = decoded_payload['class']
|
171
|
+
relevant_class = (klass.nil? || klass.to_s == job_class)
|
172
|
+
if relevant_class && yield(decoded_payload['args'])
|
173
|
+
removed = remove_delayed_job(payload)
|
188
174
|
destroyed += removed
|
189
175
|
index -= removed
|
190
176
|
else
|
@@ -192,6 +178,7 @@ module Resque
|
|
192
178
|
end
|
193
179
|
end
|
194
180
|
end
|
181
|
+
|
195
182
|
destroyed
|
196
183
|
end
|
197
184
|
|
@@ -254,6 +241,20 @@ module Resque
|
|
254
241
|
{ class: klass.to_s, args: args, queue: queue }
|
255
242
|
end
|
256
243
|
|
244
|
+
def remove_delayed_job(encoded_job)
|
245
|
+
timestamps = redis.smembers("timestamps:#{encoded_job}")
|
246
|
+
|
247
|
+
replies = redis.pipelined do
|
248
|
+
timestamps.each do |key|
|
249
|
+
redis.lrem(key, 0, encoded_job)
|
250
|
+
redis.srem("timestamps:#{encoded_job}", key)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
return 0 if replies.nil? || replies.empty?
|
255
|
+
replies.each_slice(2).map(&:first).inject(:+)
|
256
|
+
end
|
257
|
+
|
257
258
|
def clean_up_timestamp(key, timestamp)
|
258
259
|
# If the list is empty, remove it.
|
259
260
|
|
@@ -270,6 +271,18 @@ module Resque
|
|
270
271
|
end
|
271
272
|
end
|
272
273
|
|
274
|
+
def search_first_delayed_timestamp_in_range(start_at, stop_at)
|
275
|
+
start_at = start_at.nil? ? '-inf' : start_at.to_i
|
276
|
+
stop_at = stop_at.nil? ? '+inf' : stop_at.to_i
|
277
|
+
|
278
|
+
items = redis.zrangebyscore(
|
279
|
+
:delayed_queue_schedule, start_at, stop_at,
|
280
|
+
limit: [0, 1]
|
281
|
+
)
|
282
|
+
timestamp = items.nil? ? nil : Array(items).first
|
283
|
+
timestamp.to_i unless timestamp.nil?
|
284
|
+
end
|
285
|
+
|
273
286
|
def plugin
|
274
287
|
Resque::Scheduler::Plugin
|
275
288
|
end
|
data/lib/resque/scheduler/env.rb
CHANGED
@@ -1,10 +1,13 @@
|
|
1
1
|
# vim:fileencoding=utf-8
|
2
2
|
|
3
|
+
require 'English' # $PROCESS_ID
|
4
|
+
|
3
5
|
module Resque
|
4
6
|
module Scheduler
|
5
7
|
class Env
|
6
8
|
def initialize(options)
|
7
9
|
@options = options
|
10
|
+
@pidfile_path = nil
|
8
11
|
end
|
9
12
|
|
10
13
|
def setup
|
@@ -16,46 +19,79 @@ module Resque
|
|
16
19
|
setup_scheduler_configuration
|
17
20
|
end
|
18
21
|
|
22
|
+
def cleanup
|
23
|
+
cleanup_pid_file
|
24
|
+
end
|
25
|
+
|
19
26
|
private
|
20
27
|
|
21
|
-
attr_reader :options
|
28
|
+
attr_reader :options, :pidfile_path
|
22
29
|
|
23
30
|
def setup_backgrounding
|
31
|
+
return unless options[:background]
|
32
|
+
|
24
33
|
# Need to set this here for conditional Process.daemon redirect of
|
25
34
|
# stderr/stdout to /dev/null
|
26
35
|
Resque::Scheduler.quiet = !!options[:quiet]
|
27
36
|
|
28
|
-
|
29
|
-
|
30
|
-
abort 'background option is set, which requires ruby >= 1.9'
|
31
|
-
end
|
32
|
-
|
33
|
-
Process.daemon(true, !Resque::Scheduler.quiet)
|
34
|
-
Resque.redis.client.reconnect
|
37
|
+
unless Process.respond_to?('daemon')
|
38
|
+
abort 'background option is set, which requires ruby >= 1.9'
|
35
39
|
end
|
40
|
+
|
41
|
+
Process.daemon(true, !Resque::Scheduler.quiet)
|
42
|
+
Resque.redis.client.reconnect
|
36
43
|
end
|
37
44
|
|
38
45
|
def setup_pid_file
|
39
|
-
|
46
|
+
return unless options[:pidfile]
|
47
|
+
|
48
|
+
@pidfile_path = File.expand_path(options[:pidfile])
|
49
|
+
|
50
|
+
File.open(pidfile_path, 'w') do |f|
|
40
51
|
f.puts $PROCESS_ID
|
41
|
-
end
|
52
|
+
end
|
53
|
+
|
54
|
+
at_exit { cleanup_pid_file }
|
42
55
|
end
|
43
56
|
|
44
57
|
def setup_scheduler_configuration
|
45
58
|
Resque::Scheduler.configure do |c|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
59
|
+
if options.key?(:app_name)
|
60
|
+
c.app_name = options[:app_name]
|
61
|
+
end
|
62
|
+
|
63
|
+
if options.key?(:dynamic)
|
64
|
+
c.dynamic = !!options[:dynamic]
|
65
|
+
end
|
66
|
+
|
67
|
+
if options.key(:env)
|
68
|
+
c.env = options[:env]
|
69
|
+
end
|
70
|
+
|
71
|
+
if options.key?(:logfile)
|
72
|
+
c.logfile = options[:logfile]
|
73
|
+
end
|
74
|
+
|
75
|
+
if options.key?(:logformat)
|
76
|
+
c.logformat = options[:logformat]
|
77
|
+
end
|
78
|
+
|
79
|
+
if psleep = options[:poll_sleep_amount] && !psleep.nil?
|
80
|
+
c.poll_sleep_amount = Float(psleep)
|
81
|
+
end
|
82
|
+
|
83
|
+
if options.key?(:verbose)
|
84
|
+
c.verbose = !!options[:verbose]
|
85
|
+
end
|
57
86
|
end
|
58
87
|
end
|
88
|
+
|
89
|
+
def cleanup_pid_file
|
90
|
+
return unless pidfile_path
|
91
|
+
|
92
|
+
File.delete(pidfile_path) if File.exist?(pidfile_path)
|
93
|
+
@pidfile_path = nil
|
94
|
+
end
|
59
95
|
end
|
60
96
|
end
|
61
97
|
end
|
@@ -67,9 +67,17 @@ module Resque
|
|
67
67
|
end
|
68
68
|
|
69
69
|
def release_master_lock!
|
70
|
+
warn "#{self}\#release_master_lock! is deprecated because it does " \
|
71
|
+
"not respect lock ownership. Use #{self}\#release_master_lock " \
|
72
|
+
"instead (at #{caller.first}"
|
73
|
+
|
70
74
|
master_lock.release!
|
71
75
|
end
|
72
76
|
|
77
|
+
def release_master_lock
|
78
|
+
master_lock.release
|
79
|
+
end
|
80
|
+
|
73
81
|
private
|
74
82
|
|
75
83
|
def build_master_lock
|
@@ -44,15 +44,33 @@ module Resque
|
|
44
44
|
# param, otherwise params is passed in as the only parameter to
|
45
45
|
# perform.
|
46
46
|
def schedule=(schedule_hash)
|
47
|
-
#
|
48
|
-
|
47
|
+
# This operation tries to be as atomic as possible.
|
48
|
+
# It needs to read the existing schedules outside the transaction.
|
49
|
+
# Unlikely, but this could still cause a race condition.
|
50
|
+
#
|
51
|
+
# A more robust solution would be to SCRIPT it, but that would change
|
52
|
+
# the required version of Redis.
|
49
53
|
|
50
|
-
|
54
|
+
# select schedules to remove
|
55
|
+
if redis.exists(:schedules)
|
56
|
+
clean_keys = non_persistent_schedules
|
57
|
+
else
|
58
|
+
clean_keys = []
|
59
|
+
end
|
51
60
|
|
52
|
-
#
|
53
|
-
#
|
54
|
-
|
55
|
-
|
61
|
+
# Start the transaction. If this is not atomic and more than one
|
62
|
+
# process is calling `schedule=` the clean_schedules might overlap a
|
63
|
+
# set_schedule and cause the schedules to become corrupt.
|
64
|
+
redis.multi do
|
65
|
+
clean_schedules(clean_keys)
|
66
|
+
|
67
|
+
schedule_hash = prepare_schedule(schedule_hash)
|
68
|
+
|
69
|
+
# store all schedules in redis, so we can retrieve them back
|
70
|
+
# everywhere.
|
71
|
+
schedule_hash.each do |name, job_spec|
|
72
|
+
set_schedule(name, job_spec)
|
73
|
+
end
|
56
74
|
end
|
57
75
|
|
58
76
|
# ensure only return the successfully saved data!
|
@@ -82,16 +100,18 @@ module Resque
|
|
82
100
|
end
|
83
101
|
|
84
102
|
# clean the schedules as it exists in redis, useful for first setup?
|
85
|
-
def clean_schedules
|
86
|
-
|
87
|
-
|
88
|
-
remove_schedule(key) unless schedule_persisted?(key)
|
89
|
-
end
|
103
|
+
def clean_schedules(keys = non_persistent_schedules)
|
104
|
+
keys.each do |key|
|
105
|
+
remove_schedule(key)
|
90
106
|
end
|
91
107
|
@schedule = nil
|
92
108
|
true
|
93
109
|
end
|
94
110
|
|
111
|
+
def non_persistent_schedules
|
112
|
+
redis.hkeys(:schedules).select { |k| !schedule_persisted?(k) }
|
113
|
+
end
|
114
|
+
|
95
115
|
# Create or update a schedule with the provided name and configuration.
|
96
116
|
#
|
97
117
|
# Note: values for class and custom_job_class need to be strings,
|
@@ -102,14 +122,11 @@ module Resque
|
|
102
122
|
# :queue => 'high',
|
103
123
|
# :args => '/tmp/poop'})
|
104
124
|
def set_schedule(name, config)
|
105
|
-
existing_config = fetch_schedule(name)
|
106
125
|
persist = config.delete(:persist) || config.delete('persist')
|
107
|
-
|
108
|
-
redis.
|
109
|
-
|
110
|
-
|
111
|
-
redis.sadd(:persisted_schedules, name) if persist
|
112
|
-
end
|
126
|
+
redis.pipelined do
|
127
|
+
redis.hset(:schedules, name, encode(config))
|
128
|
+
redis.sadd(:schedules_changed, name)
|
129
|
+
redis.sadd(:persisted_schedules, name) if persist
|
113
130
|
end
|
114
131
|
config
|
115
132
|
end
|
@@ -125,11 +142,9 @@ module Resque
|
|
125
142
|
|
126
143
|
# remove a given schedule by name
|
127
144
|
def remove_schedule(name)
|
128
|
-
redis.
|
129
|
-
|
130
|
-
|
131
|
-
redis.sadd(:schedules_changed, name)
|
132
|
-
end
|
145
|
+
redis.hdel(:schedules, name)
|
146
|
+
redis.srem(:persisted_schedules, name)
|
147
|
+
redis.sadd(:schedules_changed, name)
|
133
148
|
end
|
134
149
|
|
135
150
|
private
|
@@ -142,7 +142,7 @@ module Resque
|
|
142
142
|
dels = delayed_jobs_for_worker(worker)
|
143
143
|
results += dels.select do |j|
|
144
144
|
j['class'].downcase.include?(worker) &&
|
145
|
-
|
145
|
+
j.merge!('where_at' => 'delayed')
|
146
146
|
end
|
147
147
|
|
148
148
|
Resque.queues.each do |queue|
|
@@ -150,7 +150,7 @@ module Resque
|
|
150
150
|
queued = [queued] unless queued.is_a?(Array)
|
151
151
|
results += queued.select do |j|
|
152
152
|
j['class'].downcase.include?(worker) &&
|
153
|
-
|
153
|
+
j.merge!('queue' => queue, 'where_at' => 'queued')
|
154
154
|
end
|
155
155
|
end
|
156
156
|
|
@@ -210,7 +210,7 @@ module Resque
|
|
210
210
|
working = [*Resque.working]
|
211
211
|
work = working.select do |w|
|
212
212
|
w.job && w.job['payload'] &&
|
213
|
-
|
213
|
+
w.job['payload']['class'].downcase.include?(worker)
|
214
214
|
end
|
215
215
|
work.each do |w|
|
216
216
|
results += [
|
data/resque-scheduler.gemspec
CHANGED
@@ -10,27 +10,32 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.email = ['bvandenbos@gmail.com']
|
11
11
|
spec.homepage = 'http://github.com/resque/resque-scheduler'
|
12
12
|
spec.summary = 'Light weight job scheduling on top of Resque'
|
13
|
-
spec.description =
|
13
|
+
spec.description = <<-DESCRIPTION
|
14
|
+
Light weight job scheduling on top of Resque.
|
14
15
|
Adds methods enqueue_at/enqueue_in to schedule jobs in the future.
|
15
|
-
Also supports queueing jobs on a fixed, cron-like schedule.
|
16
|
+
Also supports queueing jobs on a fixed, cron-like schedule.
|
17
|
+
DESCRIPTION
|
16
18
|
spec.license = 'MIT'
|
17
19
|
|
18
|
-
spec.files = `git ls-files`.split("\
|
20
|
+
spec.files = `git ls-files -z`.split("\0")
|
19
21
|
spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
|
20
22
|
spec.test_files = spec.files.grep(/^test\//)
|
21
23
|
spec.require_paths = ['lib']
|
22
24
|
|
23
|
-
spec.add_development_dependency 'bundler'
|
25
|
+
spec.add_development_dependency 'bundler'
|
24
26
|
spec.add_development_dependency 'json'
|
25
27
|
spec.add_development_dependency 'kramdown'
|
26
28
|
spec.add_development_dependency 'mocha'
|
27
29
|
spec.add_development_dependency 'pry'
|
28
30
|
spec.add_development_dependency 'rack-test'
|
29
31
|
spec.add_development_dependency 'rake'
|
30
|
-
spec.add_development_dependency 'rubocop'
|
31
32
|
spec.add_development_dependency 'simplecov'
|
32
33
|
spec.add_development_dependency 'yard'
|
33
34
|
|
35
|
+
# We pin rubocop because new cops have a tendency to result in false-y
|
36
|
+
# positives for new contributors, which is not a nice experience.
|
37
|
+
spec.add_development_dependency 'rubocop', '~> 0.28.0'
|
38
|
+
|
34
39
|
spec.add_runtime_dependency 'mono_logger', '~> 1.0'
|
35
40
|
spec.add_runtime_dependency 'redis', '~> 3.0'
|
36
41
|
spec.add_runtime_dependency 'resque', '~> 1.25'
|
data/test/cli_test.rb
CHANGED
@@ -153,8 +153,8 @@ context 'Cli' do
|
|
153
153
|
end
|
154
154
|
|
155
155
|
test 'initializes logfile from the env' do
|
156
|
-
cli = new_cli([], 'LOGFILE' => '
|
157
|
-
assert_equal('
|
156
|
+
cli = new_cli([], 'LOGFILE' => 'example.log')
|
157
|
+
assert_equal('example.log', cli.send(:options)[:logfile])
|
158
158
|
end
|
159
159
|
|
160
160
|
test 'defaults to nil logfile' do
|
data/test/delayed_queue_test.rb
CHANGED
@@ -447,6 +447,75 @@ context 'DelayedQueue' do
|
|
447
447
|
assert_equal(4, Resque.count_all_scheduled_jobs)
|
448
448
|
end
|
449
449
|
|
450
|
+
test 'remove_delayed_selection ignores last_enqueued_at redis key' do
|
451
|
+
t = Time.now + 120
|
452
|
+
Resque.enqueue_at(t, SomeIvarJob)
|
453
|
+
Resque.last_enqueued_at(SomeIvarJob, t)
|
454
|
+
|
455
|
+
assert_equal(0, Resque.remove_delayed_selection { |a| a.first == 'bar' })
|
456
|
+
assert_equal(t.to_s, Resque.get_last_enqueued_at(SomeIvarJob))
|
457
|
+
end
|
458
|
+
|
459
|
+
test 'remove_delayed_selection removes item by class' do
|
460
|
+
t = Time.now + 120
|
461
|
+
Resque.enqueue_at(t, SomeIvarJob, 'foo')
|
462
|
+
Resque.enqueue_at(t, SomeQuickJob, 'foo')
|
463
|
+
|
464
|
+
assert_equal(1, Resque.remove_delayed_selection(SomeIvarJob) do |a|
|
465
|
+
a.first == 'foo'
|
466
|
+
end)
|
467
|
+
assert_equal(1, Resque.count_all_scheduled_jobs)
|
468
|
+
end
|
469
|
+
|
470
|
+
test 'remove_delayed_selection removes item by class name as a string' do
|
471
|
+
t = Time.now + 120
|
472
|
+
Resque.enqueue_at(t, SomeIvarJob, 'foo')
|
473
|
+
Resque.enqueue_at(t, SomeQuickJob, 'foo')
|
474
|
+
|
475
|
+
assert_equal(1, Resque.remove_delayed_selection('SomeIvarJob') do |a|
|
476
|
+
a.first == 'foo'
|
477
|
+
end)
|
478
|
+
assert_equal(1, Resque.count_all_scheduled_jobs)
|
479
|
+
end
|
480
|
+
|
481
|
+
test 'remove_delayed_selection removes item by class name as a symbol' do
|
482
|
+
t = Time.now + 120
|
483
|
+
Resque.enqueue_at(t, SomeIvarJob, 'foo')
|
484
|
+
Resque.enqueue_at(t, SomeQuickJob, 'foo')
|
485
|
+
|
486
|
+
assert_equal(1, Resque.remove_delayed_selection(:SomeIvarJob) do |a|
|
487
|
+
a.first == 'foo'
|
488
|
+
end)
|
489
|
+
assert_equal(1, Resque.count_all_scheduled_jobs)
|
490
|
+
end
|
491
|
+
|
492
|
+
test 'remove_delayed_selection removes items only from matching job class' do
|
493
|
+
t = Time.now + 120
|
494
|
+
Resque.enqueue_at(t, SomeIvarJob, 'foo')
|
495
|
+
Resque.enqueue_at(t, SomeQuickJob, 'foo')
|
496
|
+
Resque.enqueue_at(t + 1, SomeIvarJob, 'bar')
|
497
|
+
Resque.enqueue_at(t + 1, SomeQuickJob, 'bar')
|
498
|
+
Resque.enqueue_at(t + 1, SomeIvarJob, 'foo')
|
499
|
+
Resque.enqueue_at(t + 2, SomeQuickJob, 'foo')
|
500
|
+
|
501
|
+
assert_equal(2, Resque.remove_delayed_selection(SomeIvarJob) do |a|
|
502
|
+
a.first == 'foo'
|
503
|
+
end)
|
504
|
+
assert_equal(4, Resque.count_all_scheduled_jobs)
|
505
|
+
end
|
506
|
+
|
507
|
+
test 'remove_delayed_selection removes items from matching job class ' \
|
508
|
+
'without params' do
|
509
|
+
t = Time.now + 120
|
510
|
+
Resque.enqueue_at(t, SomeIvarJob)
|
511
|
+
Resque.enqueue_at(t + 1, SomeQuickJob)
|
512
|
+
Resque.enqueue_at(t + 2, SomeIvarJob)
|
513
|
+
Resque.enqueue_at(t + 3, SomeQuickJob)
|
514
|
+
|
515
|
+
assert_equal(2, Resque.remove_delayed_selection(SomeQuickJob) { true })
|
516
|
+
assert_equal(2, Resque.count_all_scheduled_jobs)
|
517
|
+
end
|
518
|
+
|
450
519
|
test 'remove_delayed_job_from_timestamp removes instances of jobs ' \
|
451
520
|
'at a given timestamp' do
|
452
521
|
t = Time.now + 120
|
data/test/env_test.rb
CHANGED
@@ -31,11 +31,17 @@ context 'Env' do
|
|
31
31
|
env.setup
|
32
32
|
end
|
33
33
|
|
34
|
-
test '
|
35
|
-
|
36
|
-
|
37
|
-
File.expects(:open).with('derp.pid', 'w').yields(mock_pidfile)
|
38
|
-
env = new_env(pidfile: 'derp.pid')
|
34
|
+
test 'keep set config if no option given' do
|
35
|
+
Resque::Scheduler.configure { |c| c.dynamic = true }
|
36
|
+
env = new_env
|
39
37
|
env.setup
|
38
|
+
assert_equal(true, Resque::Scheduler.dynamic)
|
39
|
+
end
|
40
|
+
|
41
|
+
test 'override config if option given' do
|
42
|
+
Resque::Scheduler.configure { |c| c.dynamic = true }
|
43
|
+
env = new_env(dynamic: false)
|
44
|
+
env.setup
|
45
|
+
assert_equal(false, Resque::Scheduler.dynamic)
|
40
46
|
end
|
41
47
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# vim:fileencoding=utf-8
|
2
|
+
require_relative 'test_helper'
|
3
|
+
|
4
|
+
context 'Multi Process' do
|
5
|
+
test 'setting schedule= from many process does not corrupt the schedules' do
|
6
|
+
schedules = {}
|
7
|
+
counts = []
|
8
|
+
threads = []
|
9
|
+
|
10
|
+
# This number may need to be increased if this test is not failing
|
11
|
+
processes = 20
|
12
|
+
|
13
|
+
schedule_count = 200
|
14
|
+
|
15
|
+
schedule_count.times do |n|
|
16
|
+
schedules["job #{n}"] = { cron: '0 1 0 0 0' }
|
17
|
+
end
|
18
|
+
|
19
|
+
processes.times do |n|
|
20
|
+
threads << Thread.new do
|
21
|
+
sleep n * 0.1
|
22
|
+
Resque.schedule = schedules
|
23
|
+
counts << Resque.schedule.size
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# doing this outside the threads increases the odds of failure
|
28
|
+
Resque.schedule = schedules
|
29
|
+
counts << Resque.schedule.size
|
30
|
+
|
31
|
+
threads.each(&:join)
|
32
|
+
|
33
|
+
counts.each_with_index do |c, i|
|
34
|
+
assert_equal schedule_count, c, "schedule count is incorrect (c: #{i})"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/test/resque-web_test.rb
CHANGED
@@ -174,17 +174,17 @@ context 'POST /schedule/requeue' do
|
|
174
174
|
assert last_response.ok?, last_response.errors
|
175
175
|
assert last_response.body.include?('This job requires parameters')
|
176
176
|
assert last_response.body.include?(
|
177
|
-
%
|
177
|
+
%(<input type="hidden" name="job_name" value="#{job_name}">)
|
178
178
|
)
|
179
179
|
|
180
180
|
Resque.schedule[job_name]['parameters'].each do |_param_name, param_config|
|
181
181
|
assert last_response.body.include?(
|
182
182
|
'<span style="border-bottom:1px dotted;" ' <<
|
183
|
-
%
|
183
|
+
%[title="#{param_config['description']}">(?)</span>]
|
184
184
|
)
|
185
185
|
assert last_response.body.include?(
|
186
186
|
'<input type="text" name="log_level" ' <<
|
187
|
-
%
|
187
|
+
%(value="#{param_config['default']}">)
|
188
188
|
)
|
189
189
|
end
|
190
190
|
end
|
@@ -225,13 +225,13 @@ context 'on POST to /delayed/search' do
|
|
225
225
|
end
|
226
226
|
|
227
227
|
test 'should find matching scheduled job' do
|
228
|
-
post '/delayed/search'
|
228
|
+
post '/delayed/search', 'search' => 'ivar'
|
229
229
|
assert last_response.status == 200
|
230
230
|
assert last_response.body.include?('SomeIvarJob')
|
231
231
|
end
|
232
232
|
|
233
233
|
test 'should find matching queued job' do
|
234
|
-
post '/delayed/search'
|
234
|
+
post '/delayed/search', 'search' => 'quick'
|
235
235
|
assert last_response.status == 200
|
236
236
|
assert last_response.body.include?('SomeQuickJob')
|
237
237
|
end
|
@@ -113,6 +113,12 @@ context 'Resque::Scheduler::Locking' do
|
|
113
113
|
end
|
114
114
|
|
115
115
|
test 'release_master_lock should delegate to master_lock' do
|
116
|
+
@subject.master_lock.expects(:release)
|
117
|
+
@subject.release_master_lock
|
118
|
+
end
|
119
|
+
|
120
|
+
test 'release_master_lock! should delegate to master_lock' do
|
121
|
+
@subject.expects(:warn)
|
116
122
|
@subject.master_lock.expects(:release!)
|
117
123
|
@subject.release_master_lock!
|
118
124
|
end
|
data/test/scheduler_task_test.rb
CHANGED
@@ -22,7 +22,7 @@ context 'Resque::Scheduler' do
|
|
22
22
|
end
|
23
23
|
|
24
24
|
test 'sending TERM to scheduler breaks out of poll_sleep' do
|
25
|
-
Resque::Scheduler.expects(:release_master_lock
|
25
|
+
Resque::Scheduler.expects(:release_master_lock)
|
26
26
|
|
27
27
|
@pid = Process.pid
|
28
28
|
Thread.new do
|
@@ -34,7 +34,7 @@ context 'Resque::Scheduler' do
|
|
34
34
|
Resque::Scheduler.run
|
35
35
|
end
|
36
36
|
|
37
|
-
Resque::Scheduler.unstub(:release_master_lock
|
38
|
-
Resque::Scheduler.release_master_lock
|
37
|
+
Resque::Scheduler.unstub(:release_master_lock)
|
38
|
+
Resque::Scheduler.release_master_lock
|
39
39
|
end
|
40
40
|
end
|
data/test/scheduler_test.rb
CHANGED
@@ -418,8 +418,8 @@ context 'Resque::Scheduler' do
|
|
418
418
|
end
|
419
419
|
|
420
420
|
test 'procline contains env when present' do
|
421
|
-
Resque::Scheduler.env = '
|
422
|
-
assert Resque::Scheduler.send(:build_procline, 'cage') =~ /\[
|
421
|
+
Resque::Scheduler.env = 'xyz'
|
422
|
+
assert Resque::Scheduler.send(:build_procline, 'cage') =~ /\[xyz\]: cage/
|
423
423
|
end
|
424
424
|
|
425
425
|
test 'procline omits env when absent' do
|
metadata
CHANGED
@@ -1,215 +1,214 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: resque-scheduler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben VandenBos
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-12-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ! '>='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ! '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: json
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ! '>='
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ! '>='
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: kramdown
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ! '>='
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ! '>='
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: mocha
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ! '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - ! '>='
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: pry
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - ! '>='
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - ! '>='
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: rack-test
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- -
|
87
|
+
- - ! '>='
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- -
|
94
|
+
- - ! '>='
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: rake
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- -
|
101
|
+
- - ! '>='
|
102
102
|
- !ruby/object:Gem::Version
|
103
103
|
version: '0'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- -
|
108
|
+
- - ! '>='
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
112
|
+
name: simplecov
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
|
-
- -
|
115
|
+
- - ! '>='
|
116
116
|
- !ruby/object:Gem::Version
|
117
117
|
version: '0'
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
|
-
- -
|
122
|
+
- - ! '>='
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
126
|
+
name: yard
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
|
-
- -
|
129
|
+
- - ! '>='
|
130
130
|
- !ruby/object:Gem::Version
|
131
131
|
version: '0'
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
|
-
- -
|
136
|
+
- - ! '>='
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '0'
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
|
-
name:
|
140
|
+
name: rubocop
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
142
142
|
requirements:
|
143
|
-
- -
|
143
|
+
- - ~>
|
144
144
|
- !ruby/object:Gem::Version
|
145
|
-
version:
|
145
|
+
version: 0.28.0
|
146
146
|
type: :development
|
147
147
|
prerelease: false
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
150
|
-
- -
|
150
|
+
- - ~>
|
151
151
|
- !ruby/object:Gem::Version
|
152
|
-
version:
|
152
|
+
version: 0.28.0
|
153
153
|
- !ruby/object:Gem::Dependency
|
154
154
|
name: mono_logger
|
155
155
|
requirement: !ruby/object:Gem::Requirement
|
156
156
|
requirements:
|
157
|
-
- -
|
157
|
+
- - ~>
|
158
158
|
- !ruby/object:Gem::Version
|
159
159
|
version: '1.0'
|
160
160
|
type: :runtime
|
161
161
|
prerelease: false
|
162
162
|
version_requirements: !ruby/object:Gem::Requirement
|
163
163
|
requirements:
|
164
|
-
- -
|
164
|
+
- - ~>
|
165
165
|
- !ruby/object:Gem::Version
|
166
166
|
version: '1.0'
|
167
167
|
- !ruby/object:Gem::Dependency
|
168
168
|
name: redis
|
169
169
|
requirement: !ruby/object:Gem::Requirement
|
170
170
|
requirements:
|
171
|
-
- -
|
171
|
+
- - ~>
|
172
172
|
- !ruby/object:Gem::Version
|
173
173
|
version: '3.0'
|
174
174
|
type: :runtime
|
175
175
|
prerelease: false
|
176
176
|
version_requirements: !ruby/object:Gem::Requirement
|
177
177
|
requirements:
|
178
|
-
- -
|
178
|
+
- - ~>
|
179
179
|
- !ruby/object:Gem::Version
|
180
180
|
version: '3.0'
|
181
181
|
- !ruby/object:Gem::Dependency
|
182
182
|
name: resque
|
183
183
|
requirement: !ruby/object:Gem::Requirement
|
184
184
|
requirements:
|
185
|
-
- -
|
185
|
+
- - ~>
|
186
186
|
- !ruby/object:Gem::Version
|
187
187
|
version: '1.25'
|
188
188
|
type: :runtime
|
189
189
|
prerelease: false
|
190
190
|
version_requirements: !ruby/object:Gem::Requirement
|
191
191
|
requirements:
|
192
|
-
- -
|
192
|
+
- - ~>
|
193
193
|
- !ruby/object:Gem::Version
|
194
194
|
version: '1.25'
|
195
195
|
- !ruby/object:Gem::Dependency
|
196
196
|
name: rufus-scheduler
|
197
197
|
requirement: !ruby/object:Gem::Requirement
|
198
198
|
requirements:
|
199
|
-
- -
|
199
|
+
- - ~>
|
200
200
|
- !ruby/object:Gem::Version
|
201
201
|
version: '2.0'
|
202
202
|
type: :runtime
|
203
203
|
prerelease: false
|
204
204
|
version_requirements: !ruby/object:Gem::Requirement
|
205
205
|
requirements:
|
206
|
-
- -
|
206
|
+
- - ~>
|
207
207
|
- !ruby/object:Gem::Version
|
208
208
|
version: '2.0'
|
209
|
-
description:
|
210
|
-
|
211
|
-
|
212
|
-
Also supports queueing jobs on a fixed, cron-like schedule.
|
209
|
+
description: ! " Light weight job scheduling on top of Resque.\n Adds methods
|
210
|
+
enqueue_at/enqueue_in to schedule jobs in the future.\n Also supports queueing
|
211
|
+
jobs on a fixed, cron-like schedule.\n"
|
213
212
|
email:
|
214
213
|
- bvandenbos@gmail.com
|
215
214
|
executables:
|
@@ -217,15 +216,15 @@ executables:
|
|
217
216
|
extensions: []
|
218
217
|
extra_rdoc_files: []
|
219
218
|
files:
|
220
|
-
-
|
221
|
-
-
|
222
|
-
-
|
223
|
-
-
|
224
|
-
-
|
225
|
-
-
|
226
|
-
-
|
227
|
-
-
|
228
|
-
-
|
219
|
+
- .gitignore
|
220
|
+
- .rubocop.yml
|
221
|
+
- .rubocop_todo.yml
|
222
|
+
- .simplecov
|
223
|
+
- .travis.yml
|
224
|
+
- .vagrant-provision-as-vagrant.sh
|
225
|
+
- .vagrant-provision.sh
|
226
|
+
- .vagrant-skel/bash_profile
|
227
|
+
- .vagrant-skel/bashrc
|
229
228
|
- AUTHORS.md
|
230
229
|
- CONTRIBUTING.md
|
231
230
|
- Gemfile
|
@@ -279,6 +278,7 @@ files:
|
|
279
278
|
- test/cli_test.rb
|
280
279
|
- test/delayed_queue_test.rb
|
281
280
|
- test/env_test.rb
|
281
|
+
- test/multi_process_test.rb
|
282
282
|
- test/resque-web_test.rb
|
283
283
|
- test/scheduler_args_test.rb
|
284
284
|
- test/scheduler_hooks_test.rb
|
@@ -299,17 +299,17 @@ require_paths:
|
|
299
299
|
- lib
|
300
300
|
required_ruby_version: !ruby/object:Gem::Requirement
|
301
301
|
requirements:
|
302
|
-
- -
|
302
|
+
- - ! '>='
|
303
303
|
- !ruby/object:Gem::Version
|
304
304
|
version: '0'
|
305
305
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
306
306
|
requirements:
|
307
|
-
- -
|
307
|
+
- - ! '>='
|
308
308
|
- !ruby/object:Gem::Version
|
309
309
|
version: '0'
|
310
310
|
requirements: []
|
311
311
|
rubyforge_project:
|
312
|
-
rubygems_version: 2.
|
312
|
+
rubygems_version: 2.4.5
|
313
313
|
signing_key:
|
314
314
|
specification_version: 4
|
315
315
|
summary: Light weight job scheduling on top of Resque
|
@@ -317,6 +317,7 @@ test_files:
|
|
317
317
|
- test/cli_test.rb
|
318
318
|
- test/delayed_queue_test.rb
|
319
319
|
- test/env_test.rb
|
320
|
+
- test/multi_process_test.rb
|
320
321
|
- test/resque-web_test.rb
|
321
322
|
- test/scheduler_args_test.rb
|
322
323
|
- test/scheduler_hooks_test.rb
|
@@ -327,4 +328,3 @@ test_files:
|
|
327
328
|
- test/support/redis_instance.rb
|
328
329
|
- test/test_helper.rb
|
329
330
|
- test/util_test.rb
|
330
|
-
has_rdoc:
|