nogara-resque-scheduler 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ .bundle/
2
+ doc/
3
+ pkg
4
+ nbproject
5
+ Gemfile.lock
6
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source :rubygems
2
+ gemspec
3
+
4
+ group :test do
5
+ gem "rake"
6
+ gem "rack-test"
7
+ gem "yajl-ruby", "~>0.8.2", :platforms => :mri
8
+ gem "mocha"
9
+ end
data/HISTORY.md ADDED
@@ -0,0 +1,135 @@
1
+ ## 2.0.0
2
+
3
+ * Add support for Resque.inline configuration (carlosantoniodasilva)
4
+ * Fixing possible job loss race condition around deleting delayed queues
5
+ and enqueuing a job 0 seconds in the future.
6
+
7
+ ### 2.0.0.h (2012-03-19)
8
+
9
+ * Adding plugin support with hooks (andreas)
10
+
11
+ ### 2.0.0.f (2011-11-03)
12
+
13
+ * TODO: address race condition with delayed jobs (using redis transactions)
14
+ * Support ENV['BACKGROUND'] flag for daemonizing (bernerdschaefer)
15
+ * Added support for before_schedule and after_schedule hooks (yaauie)
16
+ * Added remove_delayed_job_from_timestamp to remove delayed jobs from
17
+ a given timestamp.
18
+
19
+ ### 2.0.0.e (2011-09-16)
20
+
21
+ * Adding enqueue_at_with_queue/enqueue_in_with_queue support (niralisse)
22
+ * Adding `Resque::Scheduler.poll_sleep_amount` to allow for configuring
23
+ the sleep time b/w delayed queue polls.
24
+ * Add a "Clear Delayed Jobs" button to the Delayed Jobs page (john-griffin)
25
+ * Fixed pagination issue on the Delayed tab
26
+
27
+ ### 2.0.0.d (2011-04-04)
28
+
29
+ * porting bug fixes from v1.9-stable
30
+
31
+ ### 2.0.0.c
32
+
33
+ * Rake task drop a pid file (sreeix)
34
+
35
+ ### 2.0.0.b
36
+
37
+ * Bug fixes
38
+
39
+ ### 2.0.0.a
40
+
41
+ * Dynamic schedule support (brianjlandau, davidyang)
42
+ * Now depends on redis >=1.3
43
+
44
+ ## 1.9.9 (2011-03-29)
45
+
46
+ * Compatibility with resque 1.15.0
47
+
48
+ ## 1.9.8 (???)
49
+
50
+ * Validates delayed jobs prior to insertion into the delayed queue (bogdan)
51
+ * Rescue exceptions that occur during queuing and log them (dgrijalva)
52
+
53
+ ## 1.9.7 (2010-11-09)
54
+
55
+ * Support for rufus-scheduler "every" syntax (fallwith)
56
+ * Ability to pass a Time to handle_delayed_items for testing/staging (rcarver)
57
+
58
+ ## 1.9.6 (2010-10-08)
59
+
60
+ * Support for custom job classes (like resque-status) (mattetti)
61
+
62
+ ## 1.9.5 (2010-09-09)
63
+
64
+ * Updated scheduler rake task to allow for an alternate setup task
65
+ to avoid loading the entire stack. (chewbranca)
66
+ * Fixed sig issue on win32 (#25)
67
+
68
+ ## 1.9.4 (2010-07-29)
69
+
70
+ * Adding ability to remove jobs from delayed queue (joshsz)
71
+ * Fixing issue #23 (removing .present? reference)
72
+
73
+ ## 1.9.3 (2010-07-07)
74
+
75
+ * Bug fix (#19)
76
+
77
+ ## 1.9.2 (2010-06-16)
78
+
79
+ * Fixing issue with redis gem 2.0.1 and redis server 1.2.6 (dbackeus)
80
+
81
+ ## 1.9.1 (2010-06-04)
82
+
83
+ * Fixing issue with redis server 1.2.6 and redis gem 2.0.1
84
+
85
+ ## 1.9.0 (2010-06-04)
86
+
87
+ * Adding redis 2.0 support (bpo)
88
+
89
+ ## 1.8.2 (2010-06-04)
90
+
91
+ * Adding queue now functionality to delayed timestamps (daviddoan)
92
+
93
+ ## 1.8.1 (2010-05-19)
94
+
95
+ * Adding rails_env for scheduled jobs to support scoping jobs by
96
+ RAILS_ENV (gravis).
97
+ * Fixing ruby 1.8.6 compatibility issue.
98
+ * Adding gemspec for bundler support.
99
+
100
+ ## 1.8.0 (2010-04-14)
101
+
102
+ * Moving version to match corresponding resque version
103
+ * Sorting schedule on Scheduler tab
104
+ * Adding tests for resque-web (gravis)
105
+
106
+ ## 1.0.5 (2010-03-01)
107
+
108
+ * Fixed support for overriding queue from schedule config.
109
+ * Removed resque-web dependency on loading the job classes for "Queue Now",
110
+ provided "queue" is specified in the schedule.
111
+ * The queue is now stored with the job and arguments in the delayed queue so
112
+ there is no longer a need for the scheduler to load job classes to introspect
113
+ the queue.
114
+
115
+ ## 1.0.4 (2010-02-26)
116
+
117
+ * Added support for specifying the queue to put the job onto. This allows for
118
+ you to have one job that can go onto multiple queues and be able to schedule
119
+ jobs without having to load the job classes.
120
+
121
+ ## 1.0.3 (2010-02-11)
122
+
123
+ * Added support for scheduled jobs with empty crons. This is helpful to have
124
+ jobs that you don't want on a schedule, but do want to be able to queue by
125
+ clicking a button.
126
+
127
+ ## 1.0.2 (2010-02-?)
128
+
129
+ * Change Delayed Job tab to display job details if only 1 job exists
130
+ for a given timestamp
131
+
132
+ ## 1.0.1 (2010-01-?)
133
+
134
+ * Bugfix: delayed jobs close together resulted in a 5 second sleep
135
+
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2010 Ben VandenBos
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
data/README.markdown ADDED
@@ -0,0 +1,354 @@
1
+ resque-scheduler
2
+ ================
3
+
4
+ ### Description
5
+
6
+ Resque-scheduler is an extension to [Resque](http://github.com/defunkt/resque)
7
+ that adds support for queueing items in the future.
8
+
9
+ This table explains the version requirements for redis
10
+
11
+ | resque-scheduler version | required redis version|
12
+ |:-------------------------|----------------------:|
13
+ | >= 2.0.0 | >= 2.2.0 |
14
+ | >= 0.0.1 | >= 1.3 |
15
+
16
+
17
+ Job scheduling is supported in two different way: Recurring (scheduled) and
18
+ Delayed.
19
+
20
+ Scheduled jobs are like cron jobs, recurring on a regular basis. Delayed
21
+ jobs are resque jobs that you want to run at some point in the future.
22
+ The syntax is pretty explanatory:
23
+
24
+ Resque.enqueue_in(5.days, SendFollowupEmail) # run a job in 5 days
25
+ # or
26
+ Resque.enqueue_at(5.days.from_now, SomeJob) # run SomeJob at a specific time
27
+
28
+ ### Documentation
29
+
30
+ This README covers what most people need to know. If you're looking for
31
+ details on individual methods, you might want to try the [rdoc](http://rdoc.info/github/bvandenbos/resque-scheduler/master/frames).
32
+
33
+ ### Installation
34
+
35
+ To install:
36
+
37
+ gem install resque-scheduler
38
+
39
+ If you use a Gemfile, you may want to specify the `:require` explicitly:
40
+
41
+ gem 'resque-scheduler', :require => 'resque_scheduler'
42
+
43
+ Adding the resque:scheduler rake task:
44
+
45
+ require 'resque_scheduler/tasks'
46
+
47
+ There are three things `resque-scheduler` needs to know about in order to do
48
+ it's jobs: the schedule, where redis lives, and which queues to use. The
49
+ easiest way to configure these things is via the rake task. By default,
50
+ `resque-scheduler` depends on the "resque:setup" rake task. Since you
51
+ probably already have this task, lets just put our configuration there.
52
+ `resque-scheduler` pretty much needs to know everything `resque` needs
53
+ to know.
54
+
55
+
56
+ # Resque tasks
57
+ require 'resque/tasks'
58
+ require 'resque_scheduler/tasks'
59
+
60
+ namespace :resque do
61
+ task :setup do
62
+ require 'resque'
63
+ require 'resque_scheduler'
64
+ require 'resque/scheduler'
65
+
66
+ # you probably already have this somewhere
67
+ Resque.redis = 'localhost:6379'
68
+
69
+ # If you want to be able to dynamically change the schedule,
70
+ # uncomment this line. A dynamic schedule can be updated via the
71
+ # Resque::Scheduler.set_schedule (and remove_schedule) methods.
72
+ # When dynamic is set to true, the scheduler process looks for
73
+ # schedule changes and applies them on the fly.
74
+ # Note: This feature is only available in >=2.0.0.
75
+ #Resque::Scheduler.dynamic = true
76
+
77
+ # The schedule doesn't need to be stored in a YAML, it just needs to
78
+ # be a hash. YAML is usually the easiest.
79
+ Resque.schedule = YAML.load_file('your_resque_schedule.yml')
80
+
81
+ # If your schedule already has +queue+ set for each job, you don't
82
+ # need to require your jobs. This can be an advantage since it's
83
+ # less code that resque-scheduler needs to know about. But in a small
84
+ # project, it's usually easier to just include you job classes here.
85
+ # So, something like this:
86
+ require 'jobs'
87
+ end
88
+ end
89
+
90
+ The scheduler process is just a rake task which is responsible for both
91
+ queueing items from the schedule and polling the delayed queue for items
92
+ ready to be pushed on to the work queues. For obvious reasons, this process
93
+ never exits.
94
+
95
+ $ rake resque:scheduler
96
+
97
+ Supported environment variables are `VERBOSE` and `MUTE`. If either is set to
98
+ any nonempty value, they will take effect. `VERBOSE` simply dumps more output
99
+ to stdout. `MUTE` does the opposite and silences all output. `MUTE`
100
+ supersedes `VERBOSE`.
101
+
102
+ NOTE: You DO NOT want to run >1 instance of the scheduler. Doing so will
103
+ result in the same job being queued more than once. You only need one
104
+ instance of the scheduler running per resque instance (regardless of number
105
+ of machines).
106
+
107
+ If the scheduler process goes down for whatever reason, the delayed items
108
+ that should have fired during the outage will fire once the scheduler process
109
+ is started back up again (regardless of it being on a new machine). Missed
110
+ scheduled jobs, however, will not fire upon recovery of the scheduler process.
111
+
112
+
113
+
114
+ ### Delayed jobs
115
+
116
+ Delayed jobs are one-off jobs that you want to be put into a queue at some point
117
+ in the future. The classic example is sending email:
118
+
119
+ Resque.enqueue_in(5.days, SendFollowUpEmail, :user_id => current_user.id)
120
+
121
+ This will store the job for 5 days in the resque delayed queue at which time
122
+ the scheduler process will pull it from the delayed queue and put it in the
123
+ appropriate work queue for the given job and it will be processed as soon as
124
+ a worker is available (just like any other resque job).
125
+
126
+ NOTE: The job does not fire **exactly** at the time supplied. Rather, once that
127
+ time is in the past, the job moves from the delayed queue to the actual resque
128
+ work queue and will be completed as workers as free to process it.
129
+
130
+ Also supported is `Resque.enqueue_at` which takes a timestamp to queue the
131
+ job, and `Resque.enqueue_at_with_queue` which takes both a timestamp and a
132
+ queue name.
133
+
134
+ The delayed queue is stored in redis and is persisted in the same way the
135
+ standard resque jobs are persisted (redis writing to disk). Delayed jobs differ
136
+ from scheduled jobs in that if your scheduler process is down or workers are
137
+ down when a particular job is supposed to be queue, they will simply "catch up"
138
+ once they are started again. Jobs are guaranteed to run (provided they make it
139
+ into the delayed queue) after their given queue_at time has passed.
140
+
141
+ One other thing to note is that insertion into the delayed queue is O(log(n))
142
+ since the jobs are stored in a redis sorted set (zset). I can't imagine this
143
+ being an issue for someone since redis is stupidly fast even at log(n), but full
144
+ disclosure is always best.
145
+
146
+ #### Removing Delayed jobs
147
+
148
+ If you have the need to cancel a delayed job, you can do like so:
149
+
150
+ # after you've enqueued a job like:
151
+ Resque.enqueue_at(5.days.from_now, SendFollowUpEmail, :user_id => current_user.id)
152
+ # remove the job with exactly the same parameters:
153
+ Resque.remove_delayed(SendFollowUpEmail, :user_id => current_user.id)
154
+
155
+ ### Scheduled Jobs (Recurring Jobs)
156
+
157
+ Scheduled (or recurring) jobs are logically no different than a standard cron
158
+ job. They are jobs that run based on a fixed schedule which is set at
159
+ startup.
160
+
161
+ The schedule is a list of Resque worker classes with arguments and a
162
+ schedule frequency (in crontab syntax). The schedule is just a hash, but
163
+ is most likely stored in a YAML like so:
164
+
165
+ CancelAbandonedOrders:
166
+ cron: "*/5 * * * *"
167
+
168
+ queue_documents_for_indexing:
169
+ cron: "0 0 * * *"
170
+ # you can use rufus-scheduler "every" syntax in place of cron if you prefer
171
+ # every: 1hr
172
+ # By default the job name (hash key) will be taken as worker class name.
173
+ # If you want to have a different job name and class name, provide the 'class' option
174
+ class: QueueDocuments
175
+ queue: high
176
+ args:
177
+ description: "This job queues all content for indexing in solr"
178
+
179
+ clear_leaderboards_contributors:
180
+ cron: "30 6 * * 1"
181
+ class: ClearLeaderboards
182
+ queue: low
183
+ args: contributors
184
+ description: "This job resets the weekly leaderboard for contributions"
185
+
186
+ The queue value is optional, but if left unspecified resque-scheduler will
187
+ attempt to get the queue from the job class, which means it needs to be
188
+ defined. If you're getting "uninitialized constant" errors, you probably
189
+ need to either set the queue in the schedule or require your jobs in your
190
+ "resque:setup" rake task.
191
+
192
+ You can provide options to "every" or "cron" via Array:
193
+
194
+ clear_leaderboards_moderator:
195
+ every: ["30s", :first_in => '120s']
196
+ class: CheckDaemon
197
+ queue: daemons
198
+ description: "This job will check Daemon every 30 seconds after 120 seconds after start"
199
+
200
+
201
+ NOTE: Six parameter cron's are also supported (as they supported by
202
+ rufus-scheduler which powers the resque-scheduler process). This allows you
203
+ to schedule jobs per second (ie: "30 * * * * *" would fire a job every 30
204
+ seconds past the minute).
205
+
206
+ A big shout out to [rufus-scheduler](http://github.com/jmettraux/rufus-scheduler)
207
+ for handling the heavy lifting of the actual scheduling engine.
208
+
209
+
210
+ #### Time zones
211
+
212
+ Note that if you use the cron syntax, this will be interpreted as in the server time zone
213
+ rather than the `config.time_zone` specified in Rails.
214
+
215
+ You can explicitly specify the time zone that rufus-scheduler will use:
216
+
217
+ cron: "30 6 * * 1 Europe/Stockholm"
218
+
219
+ Also note that `config.time_zone` in Rails allows for a shorthand (e.g. "Stockholm")
220
+ that rufus-scheduler does not accept. If you write code to set the scheduler time zone
221
+ from the `config.time_zone` value, make sure it's the right format, e.g. with:
222
+
223
+ ActiveSupport::TimeZone.find_tzinfo(Rails.configuration.time_zone).name
224
+
225
+ A future version of resque-scheduler may do this for you.
226
+
227
+ #### Hooks
228
+
229
+ Similar to the `before_enqueue`- and `after_enqueue`-hooks provided in Resque
230
+ (>= 1.19.1), your jobs can specify one or more of the following hooks:
231
+
232
+ * `before_schedule`: Called with the job args before a job is placed on
233
+ the delayed queue. If the hook returns `false`, the job will not be placed on
234
+ the queue.
235
+ * `after_schedule`: Called with the job args after a job is placed on the
236
+ delayed queue. Any exception raised propagates up to the code with queued the
237
+ job.
238
+ * `before_delayed_enqueue`: Called with the job args after the job has been
239
+ removed from the delayed queue, but not yet put on a normal queue. It is
240
+ called before `before_enqueue`-hooks, and on the same job instance as the
241
+ `before_enqueue`-hooks will be invoked on. Return values are ignored.
242
+
243
+ #### Support for resque-status (and other custom jobs)
244
+
245
+ Some Resque extensions like
246
+ [resque-status](http://github.com/quirkey/resque-status) use custom job
247
+ classes with a slightly different API signature. Resque-scheduler isn't
248
+ trying to support all existing and future custom job classes, instead it
249
+ supports a schedule flag so you can extend your custom class and make it
250
+ support scheduled job.
251
+
252
+ Let's pretend we have a JobWithStatus class called FakeLeaderboard
253
+
254
+ class FakeLeaderboard < Resque::JobWithStatus
255
+ def perform
256
+ # do something and keep track of the status
257
+ end
258
+ end
259
+
260
+ And then a schedule:
261
+
262
+ create_fake_leaderboards:
263
+ cron: "30 6 * * 1"
264
+ queue: scoring
265
+ custom_job_class: FakeLeaderboard
266
+ args:
267
+ rails_env: demo
268
+ description: "This job will auto-create leaderboards for our online demo and the status will update as the worker makes progress"
269
+
270
+ If your extension doesn't support scheduled job, you would need to extend the
271
+ custom job class to support the #scheduled method:
272
+
273
+ module Resque
274
+ class JobWithStatus
275
+ # Wrapper API to forward a Resque::Job creation API call into
276
+ # a JobWithStatus call.
277
+ def self.scheduled(queue, klass, *args)
278
+ create(*args)
279
+ end
280
+ end
281
+ end
282
+
283
+
284
+
285
+ ### resque-web Additions
286
+
287
+ Resque-scheduler also adds to tabs to the resque-web UI. One is for viewing
288
+ (and manually queueing) the schedule and one is for viewing pending jobs in
289
+ the delayed queue.
290
+
291
+ The Schedule tab:
292
+
293
+ ![The Schedule Tab](http://img.skitch.com/20100111-km2f5gmtpbq23enpujbruj6mgk.png)
294
+
295
+ The Delayed tab:
296
+
297
+ ![The Delayed Tab](http://img.skitch.com/20100111-ne4fcqtc5emkcuwc5qtais2kwx.jpg)
298
+
299
+ #### How do I get the schedule tabs to show up???
300
+
301
+ To get these to show up you need to pass a file to `resque-web` to tell it to
302
+ include the `resque-scheduler` plugin and the resque-schedule server extension
303
+ to the resque-web sinatra app. Unless you're running redis on localhost, you
304
+ probably already have this file. It probably looks something like this:
305
+
306
+ require 'resque' # include resque so we can configure it
307
+ Resque.redis = "redis_server:6379" # tell Resque where redis lives
308
+
309
+ Now, you want to add the following:
310
+
311
+ # This will make the tabs show up.
312
+ require 'resque_scheduler'
313
+ require 'resque_scheduler/server'
314
+
315
+ That should make the scheduler tabs show up in `resque-web`.
316
+
317
+
318
+ #### Changes as of 2.0.0
319
+
320
+ As of resque-scheduler 2.0.0, it's no longer necessary to have the resque-web
321
+ process aware of the schedule because it reads it from redis. But prior to
322
+ 2.0, you'll want to make sure you load the schedule in this file as well.
323
+ Something like this:
324
+
325
+ Resque.schedule = YAML.load_file(File.join(RAILS_ROOT, 'config/resque_schedule.yml')) # load the schedule
326
+
327
+ Now make sure you're passing that file to resque-web like so:
328
+
329
+ resque-web ~/yourapp/config/resque_config.rb
330
+
331
+
332
+ ### Running in the background
333
+
334
+ (Only supported with ruby >= 1.9). There are scenarios where it's helpful for
335
+ the resque worker to run itself in the background (usually in combination with
336
+ PIDFILE). Use the BACKGROUND option so that rake will return as soon as the
337
+ worker is started.
338
+
339
+ $ PIDFILE=./resque-scheduler.pid BACKGROUND=yes \
340
+ rake resque:scheduler
341
+
342
+ ### Plagiarism alert
343
+
344
+ This was intended to be an extension to resque and so resulted in a lot of the
345
+ code looking very similar to resque, particularly in resque-web and the views. I
346
+ wanted it to be similar enough that someone familiar with resque could easily
347
+ work on resque-scheduler.
348
+
349
+
350
+ ### Contributing
351
+
352
+ For bugs or suggestions, please just open an issue in github.
353
+
354
+ Patches are always welcome.