resque-scheduler 1.9.10 → 2.0.0.a
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of resque-scheduler might be problematic. Click here for more details.
- data/.gitignore +0 -3
- data/Gemfile +1 -2
- data/Gemfile.lock +52 -0
- data/HISTORY.md +3 -14
- data/README.markdown +98 -44
- data/Rakefile +3 -31
- data/lib/resque/scheduler.rb +98 -42
- data/lib/resque_scheduler.rb +48 -34
- data/lib/resque_scheduler/server.rb +8 -7
- data/lib/resque_scheduler/server/views/delayed.erb +3 -3
- data/lib/resque_scheduler/server/views/scheduler.erb +4 -4
- data/lib/resque_scheduler/tasks.rb +1 -1
- data/lib/resque_scheduler/version.rb +1 -1
- data/resque-scheduler.gemspec +23 -26
- data/test/delayed_queue_test.rb +5 -41
- data/test/redis-test.conf +1 -1
- data/test/resque-web_test.rb +2 -3
- data/test/scheduler_args_test.rb +1 -1
- data/test/scheduler_test.rb +159 -6
- data/test/test_helper.rb +8 -8
- metadata +121 -139
- checksums.yaml +0 -7
- data/.rubocop.yml +0 -120
- data/.travis.yml +0 -10
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
resque-scheduler (1.9.7)
|
5
|
+
redis (>= 2.0.1)
|
6
|
+
resque (>= 1.8.0)
|
7
|
+
rufus-scheduler
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: http://rubygems.org/
|
11
|
+
specs:
|
12
|
+
git (1.2.5)
|
13
|
+
jeweler (1.5.1)
|
14
|
+
bundler (~> 1.0.0)
|
15
|
+
git (>= 1.2.5)
|
16
|
+
rake
|
17
|
+
json (1.4.6)
|
18
|
+
mocha (0.9.9)
|
19
|
+
rake
|
20
|
+
rack (1.2.1)
|
21
|
+
rack-test (0.5.6)
|
22
|
+
rack (>= 1.0)
|
23
|
+
rake (0.8.7)
|
24
|
+
redis (2.1.1)
|
25
|
+
redis-namespace (0.8.0)
|
26
|
+
redis (< 3.0.0)
|
27
|
+
resque (1.10.0)
|
28
|
+
json (~> 1.4.6)
|
29
|
+
redis-namespace (~> 0.8.0)
|
30
|
+
sinatra (>= 0.9.2)
|
31
|
+
vegas (~> 0.1.2)
|
32
|
+
rufus-scheduler (2.0.7)
|
33
|
+
tzinfo
|
34
|
+
sinatra (1.1.0)
|
35
|
+
rack (~> 1.1)
|
36
|
+
tilt (~> 1.1)
|
37
|
+
tilt (1.1)
|
38
|
+
tzinfo (0.3.23)
|
39
|
+
vegas (0.1.8)
|
40
|
+
rack (>= 1.0.0)
|
41
|
+
|
42
|
+
PLATFORMS
|
43
|
+
ruby
|
44
|
+
|
45
|
+
DEPENDENCIES
|
46
|
+
jeweler
|
47
|
+
mocha
|
48
|
+
rack-test
|
49
|
+
redis (>= 2.0.1)
|
50
|
+
resque (>= 1.8.0)
|
51
|
+
resque-scheduler!
|
52
|
+
rufus-scheduler
|
data/HISTORY.md
CHANGED
@@ -1,18 +1,7 @@
|
|
1
|
-
##
|
1
|
+
## 2.0.0 (???)
|
2
2
|
|
3
|
-
*
|
4
|
-
*
|
5
|
-
* Mocha setup compatibility
|
6
|
-
* Ruby 1.8 compatibility in scheduler tab when schedule keys are symbols
|
7
|
-
|
8
|
-
## 1.9.9 (2011-03-29)
|
9
|
-
|
10
|
-
* Compatibility with resque 1.15.0
|
11
|
-
|
12
|
-
## 1.9.8 (???)
|
13
|
-
|
14
|
-
* Validates delayed jobs prior to insertion into the delayed queue (bogdan)
|
15
|
-
* Rescue exceptions that occur during queuing and log them (dgrijalva)
|
3
|
+
* Dynamic schedule support (brianjlandau, davidyang)
|
4
|
+
* Now depends on redis >=1.3
|
16
5
|
|
17
6
|
## 1.9.7 (2010-11-09)
|
18
7
|
|
data/README.markdown
CHANGED
@@ -4,7 +4,7 @@ resque-scheduler
|
|
4
4
|
Resque-scheduler is an extension to [Resque](http://github.com/defunkt/resque)
|
5
5
|
that adds support for queueing items in the future.
|
6
6
|
|
7
|
-
Requires redis >=1.
|
7
|
+
Requires redis >=1.3.
|
8
8
|
|
9
9
|
|
10
10
|
Job scheduling is supported in two different way:
|
@@ -30,9 +30,9 @@ is most likely stored in a YAML like so:
|
|
30
30
|
args: contributors
|
31
31
|
description: "This job resets the weekly leaderboard for contributions"
|
32
32
|
|
33
|
-
A queue option can also be specified.
|
34
|
-
if it is available (Even if @queue is specified in the job class). When
|
35
|
-
queue is given it is not necessary for the scheduler to load the class.
|
33
|
+
A queue option can also be specified. Then the job will go onto the specified
|
34
|
+
queue if it is available (Even if @queue is specified in the job class). When
|
35
|
+
the queue is given it is not necessary for the scheduler to load the class.
|
36
36
|
|
37
37
|
clear_leaderboards_moderator:
|
38
38
|
cron: "30 6 * * 1"
|
@@ -95,6 +95,86 @@ If you have the need to cancel a delayed job, you can do so thusly:
|
|
95
95
|
# remove the job with exactly the same parameters:
|
96
96
|
Resque.remove_delayed(SendFollowUpEmail, :user_id => current_user.id)
|
97
97
|
|
98
|
+
|
99
|
+
### Dynamic Schedules
|
100
|
+
|
101
|
+
If needed you can also have recurring jobs (scheduled) that are dynamically
|
102
|
+
defined and updated inside of your application. A good example is if you want
|
103
|
+
to allow users to configured when a report is automatically generated. This
|
104
|
+
can be completed by loading the schedule initially wherever you configure
|
105
|
+
Resque and setting `Resque::Scheduler.dynamic` to `true`. Then subsequently
|
106
|
+
updating the "`schedules`" key in redis, namespaced to the Resque namespace.
|
107
|
+
The "`schedules`" key is expected to be a redis hash data type, where the key
|
108
|
+
is the name of the schedule and the value is a JSON encoded hash of the
|
109
|
+
schedule configuration. There are methods on Resque to make this easy (see
|
110
|
+
below).
|
111
|
+
|
112
|
+
When the scheduler loops it will look for differences between the existing
|
113
|
+
schedule and the current schedule in redis. If there are differences it will
|
114
|
+
make the necessary changes to the running schedule. The schedule names that
|
115
|
+
need to be changed are stored in the `schedules_changed` set in redis.
|
116
|
+
|
117
|
+
To force the scheduler to reload the schedule you just send it the `USR2`
|
118
|
+
signal. This will force a complete schedule reload (unscheduling and
|
119
|
+
rescheduling everything).
|
120
|
+
|
121
|
+
To add/update, delete, and retrieve individual schedule items you should
|
122
|
+
use the provided API methods:
|
123
|
+
|
124
|
+
* `Resque.set_schedule(name, config)`
|
125
|
+
* `Resque.get_schedule(name)`
|
126
|
+
* `Resque.remove_schedule(name)`
|
127
|
+
|
128
|
+
For example:
|
129
|
+
|
130
|
+
Resque.set_schedule("create_fake_leaderboards", {
|
131
|
+
:cron => "30 6 * * 1",
|
132
|
+
:class => "CreateFakeLeaderboards",
|
133
|
+
:queue => scoring
|
134
|
+
})
|
135
|
+
|
136
|
+
In this way, it's possible to completely configure your scheduled jobs from
|
137
|
+
inside your app if you so desire.
|
138
|
+
|
139
|
+
### Support for customized Job classes
|
140
|
+
|
141
|
+
Some Resque extensions like
|
142
|
+
[resque-status](http://github.com/quirkey/resque-status) use custom job
|
143
|
+
classes with a slightly different API signature. Resque-scheduler isn't
|
144
|
+
trying to support all existing and future custom job classes, instead it
|
145
|
+
supports a schedule flag so you can extend your custom class and make it
|
146
|
+
support scheduled job.
|
147
|
+
|
148
|
+
Let's pretend we have a JobWithStatus class called FakeLeaderboard
|
149
|
+
|
150
|
+
class FakeLeaderboard < Resque::JobWithStatus
|
151
|
+
def perform
|
152
|
+
# do something and keep track of the status
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
create_fake_leaderboards:
|
157
|
+
cron: "30 6 * * 1"
|
158
|
+
queue: scoring
|
159
|
+
custom_job_class: FakeLeaderboard
|
160
|
+
args:
|
161
|
+
rails_env: demo
|
162
|
+
description: "This job will auto-create leaderboards for our online demo and the status will update as the worker makes progress"
|
163
|
+
|
164
|
+
If your extension doesn't support scheduled job, you would need to extend the
|
165
|
+
custom job class to support the #scheduled method:
|
166
|
+
|
167
|
+
module Resque
|
168
|
+
class JobWithStatus
|
169
|
+
# Wrapper API to forward a Resque::Job creation API call into
|
170
|
+
# a JobWithStatus call.
|
171
|
+
def self.scheduled(queue, klass, *args)
|
172
|
+
create(args)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
|
98
178
|
### Schedule jobs per environment
|
99
179
|
|
100
180
|
Resque-Scheduler allows to create schedule jobs for specific envs. The arg
|
@@ -138,39 +218,6 @@ Multiple envs are allowed, separated by commas:
|
|
138
218
|
NOTE: If you specify the `rails_env` arg without setting RAILS_ENV as an
|
139
219
|
environment variable, the job won't be loaded.
|
140
220
|
|
141
|
-
### Support for customized Job classes
|
142
|
-
|
143
|
-
Some Resque extensions like [resque-status](http://github.com/quirkey/resque-status) use custom job classes with a slightly different API signature.
|
144
|
-
Resque-scheduler isn't trying to support all existing and future custom job classes, instead it supports a schedule flag so you can extend your custom class
|
145
|
-
and make it support scheduled job.
|
146
|
-
|
147
|
-
Let's pretend we have a JobWithStatus class called FakeLeaderboard
|
148
|
-
|
149
|
-
class FakeLeaderboard < Resque::JobWithStatus
|
150
|
-
def perform
|
151
|
-
# do something and keep track of the status
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
create_fake_leaderboards:
|
156
|
-
cron: "30 6 * * 1"
|
157
|
-
queue: scoring
|
158
|
-
custom_job_class: FakeLeaderboard
|
159
|
-
args:
|
160
|
-
rails_env: demo
|
161
|
-
description: "This job will auto-create leaderboards for our online demo and the status will update as the worker makes progress"
|
162
|
-
|
163
|
-
If your extension doesn't support scheduled job, you would need to extend the custom job class to support the #scheduled method:
|
164
|
-
|
165
|
-
module Resque
|
166
|
-
class JobWithStatus
|
167
|
-
# Wrapper API to forward a Resque::Job creation API call into a JobWithStatus call.
|
168
|
-
def self.scheduled(queue, klass, *args)
|
169
|
-
create(args)
|
170
|
-
end
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
221
|
|
175
222
|
Resque-web additions
|
176
223
|
--------------------
|
@@ -188,8 +235,8 @@ The Delayed tab:
|
|
188
235
|
![The Delayed Tab](http://img.skitch.com/20100111-ne4fcqtc5emkcuwc5qtais2kwx.jpg)
|
189
236
|
|
190
237
|
Get get these to show up you need to pass a file to `resque-web` to tell it to
|
191
|
-
include the `resque-scheduler` plugin. You probably already have a file
|
192
|
-
where you configure `resque`. It probably looks something like this:
|
238
|
+
include the `resque-scheduler` plugin. You probably already have a file
|
239
|
+
somewhere where you configure `resque`. It probably looks something like this:
|
193
240
|
|
194
241
|
require 'resque' # include resque so we can configure it
|
195
242
|
Resque.redis = "redis_server:6379" # tell Resque where redis lives
|
@@ -198,7 +245,10 @@ Now, you want to add the following:
|
|
198
245
|
|
199
246
|
require 'resque_scheduler' # include the resque_scheduler (this makes the tabs show up)
|
200
247
|
|
201
|
-
|
248
|
+
As of resque-scheduler 2.0, it's no longer necessary to have the resque-web
|
249
|
+
process aware of the schedule because it reads it from redis. But prior to
|
250
|
+
2.0, you'll want to make sure you load the schedule in this file as well.
|
251
|
+
Something like this:
|
202
252
|
|
203
253
|
Resque.schedule = YAML.load_file(File.join(RAILS_ROOT, 'config/resque_schedule.yml')) # load the schedule
|
204
254
|
|
@@ -209,7 +259,6 @@ Now make sure you're passing that file to resque-web like so:
|
|
209
259
|
That should make the scheduler tabs show up in `resque-web`.
|
210
260
|
|
211
261
|
|
212
|
-
|
213
262
|
Installation and the Scheduler process
|
214
263
|
--------------------------------------
|
215
264
|
|
@@ -217,10 +266,15 @@ To install:
|
|
217
266
|
|
218
267
|
gem install resque-scheduler
|
219
268
|
|
220
|
-
|
269
|
+
The unless you specify the `queue` for each scheduled job, the scheduler
|
270
|
+
needs to know about your job classes (so it can put them into the appropriate
|
271
|
+
queue). To do so, extend the "resque:scheduler_setup" to load your app's code.
|
272
|
+
In rails, it would look something like this:
|
221
273
|
|
222
274
|
require 'resque_scheduler/tasks'
|
223
|
-
task "resque:
|
275
|
+
task "resque:scheduler_setup" => :environment # load the env so we know about the job classes
|
276
|
+
|
277
|
+
By default, "resque:scheduler_setup" invokes "resque:setup".
|
224
278
|
|
225
279
|
The scheduler process is just a rake task which is responsible for both queueing
|
226
280
|
items from the schedule and polling the delayed queue for items ready to be
|
@@ -230,7 +284,7 @@ pushed on to the work queues. For obvious reasons, this process never exits.
|
|
230
284
|
|
231
285
|
Supported environment variables are `VERBOSE` and `MUTE`. If either is set to
|
232
286
|
any nonempty value, they will take effect. `VERBOSE` simply dumps more output
|
233
|
-
to stdout. `MUTE` does the opposite and silences all output. `MUTE`
|
287
|
+
to stdout. `MUTE` does the opposite and silences all output. `MUTE` supersedes
|
234
288
|
`VERBOSE`.
|
235
289
|
|
236
290
|
NOTE: You DO NOT want to run >1 instance of the scheduler. Doing so will result
|
data/Rakefile
CHANGED
@@ -1,41 +1,13 @@
|
|
1
|
-
require 'bundler
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
2
3
|
|
3
4
|
$LOAD_PATH.unshift 'lib'
|
4
5
|
|
5
6
|
task :default => :test
|
6
7
|
|
7
|
-
desc
|
8
|
+
desc "Run tests"
|
8
9
|
task :test do
|
9
|
-
if RUBY_VERSION =~ /^1\.8/
|
10
|
-
unless ENV['SEED']
|
11
|
-
srand
|
12
|
-
ENV['SEED'] = (srand % 0xFFFF).to_s
|
13
|
-
end
|
14
|
-
|
15
|
-
$stdout.puts "Running with SEED=#{ENV['SEED']}"
|
16
|
-
srand Integer(ENV['SEED'])
|
17
|
-
elsif ENV['SEED']
|
18
|
-
ARGV += %W(--seed #{ENV['SEED']})
|
19
|
-
end
|
20
10
|
Dir['test/*_test.rb'].each do |f|
|
21
11
|
require File.expand_path(f)
|
22
12
|
end
|
23
13
|
end
|
24
|
-
|
25
|
-
desc 'Run rubocop'
|
26
|
-
task :rubocop do
|
27
|
-
unless RUBY_VERSION < '1.9'
|
28
|
-
sh('rubocop --config .rubocop.yml --format simple') { |r, _| r || abort }
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
begin
|
33
|
-
require 'rdoc/task'
|
34
|
-
|
35
|
-
Rake::RDocTask.new do |rd|
|
36
|
-
rd.main = 'README.md'
|
37
|
-
rd.rdoc_files.include('README.md', 'lib/**/*.rb')
|
38
|
-
rd.rdoc_dir = 'doc'
|
39
|
-
end
|
40
|
-
rescue LoadError
|
41
|
-
end
|
data/lib/resque/scheduler.rb
CHANGED
@@ -11,22 +11,32 @@ module Resque
|
|
11
11
|
|
12
12
|
# If true, logs more stuff...
|
13
13
|
attr_accessor :verbose
|
14
|
-
|
14
|
+
|
15
15
|
# If set, produces no output
|
16
16
|
attr_accessor :mute
|
17
|
+
|
18
|
+
# If set, will try to update the schulde in the loop
|
19
|
+
attr_accessor :dynamic
|
20
|
+
|
21
|
+
# the Rufus::Scheduler jobs that are scheduled
|
22
|
+
def scheduled_jobs
|
23
|
+
@@scheduled_jobs
|
24
|
+
end
|
17
25
|
|
18
26
|
# Schedule all jobs and continually look for delayed jobs (never returns)
|
19
27
|
def run
|
20
|
-
|
28
|
+
$0 = "resque-scheduler: Starting"
|
21
29
|
# trap signals
|
22
30
|
register_signal_handlers
|
23
31
|
|
24
32
|
# Load the schedule into rufus
|
33
|
+
procline "Loading Schedule"
|
25
34
|
load_schedule!
|
26
35
|
|
27
36
|
# Now start the scheduling part of the loop.
|
28
37
|
loop do
|
29
38
|
handle_delayed_items
|
39
|
+
update_schedule if dynamic
|
30
40
|
poll_sleep
|
31
41
|
end
|
32
42
|
|
@@ -39,12 +49,13 @@ module Resque
|
|
39
49
|
def register_signal_handlers
|
40
50
|
trap("TERM") { shutdown }
|
41
51
|
trap("INT") { shutdown }
|
42
|
-
|
52
|
+
|
43
53
|
begin
|
44
54
|
trap('QUIT') { shutdown }
|
45
55
|
trap('USR1') { kill_child }
|
56
|
+
trap('USR2') { reload_schedule! }
|
46
57
|
rescue ArgumentError
|
47
|
-
warn "Signals QUIT and USR1 not supported."
|
58
|
+
warn "Signals QUIT and USR1 and USR2 not supported."
|
48
59
|
end
|
49
60
|
end
|
50
61
|
|
@@ -52,29 +63,42 @@ module Resque
|
|
52
63
|
# rufus scheduler instance
|
53
64
|
def load_schedule!
|
54
65
|
log! "Schedule empty! Set Resque.schedule" if Resque.schedule.empty?
|
55
|
-
|
66
|
+
|
67
|
+
@@scheduled_jobs = {}
|
68
|
+
|
56
69
|
Resque.schedule.each do |name, config|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
70
|
+
load_schedule_job(name, config)
|
71
|
+
end
|
72
|
+
Resque.redis.del(:schedules_changed)
|
73
|
+
procline "Schedules Loaded"
|
74
|
+
end
|
75
|
+
|
76
|
+
# Loads a job schedule into the Rufus::Scheduler and stores it in @@scheduled_jobs
|
77
|
+
def load_schedule_job(name, config)
|
78
|
+
# If rails_env is set in the config, enforce ENV['RAILS_ENV'] as
|
79
|
+
# required for the jobs to be scheduled. If rails_env is missing, the
|
80
|
+
# job should be scheduled regardless of what ENV['RAILS_ENV'] is set
|
81
|
+
# to.
|
82
|
+
if config['rails_env'].nil? || rails_env_matches?(config)
|
83
|
+
log! "Scheduling #{name} "
|
84
|
+
interval_defined = false
|
85
|
+
interval_types = %w{cron every}
|
86
|
+
interval_types.each do |interval_type|
|
87
|
+
if !config[interval_type].nil? && config[interval_type].length > 0
|
88
|
+
begin
|
89
|
+
@@scheduled_jobs[name] = rufus_scheduler.send(interval_type, config[interval_type]) do
|
68
90
|
log! "queueing #{config['class']} (#{name})"
|
69
91
|
enqueue_from_config(config)
|
70
92
|
end
|
71
|
-
|
72
|
-
|
93
|
+
rescue Exception => e
|
94
|
+
log! "#{e.class.name}: #{e.message}"
|
73
95
|
end
|
96
|
+
interval_defined = true
|
97
|
+
break
|
74
98
|
end
|
75
|
-
|
76
|
-
|
77
|
-
|
99
|
+
end
|
100
|
+
unless interval_defined
|
101
|
+
log! "no #{interval_types.join(' / ')} found for #{config['class']} (#{name}) - skipping"
|
78
102
|
end
|
79
103
|
end
|
80
104
|
end
|
@@ -88,33 +112,30 @@ module Resque
|
|
88
112
|
# Handles queueing delayed items
|
89
113
|
# at_time - Time to start scheduling items (default: now).
|
90
114
|
def handle_delayed_items(at_time=nil)
|
91
|
-
|
92
|
-
|
93
|
-
|
115
|
+
item = nil
|
116
|
+
if timestamp = Resque.next_delayed_timestamp(at_time)
|
117
|
+
procline "Processing Delayed Items"
|
118
|
+
while !timestamp.nil?
|
94
119
|
enqueue_delayed_items_for_timestamp(timestamp)
|
120
|
+
timestamp = Resque.next_delayed_timestamp(at_time)
|
95
121
|
end
|
96
|
-
|
97
|
-
end while !timestamp.nil?
|
122
|
+
end
|
98
123
|
end
|
99
|
-
|
124
|
+
|
100
125
|
# Enqueues all delayed jobs for a timestamp
|
101
126
|
def enqueue_delayed_items_for_timestamp(timestamp)
|
102
127
|
item = nil
|
103
128
|
begin
|
104
129
|
handle_shutdown do
|
105
130
|
if item = Resque.next_item_for_timestamp(timestamp)
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
Resque::Job.create(queue, item['class'], *item['args'])
|
115
|
-
end
|
116
|
-
rescue
|
117
|
-
log! "Failed to enqueue #{klass_name}:\n #{$!}"
|
131
|
+
log "queuing #{item['class']} [delayed]"
|
132
|
+
queue = item['queue'] || Resque.queue_from_class(constantize(item['class']))
|
133
|
+
# Support custom job classes like job with status
|
134
|
+
if (job_klass = item['custom_job_class']) && (job_klass != 'Resque::Job')
|
135
|
+
# custom job classes not supporting the same API calls must implement the #schedule method
|
136
|
+
constantize(job_klass).scheduled(queue, item['class'], *item['args'])
|
137
|
+
else
|
138
|
+
Resque::Job.create(queue, item['class'], *item['args'])
|
118
139
|
end
|
119
140
|
end
|
120
141
|
end
|
@@ -140,9 +161,7 @@ module Resque
|
|
140
161
|
constantize(job_klass).scheduled(queue, klass_name, *params)
|
141
162
|
else
|
142
163
|
Resque::Job.create(queue, klass_name, *params)
|
143
|
-
end
|
144
|
-
rescue
|
145
|
-
log! "Failed to enqueue #{klass_name}:\n #{$!}"
|
164
|
+
end
|
146
165
|
end
|
147
166
|
|
148
167
|
def rufus_scheduler
|
@@ -154,8 +173,40 @@ module Resque
|
|
154
173
|
def clear_schedule!
|
155
174
|
rufus_scheduler.stop
|
156
175
|
@rufus_scheduler = nil
|
176
|
+
@@scheduled_jobs = {}
|
157
177
|
rufus_scheduler
|
158
178
|
end
|
179
|
+
|
180
|
+
def reload_schedule!
|
181
|
+
procline "Reloading Schedule"
|
182
|
+
clear_schedule!
|
183
|
+
Resque.reload_schedule!
|
184
|
+
load_schedule!
|
185
|
+
end
|
186
|
+
|
187
|
+
def update_schedule
|
188
|
+
if Resque.redis.scard(:schedules_changed) > 0
|
189
|
+
procline "Updating schedule"
|
190
|
+
Resque.reload_schedule!
|
191
|
+
while schedule_name = Resque.redis.spop(:schedules_changed)
|
192
|
+
if Resque.schedule.keys.include?(schedule_name)
|
193
|
+
unschedule_job(schedule_name)
|
194
|
+
load_schedule_job(schedule_name, Resque.schedule[schedule_name])
|
195
|
+
else
|
196
|
+
unschedule_job(schedule_name)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
procline "Schedules Loaded"
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def unschedule_job(name)
|
204
|
+
if scheduled_jobs[name]
|
205
|
+
log "Removing schedule #{name}"
|
206
|
+
scheduled_jobs[name].unschedule
|
207
|
+
@@scheduled_jobs.delete(name)
|
208
|
+
end
|
209
|
+
end
|
159
210
|
|
160
211
|
# Sleeps and returns true
|
161
212
|
def poll_sleep
|
@@ -179,6 +230,11 @@ module Resque
|
|
179
230
|
# add "verbose" logic later
|
180
231
|
log!(msg) if verbose
|
181
232
|
end
|
233
|
+
|
234
|
+
def procline(string)
|
235
|
+
$0 = "resque-scheduler-#{ResqueScheduler::Version}: #{string}"
|
236
|
+
log! $0
|
237
|
+
end
|
182
238
|
|
183
239
|
end
|
184
240
|
|