resque-admin-scheduler 1.0.2 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/bin/migrate_to_timestamps_set.rb +16 -0
  3. data/exe/resque-scheduler +2 -2
  4. data/lib/resque/scheduler/cli.rb +6 -6
  5. data/lib/resque/scheduler/delaying_extensions.rb +14 -14
  6. data/lib/resque/scheduler/env.rb +7 -7
  7. data/lib/resque/scheduler/lock.rb +1 -1
  8. data/lib/resque/scheduler/locking.rb +7 -7
  9. data/lib/resque/scheduler/logger_builder.rb +4 -4
  10. data/lib/resque/scheduler/scheduling_extensions.rb +4 -4
  11. data/lib/resque/scheduler/server/views/delayed.erb +4 -4
  12. data/lib/resque/scheduler/server/views/search.erb +1 -1
  13. data/lib/resque/scheduler/server.rb +37 -37
  14. data/lib/resque/scheduler/signal_handling.rb +1 -1
  15. data/lib/resque/scheduler/tasks.rb +6 -6
  16. data/lib/resque/scheduler/util.rb +4 -4
  17. data/lib/resque/scheduler_admin/cli.rb +147 -0
  18. data/lib/resque/scheduler_admin/delaying_extensions.rb +324 -0
  19. data/lib/resque/scheduler_admin/env.rb +89 -0
  20. data/lib/resque/scheduler_admin/lock.rb +4 -0
  21. data/lib/resque/scheduler_admin/locking.rb +104 -0
  22. data/lib/resque/scheduler_admin/logger_builder.rb +72 -0
  23. data/lib/resque/scheduler_admin/scheduling_extensions.rb +141 -0
  24. data/lib/resque/scheduler_admin/server/views/delayed.erb +63 -0
  25. data/lib/resque/scheduler_admin/server/views/search.erb +72 -0
  26. data/lib/resque/scheduler_admin/signal_handling.rb +40 -0
  27. data/lib/resque/scheduler_admin/tasks.rb +25 -0
  28. data/lib/resque/scheduler_admin/util.rb +39 -0
  29. data/lib/resque-admin-scheduler.rb +4 -0
  30. data/lib/resque_admin/scheduler/cli.rb +147 -0
  31. data/lib/{resque → resque_admin}/scheduler/configuration.rb +1 -1
  32. data/lib/resque_admin/scheduler/delaying_extensions.rb +324 -0
  33. data/lib/resque_admin/scheduler/env.rb +89 -0
  34. data/lib/{resque → resque_admin}/scheduler/extension.rb +1 -1
  35. data/lib/{resque → resque_admin}/scheduler/failure_handler.rb +2 -2
  36. data/lib/{resque → resque_admin}/scheduler/lock/base.rb +3 -3
  37. data/lib/{resque → resque_admin}/scheduler/lock/basic.rb +4 -4
  38. data/lib/{resque → resque_admin}/scheduler/lock/resilient.rb +4 -4
  39. data/lib/resque_admin/scheduler/lock.rb +4 -0
  40. data/lib/resque_admin/scheduler/locking.rb +104 -0
  41. data/lib/resque_admin/scheduler/logger_builder.rb +72 -0
  42. data/lib/{resque → resque_admin}/scheduler/plugin.rb +1 -1
  43. data/lib/resque_admin/scheduler/scheduling_extensions.rb +141 -0
  44. data/lib/resque_admin/scheduler/server/views/delayed.erb +63 -0
  45. data/lib/{resque → resque_admin}/scheduler/server/views/delayed_schedules.erb +0 -0
  46. data/lib/{resque → resque_admin}/scheduler/server/views/delayed_timestamp.erb +2 -2
  47. data/lib/{resque → resque_admin}/scheduler/server/views/requeue-params.erb +0 -0
  48. data/lib/{resque → resque_admin}/scheduler/server/views/scheduler.erb +7 -7
  49. data/lib/resque_admin/scheduler/server/views/search.erb +72 -0
  50. data/lib/{resque → resque_admin}/scheduler/server/views/search_form.erb +0 -0
  51. data/lib/resque_admin/scheduler/server.rb +268 -0
  52. data/lib/resque_admin/scheduler/signal_handling.rb +40 -0
  53. data/lib/resque_admin/scheduler/tasks.rb +25 -0
  54. data/lib/resque_admin/scheduler/util.rb +39 -0
  55. data/lib/{resque → resque_admin}/scheduler/version.rb +2 -2
  56. data/lib/{resque → resque_admin}/scheduler.rb +44 -44
  57. data/tasks/resque_admin_scheduler.rake +2 -0
  58. metadata +47 -85
  59. data/AUTHORS.md +0 -81
  60. data/CHANGELOG.md +0 -456
  61. data/CODE_OF_CONDUCT.md +0 -74
  62. data/CONTRIBUTING.md +0 -6
  63. data/Gemfile +0 -4
  64. data/LICENSE +0 -23
  65. data/README.md +0 -691
  66. data/Rakefile +0 -21
  67. data/lib/resque-scheduler.rb +0 -4
  68. data/resque-scheduler.gemspec +0 -60
data/README.md DELETED
@@ -1,691 +0,0 @@
1
- resque-scheduler
2
- ================
3
-
4
-
5
- [![Dependency Status](https://gemnasium.com/badges/github.com/resque/resque-scheduler.svg)](https://gemnasium.com/github.com/resque/resque-scheduler)
6
- [![Gem Version](https://badge.fury.io/rb/resque-scheduler.svg)](https://badge.fury.io/rb/resque-scheduler)
7
- [![Build Status](https://travis-ci.org/resque/resque-scheduler.svg?branch=master)](https://travis-ci.org/resque/resque-scheduler)
8
- [![Windows Build Status](https://ci.appveyor.com/api/projects/status/sxvf2086v5j0absb/branch/master?svg=true)](https://ci.appveyor.com/project/resque/resque-scheduler/branch/master)
9
- [![Code Climate](https://codeclimate.com/github/resque/resque-scheduler/badges/gpa.svg)](https://codeclimate.com/github/resque/resque-scheduler)
10
-
11
- ### Description
12
-
13
- Resque-scheduler is an extension to [Resque](http://github.com/resque/resque)
14
- that adds support for queueing items in the future.
15
-
16
- Job scheduling is supported in two different way: Recurring (scheduled) and
17
- Delayed.
18
-
19
- Scheduled jobs are like cron jobs, recurring on a regular basis. Delayed
20
- jobs are resque jobs that you want to run at some point in the future.
21
- The syntax is pretty explanatory:
22
-
23
- ```ruby
24
- Resque.enqueue_in(5.days, SendFollowupEmail, argument) # runs a job in 5 days, calling SendFollowupEmail.perform(argument)
25
- # or
26
- Resque.enqueue_at(5.days.from_now, SomeJob, argument) # runs a job at a specific time, calling SomeJob.perform(argument)
27
- ```
28
-
29
- ### Documentation
30
-
31
- This `README` covers what most people need to know. If you're looking
32
- for details on individual methods, you might want to try the
33
- [rdoc](http://rdoc.info/github/resque/resque-scheduler/master/frames).
34
-
35
- ### Installation
36
-
37
- To install:
38
-
39
- gem install resque-scheduler
40
-
41
- If you use a Gemfile:
42
-
43
- ```ruby
44
- gem 'resque-scheduler'
45
- ```
46
-
47
- Adding the resque:scheduler rake task:
48
-
49
- ```ruby
50
- require 'resque/scheduler/tasks'
51
- ```
52
-
53
- ### Rake integration
54
-
55
- By default, `resque-scheduler` depends on the "resque:setup" rake task.
56
- Since you probably already have this task, lets just put our
57
- configuration there. `resque-scheduler` pretty much needs to know
58
- everything `resque` needs to know.
59
-
60
- ```ruby
61
- # Resque tasks
62
- require 'resque/tasks'
63
- require 'resque/scheduler/tasks'
64
-
65
- namespace :resque do
66
- task :setup do
67
- require 'resque'
68
-
69
- # you probably already have this somewhere
70
- Resque.redis = 'localhost:6379'
71
- end
72
-
73
- task :setup_schedule => :setup do
74
- require 'resque-scheduler'
75
-
76
- # If you want to be able to dynamically change the schedule,
77
- # uncomment this line. A dynamic schedule can be updated via the
78
- # Resque::Scheduler.set_schedule (and remove_schedule) methods.
79
- # When dynamic is set to true, the scheduler process looks for
80
- # schedule changes and applies them on the fly.
81
- # Note: This feature is only available in >=2.0.0.
82
- # Resque::Scheduler.dynamic = true
83
-
84
- # The schedule doesn't need to be stored in a YAML, it just needs to
85
- # be a hash. YAML is usually the easiest.
86
- Resque.schedule = YAML.load_file('your_resque_schedule.yml')
87
-
88
- # If your schedule already has +queue+ set for each job, you don't
89
- # need to require your jobs. This can be an advantage since it's
90
- # less code that resque-scheduler needs to know about. But in a small
91
- # project, it's usually easier to just include you job classes here.
92
- # So, something like this:
93
- require 'jobs'
94
- end
95
-
96
- task :scheduler => :setup_schedule
97
- end
98
- ```
99
-
100
- The scheduler rake task is responsible for both queueing items from the
101
- schedule and polling the delayed queue for items ready to be pushed on
102
- to the work queues. For obvious reasons, this process never exits.
103
-
104
- ``` bash
105
- rake resque:scheduler
106
- ```
107
-
108
- or, if you want to load the environment first:
109
-
110
- ``` bash
111
- rake environment resque:scheduler
112
- ```
113
-
114
-
115
- ### Standalone Executable
116
-
117
- The scheduler may also be run via a standalone `resque-scheduler`
118
- executable, which will be available once the gem is installed.
119
-
120
- ``` bash
121
- # Get some help
122
- resque-scheduler --help
123
- ```
124
-
125
- The executable accepts options via option flags as well as via
126
- [environment variables](#environment-variables).
127
-
128
- ### Environment Variables
129
-
130
- Both the Rake task and standalone executable support the following
131
- environment variables:
132
-
133
- * `APP_NAME` - Application name used in procline (`$0`) (default empty)
134
- * `BACKGROUND` - [Run in the background](#running-in-the-background) if
135
- non-empty (via `Process.daemon`, if supported) (default `false`)
136
- * `DYNAMIC_SCHEDULE` - Enables [dynamic scheduling](#dynamic-schedules)
137
- if non-empty (default `false`)
138
- * `RAILS_ENV` - Environment to use in procline (`$0`) (default empty)
139
- * `INITIALIZER_PATH` - Path to a Ruby file that will be loaded *before*
140
- requiring `resque` and `resque/scheduler` (default empty).
141
- * `RESQUE_SCHEDULER_INTERVAL` - Interval in seconds for checking if a
142
- scheduled job must run (coerced with `Kernel#Float()`) (default `5`)
143
- * `LOGFILE` - Log file name (default empty, meaning `$stdout`)
144
- * `LOGFORMAT` - Log output format to use (either `'text'` or `'json'`,
145
- default `'text'`)
146
- * `PIDFILE` - If non-empty, write process PID to file (default empty)
147
- * `QUIET` - Silence most output if non-empty (equivalent to a level of
148
- `MonoLogger::FATAL`, default `false`)
149
- * `VERBOSE` - Maximize log verbosity if non-empty (equivalent to a level
150
- of `MonoLogger::DEBUG`, default `false`)
151
-
152
-
153
- ### Resque Pool integration
154
-
155
- For normal work with the
156
- [resque-pool](https://github.com/nevans/resque-pool) gem, add the
157
- following task to wherever tasks are kept, such as
158
- `./lib/tasks/resque.rake`:
159
-
160
- ```ruby
161
- task 'resque:pool:setup' do
162
- Resque::Pool.after_prefork do |job|
163
- Resque.redis.client.reconnect
164
- end
165
- end
166
- ```
167
-
168
-
169
- ### Delayed jobs
170
-
171
- Delayed jobs are one-off jobs that you want to be put into a queue at some point
172
- in the future. The classic example is sending email:
173
-
174
- ```ruby
175
- Resque.enqueue_in(
176
- 5.days,
177
- SendFollowUpEmail,
178
- user_id: current_user.id
179
- )
180
- ```
181
-
182
- This will store the job for 5 days in the resque delayed queue at which time
183
- the scheduler process will pull it from the delayed queue and put it in the
184
- appropriate work queue for the given job and it will be processed as soon as
185
- a worker is available (just like any other resque job).
186
-
187
- **NOTE**: The job does not fire **exactly** at the time supplied. Rather, once that
188
- time is in the past, the job moves from the delayed queue to the actual resque
189
- work queue and will be completed as workers are free to process it.
190
-
191
- Also supported is `Resque.enqueue_at` which takes a timestamp to queue the
192
- job, and `Resque.enqueue_at_with_queue` which takes both a timestamp and a
193
- queue name:
194
-
195
- ```ruby
196
- Resque.enqueue_at_with_queue(
197
- 'queue_name',
198
- 5.days.from_now,
199
- SendFollowUpEmail,
200
- user_id: current_user.id
201
- )
202
- ```
203
-
204
- The delayed queue is stored in redis and is persisted in the same way the
205
- standard resque jobs are persisted (redis writing to disk). Delayed jobs differ
206
- from scheduled jobs in that if your scheduler process is down or workers are
207
- down when a particular job is supposed to be queue, they will simply "catch up"
208
- once they are started again. Jobs are guaranteed to run (provided they make it
209
- into the delayed queue) after their given `queue_at` time has passed.
210
-
211
- One other thing to note is that insertion into the delayed queue is O(log(n))
212
- since the jobs are stored in a redis sorted set (zset). I can't imagine this
213
- being an issue for someone since redis is stupidly fast even at log(n), but full
214
- disclosure is always best.
215
-
216
- #### Removing Delayed jobs
217
-
218
- If you have the need to cancel a delayed job, you can do like so:
219
-
220
- ```ruby
221
- # after you've enqueued a job like:
222
- Resque.enqueue_at(5.days.from_now, SendFollowUpEmail, :user_id => current_user.id)
223
- # remove the job with exactly the same parameters:
224
- Resque.remove_delayed(SendFollowUpEmail, :user_id => current_user.id)
225
- ```
226
-
227
- If you need to cancel a delayed job based on some matching arguments, but don't wish to specify each argument from when the job was created, you can do like so:
228
-
229
- ``` ruby
230
- # after you've enqueued a job like:
231
- Resque.enqueue_at(5.days.from_now, SendFollowUpEmail, :account_id => current_account.id, :user_id => current_user.id)
232
- # remove jobs matching just the account:
233
- Resque.remove_delayed_selection { |args| args[0]['account_id'] == current_account.id }
234
- # or remove jobs matching just the user:
235
- Resque.remove_delayed_selection { |args| args[0]['user_id'] == current_user.id }
236
- ```
237
-
238
- If you need to enqueue immediately a delayed job based on some matching arguments, but don't wish to specify each argument from when the job was created, you can do like so:
239
-
240
- ``` ruby
241
- # after you've enqueued a job like:
242
- Resque.enqueue_at(5.days.from_now, SendFollowUpEmail, :account_id => current_account.id, :user_id => current_user.id)
243
- # enqueue immediately jobs matching just the account:
244
- Resque.enqueue_delayed_selection { |args| args[0]['account_id'] == current_account.id }
245
- # or enqueue immediately jobs matching just the user:
246
- Resque.enqueue_delayed_selection { |args| args[0]['user_id'] == current_user.id }
247
- ```
248
-
249
- ### Scheduled Jobs (Recurring Jobs)
250
-
251
- Scheduled (or recurring) jobs are logically no different than a standard cron
252
- job. They are jobs that run based on a schedule which can be static or dynamic.
253
-
254
- #### Static schedules
255
-
256
- Static schedules are set when `resque-scheduler` starts by passing a schedule file
257
- to `resque-scheduler` initialization like this (see *Installation* above for a more complete example):
258
-
259
- ```ruby
260
- Resque.schedule = YAML.load_file('your_resque_schedule.yml')
261
- ```
262
-
263
- If a static schedule is not set `resque-scheduler` will issue a "Schedule empty!" warning on
264
- startup, but despite that warning setting a static schedule is totally optional. It is possible
265
- to use only dynamic schedules (see below).
266
-
267
- The schedule file is a list of Resque job classes with arguments and a
268
- schedule frequency (in crontab syntax). The schedule is just a hash, but
269
- is usually stored in a YAML like this:
270
-
271
- ```yaml
272
- CancelAbandonedOrders:
273
- cron: "*/5 * * * *"
274
-
275
- queue_documents_for_indexing:
276
- cron: "0 0 * * *"
277
- # you can use rufus-scheduler "every" syntax in place of cron if you prefer
278
- # every: 1h
279
- # By default the job name (hash key) will be taken as worker class name.
280
- # If you want to have a different job name and class name, provide the 'class' option
281
- class: "QueueDocuments"
282
- queue: high
283
- args:
284
- description: "This job queues all content for indexing in solr"
285
-
286
- clear_leaderboards_contributors:
287
- cron: "30 6 * * 1"
288
- class: "ClearLeaderboards"
289
- queue: low
290
- args: contributors
291
- description: "This job resets the weekly leaderboard for contributions"
292
- ```
293
-
294
- If you would like to setup a job that is executed manually you can configure like this in your YAML file.
295
-
296
- ```yaml
297
- ImportOrdersManual:
298
- description: 'Import Amazon Orders Manual'
299
- custom_job_class: 'AmazonMws::ImportOrdersJob'
300
- never: "* * * * *"
301
- queue: high
302
- description: "This is a manual job for importing orders."
303
- args:
304
- days_in_arrears: 7
305
- ```
306
-
307
- The queue value is optional, but if left unspecified resque-scheduler will
308
- attempt to get the queue from the job class, which means it needs to be
309
- defined. If you're getting "uninitialized constant" errors, you probably
310
- need to either set the queue in the schedule or require your jobs in your
311
- "resque:setup" rake task.
312
-
313
- You can provide options to "every" or "cron" via Array:
314
-
315
- ```yaml
316
- clear_leaderboards_moderator:
317
- every:
318
- - "30s"
319
- - :first_in: '120s'
320
- class: "CheckDaemon"
321
- queue: daemons
322
- description: "This job will check Daemon every 30 seconds after 120 seconds after start"
323
- ```
324
-
325
- IMPORTANT: Rufus `every` syntax will calculate jobs scheduling time starting from the moment of deploy,
326
- resulting in resetting schedule time on every deploy, so it's probably a good idea to use it only for
327
- frequent jobs (like every 10-30 minutes), otherwise - when you use something like `every 20h` and deploy once-twice per day -
328
- it will schedule the job for 20 hours from deploy, resulting in a job to never be run.
329
-
330
- **NOTE**: Six parameter cron's are also supported (as they supported by
331
- rufus-scheduler which powers the resque-scheduler process). This allows you
332
- to schedule jobs per second (ie: `"30 * * * * *"` would fire a job every 30
333
- seconds past the minute).
334
-
335
- A big shout out to [rufus-scheduler](http://github.com/jmettraux/rufus-scheduler)
336
- for handling the heavy lifting of the actual scheduling engine.
337
-
338
- #### Dynamic schedules
339
-
340
- Dynamic schedules are programmatically set on a running `resque-scheduler`.
341
- All [rufus-scheduler](http://github.com/jmettraux/rufus-scheduler) options are supported
342
- when setting schedules.
343
-
344
- Dynamic schedules are not enabled by default. To be able to dynamically set schedules, you
345
- must pass the following to `resque-scheduler` initialization (see *Installation* above for a more complete example):
346
-
347
- ```ruby
348
- Resque::Scheduler.dynamic = true
349
- ```
350
-
351
- **NOTE**: In order to delete dynamic schedules via `resque-web` in the
352
- "Schedule" tab, you must include the `Rack::MethodOverride` middleware (in
353
- `config.ru` or equivalent).
354
-
355
- Dynamic schedules allow for greater flexibility than static schedules as they can be set,
356
- unset or changed without having to restart `resque-scheduler`. You can specify, if the schedule
357
- must survive a resque-scheduler restart or not. This is done by setting the `persist` configuration
358
- for the schedule: it is a boolean value, if set the schedule will persist a restart. By default,
359
- a schedule will not be persisted.
360
-
361
- The job to be scheduled must be a valid Resque job class.
362
-
363
- For example, suppose you have a SendEmail job which sends emails. The `perform` method of the
364
- job receives a string argument with the email subject. To run the SendEmail job every hour
365
- starting five minutes from now, you can do:
366
-
367
- ```ruby
368
- name = 'send_emails'
369
- config = {}
370
- config[:class] = 'SendEmail'
371
- config[:args] = 'POC email subject'
372
- config[:every] = ['1h', {first_in: 5.minutes}]
373
- config[:persist] = true
374
- Resque.set_schedule(name, config)
375
- ```
376
-
377
- Schedules can later be removed by passing their name to the `remove_schedule` method:
378
-
379
- ```ruby
380
- name = 'send_emails'
381
- Resque.remove_schedule(name)
382
- ```
383
-
384
- Schedule names are unique; i.e. two dynamic schedules cannot have the same name. If `set_schedule` is
385
- passed the name of an existing schedule, that schedule is updated. E.g. if after setting the above schedule
386
- we want the job to run every day instead of every hour from now on, we can do:
387
-
388
- ```ruby
389
- name = 'send_emails'
390
- config = {}
391
- config[:class] = 'SendEmail'
392
- config[:args] = 'POC email subject'
393
- config[:every] = '1d'
394
- Resque.set_schedule(name, config)
395
- ```
396
-
397
- #### Time zones
398
-
399
- Note that if you use the cron syntax, this will be interpreted as in the server time zone
400
- rather than the `config.time_zone` specified in Rails.
401
-
402
- You can explicitly specify the time zone that rufus-scheduler will use:
403
-
404
- ```yaml
405
- cron: "30 6 * * 1 Europe/Stockholm"
406
- ```
407
-
408
- Also note that `config.time_zone` in Rails allows for a shorthand (e.g. "Stockholm")
409
- that rufus-scheduler does not accept. If you write code to set the scheduler time zone
410
- from the `config.time_zone` value, make sure it's the right format, e.g. with:
411
-
412
- ```ruby
413
- ActiveSupport::TimeZone.find_tzinfo(Rails.configuration.time_zone).name
414
- ```
415
-
416
- A future version of resque-scheduler may do this for you.
417
-
418
- #### Hooks
419
-
420
- Similar to the `before_enqueue`- and `after_enqueue`-hooks provided in Resque
421
- (>= 1.19.1), your jobs can specify one or more of the following hooks:
422
-
423
- * `before_schedule`: Called with the job args before a job is placed on
424
- the delayed queue. If the hook returns `false`, the job will not be placed on
425
- the queue.
426
- * `after_schedule`: Called with the job args after a job is placed on the
427
- delayed queue. Any exception raised propagates up to the code with queued the
428
- job.
429
- * `before_delayed_enqueue`: Called with the job args after the job has been
430
- removed from the delayed queue, but not yet put on a normal queue. It is
431
- called before `before_enqueue`-hooks, and on the same job instance as the
432
- `before_enqueue`-hooks will be invoked on. Return values are ignored.
433
- * `on_enqueue_failure`: Called with the job args and the exception that was raised
434
- while enqueueing a job to resque or external application fails. Return
435
- values are ignored. For example:
436
-
437
- ```ruby
438
- Resque::Scheduler.failure_handler = ExceptionHandlerClass
439
- ```
440
-
441
- #### Support for resque-status (and other custom jobs)
442
-
443
- Some Resque extensions like
444
- [resque-status](http://github.com/quirkey/resque-status) use custom job
445
- classes with a slightly different API signature. Resque-scheduler isn't
446
- trying to support all existing and future custom job classes, instead it
447
- supports a schedule flag so you can extend your custom class and make it
448
- support scheduled job.
449
-
450
- Let's pretend we have a `JobWithStatus` class called `FakeLeaderboard`
451
-
452
- ```ruby
453
- class FakeLeaderboard < Resque::JobWithStatus
454
- def perform
455
- # do something and keep track of the status
456
- end
457
- end
458
- ```
459
-
460
- And then a schedule:
461
-
462
- ```yaml
463
- create_fake_leaderboards:
464
- cron: "30 6 * * 1"
465
- queue: scoring
466
- custom_job_class: "FakeLeaderboard"
467
- args:
468
- rails_env: demo
469
- description: "This job will auto-create leaderboards for our online demo and the status will update as the worker makes progress"
470
- ```
471
-
472
- If your extension doesn't support scheduled job, you would need to extend the
473
- custom job class to support the #scheduled method:
474
-
475
- ```ruby
476
- module Resque
477
- class JobWithStatus
478
- # Wrapper API to forward a Resque::Job creation API call into
479
- # a JobWithStatus call.
480
- def self.scheduled(queue, klass, *args)
481
- create(*args)
482
- end
483
- end
484
- end
485
- ```
486
-
487
- ### Redundancy and Fail-Over
488
-
489
- *>= 2.0.1 only. Prior to 2.0.1, it is not recommended to run multiple resque-scheduler processes and will result in duplicate jobs.*
490
-
491
- You may want to have resque-scheduler running on multiple machines for
492
- redundancy. Electing a master and failover is built in and default. Simply
493
- run resque-scheduler on as many machine as you want pointing to the same
494
- redis instance and schedule. The scheduler processes will use redis to
495
- elect a master process and detect failover when the master dies. Precautions are
496
- taken to prevent jobs from potentially being queued twice during failover even
497
- when the clocks of the scheduler machines are slightly out of sync (or load affects
498
- scheduled job firing time). If you want the gory details, look at Resque::Scheduler::Locking.
499
-
500
- If the scheduler process(es) goes down for whatever reason, the delayed items
501
- that should have fired during the outage will fire once the scheduler process
502
- is started back up again (regardless of it being on a new machine). Missed
503
- scheduled jobs, however, will not fire upon recovery of the scheduler process.
504
- Think of scheduled (recurring) jobs as cron jobs - if you stop cron, it doesn't fire
505
- missed jobs once it starts back up.
506
-
507
- You might want to share a redis instance amongst multiple Rails applications with different
508
- scheduler with different config yaml files. If this is the case, normally, only one will ever
509
- run, leading to undesired behaviour. To allow different scheduler configs run at the same time
510
- on one redis, you can either namespace your redis connections, or supply an environment variable
511
- to split the shared lock key resque-scheduler uses thus:
512
-
513
- ``` bash
514
- RESQUE_SCHEDULER_MASTER_LOCK_PREFIX=MyApp: rake resque:scheduler
515
- ```
516
-
517
- ### resque-web Additions
518
-
519
- Resque-scheduler also adds to tabs to the resque-web UI. One is for viewing
520
- (and manually queueing) the schedule and one is for viewing pending jobs in
521
- the delayed queue.
522
-
523
- The Schedule tab:
524
-
525
- ![The Schedule Tab](https://f.cloud.github.com/assets/45143/1178456/c99e5568-21b0-11e3-8c57-e1305d0ee8ef.png)
526
-
527
- The Delayed tab:
528
-
529
- ![The Delayed Tab](http://img.skitch.com/20100111-ne4fcqtc5emkcuwc5qtais2kwx.jpg)
530
-
531
- #### How do I get the schedule tabs to show up???
532
-
533
- To get these to show up you need to pass a file to `resque-web` to tell it to
534
- include the `resque-scheduler` plugin and the resque-schedule server extension
535
- to the resque-web sinatra app. Unless you're running redis on localhost, you
536
- probably already have this file. It probably looks something like this:
537
-
538
- ```ruby
539
- require 'resque' # include resque so we can configure it
540
- Resque.redis = "redis_server:6379" # tell Resque where redis lives
541
- ```
542
-
543
- Now, you want to add the following:
544
-
545
- ```ruby
546
- # This will make the tabs show up.
547
- require 'resque-scheduler'
548
- require 'resque/scheduler/server'
549
- ```
550
-
551
- That should make the scheduler tabs show up in `resque-web`.
552
-
553
- #### Changes as of 2.0.0
554
-
555
- As of resque-scheduler 2.0.0, it's no longer necessary to have the resque-web
556
- process aware of the schedule because it reads it from redis. But prior to
557
- 2.0, you'll want to make sure you load the schedule in this file as well.
558
- Something like this:
559
-
560
- ```ruby
561
- Resque.schedule = YAML.load_file(File.join(RAILS_ROOT, 'config/resque_schedule.yml')) # load the schedule
562
- ```
563
-
564
- Now make sure you're passing that file to resque-web like so:
565
-
566
- resque-web ~/yourapp/config/resque_config.rb
567
-
568
-
569
- ### Running in the background
570
-
571
- (Only supported with ruby >= 1.9). There are scenarios where it's helpful for
572
- the resque worker to run itself in the background (usually in combination with
573
- PIDFILE). Use the BACKGROUND option so that rake will return as soon as the
574
- worker is started.
575
-
576
- $ PIDFILE=./resque-scheduler.pid BACKGROUND=yes \
577
- rake resque:scheduler
578
-
579
-
580
- ### Logging
581
-
582
- There are several options to toggle the way scheduler logs its actions. They
583
- are toggled by environment variables:
584
-
585
- - `QUIET` will stop logging anything. Completely silent.
586
- - `VERBOSE` opposite of 'QUIET'; will log even debug information
587
- - `LOGFILE` specifies the file to write logs to. (default standard output)
588
- - `LOGFORMAT` specifies either "text" or "json" output format
589
- (default "text")
590
-
591
- All of these variables are optional and will be given the following default
592
- values:
593
-
594
- ```ruby
595
- Resque::Scheduler.configure do |c|
596
- c.quiet = false
597
- c.verbose = false
598
- c.logfile = nil # meaning all messages go to $stdout
599
- c.logformat = 'text'
600
- end
601
- ```
602
-
603
- ### Polling frequency
604
-
605
- You can pass a `RESQUE_SCHEDULER_INTERVAL` option which is an integer or
606
- float representing the polling frequency. The default is 5 seconds, but
607
- for a semi-active app you may want to use a smaller value.
608
-
609
- $ RESQUE_SCHEDULER_INTERVAL=1 rake resque:scheduler
610
-
611
- **NOTE** This value was previously `INTERVAL` but was renamed to
612
- `RESQUE_SCHEDULER_INTERVAL` to avoid clashing with the interval Resque
613
- uses for its jobs.
614
-
615
- ### Plagiarism alert
616
-
617
- This was intended to be an extension to resque and so resulted in a lot
618
- of the code looking very similar to resque, particularly in resque-web
619
- and the views. I wanted it to be similar enough that someone familiar
620
- with resque could easily work on resque-scheduler.
621
-
622
- ### Development
623
-
624
- Working on resque-scheduler requires the following:
625
-
626
- * A relatively modern Ruby interpreter
627
- * bundler
628
-
629
- The development setup looks like this, which is roughly the same thing
630
- that happens on Travis CI and Appveyor:
631
-
632
- ``` bash
633
- # Install everything
634
- bundle install
635
-
636
- # Make sure tests are green before you change stuff
637
- bundle exec rake
638
- # Change stuff
639
- # Repeat
640
- ```
641
-
642
- If you have [vagrant](http://www.vagrantup.com) installed, there is a
643
- development box available that requires no plugins or external
644
- provisioners:
645
-
646
- ``` bash
647
- vagrant up
648
- ```
649
-
650
- ### Deployment Notes
651
-
652
- It is recommended that a production deployment of `resque-scheduler` be hosted
653
- on a dedicated Redis database. While making and managing scheduled tasks,
654
- `resque-scheduler` currently scans the entire Redis keyspace, which may cause
655
- latency and stability issues if `resque-scheduler` is hosted on a Redis instance
656
- storing a large number of keys (such as those written by a different system
657
- hosted on the same Redis instance).
658
-
659
- #### Compatibility Notes
660
-
661
- Different versions of the `redis` and `rufus-scheduler` gems are needed
662
- depending on your version of `resque-scheduler`. This is typically not a
663
- problem with `resque-scheduler` itself, but when mixing dependencies with an
664
- existing application.
665
-
666
- This table explains the version requirements for redis gem
667
-
668
- | resque-scheduler | redis gem |
669
- |:-----------------|-----------:|
670
- | `~> 2.0` | `>= 3.0.0` |
671
- | `>= 0.0.1` | `~> 1.3` |
672
-
673
- This table explains the version requirements for rufus-scheduler
674
-
675
- | resque-scheduler | rufus-scheduler |
676
- |:-----------------|----------------:|
677
- | `~> 4.0` | `~> 3.0` |
678
- | `< 4.0` | `~> 2.0` |
679
-
680
-
681
- ### Contributing
682
-
683
- See [CONTRIBUTING.md](CONTRIBUTING.md)
684
-
685
- ### Authors
686
-
687
- See [AUTHORS.md](AUTHORS.md)
688
-
689
- ### License
690
-
691
- See [LICENSE](LICENSE)