nogara-resque-scheduler 2.0.1

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.
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.