{"id":13484488,"url":"https://github.com/resque/resque-scheduler","last_synced_at":"2026-01-18T03:58:20.630Z","repository":{"id":425082,"uuid":"444380","full_name":"resque/resque-scheduler","owner":"resque","description":"A light-weight job scheduling system built on top of Resque","archived":false,"fork":false,"pushed_at":"2025-05-13T13:46:58.000Z","size":1154,"stargazers_count":1739,"open_issues_count":78,"forks_count":483,"subscribers_count":29,"default_branch":"master","last_synced_at":"2025-05-14T22:03:54.692Z","etag":null,"topics":["background-jobs","queue","scheduler"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/resque.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/funding.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS.md","dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":["iloveitaly"]}},"created_at":"2009-12-21T05:24:09.000Z","updated_at":"2025-05-13T13:47:02.000Z","dependencies_parsed_at":"2023-07-05T14:53:30.122Z","dependency_job_id":"12ab87a9-e06f-4595-9787-dbf9cf3a95ef","html_url":"https://github.com/resque/resque-scheduler","commit_stats":{"total_commits":757,"total_committers":169,"mean_commits":4.479289940828402,"dds":0.8110964332892998,"last_synced_commit":"121e3427d1211baf8354067321d1f1dd14c7e4a1"},"previous_names":["bvandenbos/resque-scheduler"],"tags_count":58,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/resque%2Fresque-scheduler","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/resque%2Fresque-scheduler/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/resque%2Fresque-scheduler/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/resque%2Fresque-scheduler/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/resque","download_url":"https://codeload.github.com/resque/resque-scheduler/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254235687,"owners_count":22036962,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["background-jobs","queue","scheduler"],"created_at":"2024-07-31T17:01:25.138Z","updated_at":"2026-01-18T03:58:20.607Z","avatar_url":"https://github.com/resque.png","language":"Ruby","readme":"resque-scheduler\n================\n\n\n[![Gem Version](https://badge.fury.io/rb/resque-scheduler.svg)](https://badge.fury.io/rb/resque-scheduler)\n[![Ruby specs](https://github.com/resque/resque-scheduler/actions/workflows/ruby.yml/badge.svg)](https://github.com/resque/resque-scheduler/actions)\n[![Code Climate](https://codeclimate.com/github/resque/resque-scheduler/badges/gpa.svg)](https://codeclimate.com/github/resque/resque-scheduler)\n\n### Description\n\nResque-scheduler is an extension to [Resque](http://github.com/resque/resque)\nthat adds support for queueing items in the future.\n\nJob scheduling is supported in two different ways: Recurring (scheduled) and\nDelayed.\n\nScheduled jobs are like cron jobs, recurring on a regular basis.  Delayed\njobs are resque jobs that you want to run at some point in the future.\nThe syntax is pretty explanatory:\n\n```ruby\nResque.enqueue_in(5.days, SendFollowupEmail, argument) # runs a job in 5 days, calling SendFollowupEmail.perform(argument)\n# or\nResque.enqueue_at(5.days.from_now, SomeJob, argument) # runs a job at a specific time, calling SomeJob.perform(argument)\n```\n\n### Documentation\n\nThis `README` covers what most people need to know.  If you're looking\nfor details on individual methods, you might want to try the\n[rubydoc](https://rubydoc.info/github/resque/resque-scheduler/master/frames).\n\n### Installation\n\nTo install:\n\n    gem install resque-scheduler\n\nIf you use a Gemfile:\n\n```ruby\ngem 'resque-scheduler'\n```\n\nAdding the resque:scheduler rake task:\n\n```ruby\nrequire 'resque/scheduler/tasks'\n```\n\n### Rake integration\n\nBy default, `resque-scheduler` depends on the \"resque:setup\" rake task.\nSince you probably already have this task, lets just put our\nconfiguration there.  `resque-scheduler` pretty much needs to know\neverything `resque` needs to know.\n\n```ruby\n# Resque tasks\nrequire 'resque/tasks'\nrequire 'resque/scheduler/tasks'\n\nnamespace :resque do\n  task :setup do\n    require 'resque'\n\n    # you probably already have this somewhere\n    Resque.redis = 'localhost:6379'\n  end\n\n  task :setup_schedule =\u003e :setup do\n    require 'resque-scheduler'\n\n    # If you want to be able to dynamically change the schedule,\n    # uncomment this line.  A dynamic schedule can be updated via the\n    # Resque::Scheduler.set_schedule (and remove_schedule) methods.\n    # When dynamic is set to true, the scheduler process looks for\n    # schedule changes and applies them on the fly.\n    # Note: This feature is only available in \u003e=2.0.0.\n    # Resque::Scheduler.dynamic = true\n\n    # The schedule doesn't need to be stored in a YAML, it just needs to\n    # be a hash.  YAML is usually the easiest.\n    Resque.schedule = YAML.load_file('your_resque_schedule.yml')\n\n    # If your schedule already has +queue+ set for each job, you don't\n    # need to require your jobs.  This can be an advantage since it's\n    # less code that resque-scheduler needs to know about. But in a small\n    # project, it's usually easier to just include your job classes here.\n    # So, something like this:\n    require 'jobs'\n  end\n\n  task :scheduler =\u003e :setup_schedule\nend\n```\n\nThe scheduler rake task is responsible for both queueing items from the\nschedule and polling the delayed queue for items ready to be pushed on\nto the work queues.  For obvious reasons, this process never exits.\n\n``` bash\nrake resque:scheduler\n```\n\nor, if you want to load the environment first:\n\n``` bash\nrake environment resque:scheduler\n```\n\n\n### Standalone Executable\n\nThe scheduler may also be run via a standalone `resque-scheduler`\nexecutable, which will be available once the gem is installed.\n\n``` bash\n# Get some help\nresque-scheduler --help\n```\n\nThe executable accepts options via option flags as well as via\n[environment variables](#environment-variables).\n\n### Environment Variables\n\nBoth the Rake task and standalone executable support the following\nenvironment variables:\n\n* `APP_NAME` - Application name used in procline (`$0`) (default empty)\n* `BACKGROUND` - [Run in the background](#running-in-the-background) if\nnon-empty (via `Process.daemon`, if supported) (default `false`)\n* `DYNAMIC_SCHEDULE` - Enables [dynamic scheduling](#dynamic-schedules)\nif non-empty (default `false`)\n* `RAILS_ENV` - Environment to use in procline (`$0`) (default empty)\n* `INITIALIZER_PATH` - Path to a Ruby file that will be loaded *before*\nrequiring `resque` and `resque/scheduler` (default empty).\n* `RESQUE_SCHEDULER_INTERVAL` - Interval in seconds for checking if a\nscheduled job must run (coerced with `Kernel#Float()`) (default `5`)\n* `LOGFILE` - Log file name (default empty, meaning `$stdout`)\n* `LOGFORMAT` - Log output format to use (either `'text'`, `'json'` or `'logfmt'`,\ndefault `'text'`)\n* `PIDFILE` - If non-empty, write process PID to file (default empty)\n* `QUIET` - Silence most output if non-empty (equivalent to a level of\n`MonoLogger::FATAL`, default `false`)\n* `VERBOSE` - Maximize log verbosity if non-empty (equivalent to a level\nof `MonoLogger::DEBUG`, default `false`)\n\n\n### Resque Pool integration\n\nFor normal work with the\n[resque-pool](https://github.com/nevans/resque-pool) gem, add the\nfollowing task to wherever tasks are kept, such as\n`./lib/tasks/resque.rake`:\n\n```ruby\ntask 'resque:pool:setup' do\n  Resque::Pool.after_prefork do |job|\n    Resque.redis.reconnect\n  end\nend\n```\n\n\n### Delayed jobs\n\nDelayed jobs are one-off jobs that you want to be put into a queue at some point\nin the future.  The classic example is sending email:\n\n```ruby\nResque.enqueue_in(\n  5.days,\n  SendFollowUpEmail,\n  user_id: current_user.id\n)\n```\n\nThis will store the job for 5 days in the resque delayed queue at which time\nthe scheduler process will pull it from the delayed queue and put it in the\nappropriate work queue for the given job and it will be processed as soon as\na worker is available (just like any other resque job).\n\n**NOTE**: The job does not fire **exactly** at the time supplied.  Rather, once that\ntime is in the past, the job moves from the delayed queue to the actual resque\nwork queue and will be completed as workers are free to process it.\n\nAlso supported is `Resque.enqueue_at` which takes a timestamp to queue the\njob, and `Resque.enqueue_at_with_queue` which takes both a timestamp and a\nqueue name:\n\n```ruby\nResque.enqueue_at_with_queue(\n  'queue_name',\n  5.days.from_now,\n  SendFollowUpEmail,\n  user_id: current_user.id\n)\n```\n\nThe delayed queue is stored in redis and is persisted in the same way the\nstandard resque jobs are persisted (redis writing to disk). Delayed jobs differ\nfrom scheduled jobs in that if your scheduler process is down or workers are\ndown when a particular job is supposed to be queue, they will simply \"catch up\"\nonce they are started again.  Jobs are guaranteed to run (provided they make it\ninto the delayed queue) after their given `queue_at` time has passed.\n\nOne other thing to note is that insertion into the delayed queue is O(log(n))\nsince the jobs are stored in a redis sorted set (zset).  I can't imagine this\nbeing an issue for someone since redis is stupidly fast even at log(n), but full\ndisclosure is always best.\n\n#### Removing Delayed Jobs\n\nIf you have the need to cancel a delayed job, you can do like so:\n\n```ruby\n# after you've enqueued a job like:\nResque.enqueue_at(5.days.from_now, SendFollowUpEmail, :user_id =\u003e current_user.id)\n# remove the job with exactly the same parameters:\nResque.remove_delayed(SendFollowUpEmail, :user_id =\u003e current_user.id)\n```\n\nIf 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:\n\n``` ruby\n# after you've enqueued a job like:\nResque.enqueue_at(5.days.from_now, SendFollowUpEmail, :account_id =\u003e current_account.id, :user_id =\u003e current_user.id)\n# remove jobs matching just the account:\nResque.remove_delayed_selection { |args| args[0]['account_id'] == current_account.id }\n# or remove jobs matching just the user:\nResque.remove_delayed_selection { |args| args[0]['user_id'] == current_user.id }\n```\n\nIf you need to cancel a delayed job based on some matching arguments AND by which class the job is, but don't wish to specify each argument from when the job was created, you can do like so:\n\n``` ruby\n# after you've enqueued a job like:\nResque.enqueue_at(5.days.from_now, SendFollowUpEmail, :account_id =\u003e current_account.id, :user_id =\u003e current_user.id)\n# remove jobs matching just the account and that were of the class SendFollowUpEmail:\nResque.remove_delayed_selection(SendFollowUpEmail) { |args| args[0]['account_id'] == current_account.id }\n# or remove jobs matching just the user and that were of the class SendFollowUpEmail:\nResque.remove_delayed_selection(SendFollowUpEmail) { |args| args[0]['user_id'] == current_user.id }\n```\n\nIf 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:\n\n``` ruby\n# after you've enqueued a job like:\nResque.enqueue_at(5.days.from_now, SendFollowUpEmail, :account_id =\u003e current_account.id, :user_id =\u003e current_user.id)\n# enqueue immediately jobs matching just the account:\nResque.enqueue_delayed_selection { |args| args[0]['account_id'] == current_account.id }\n# or enqueue immediately jobs matching just the user:\nResque.enqueue_delayed_selection { |args| args[0]['user_id'] == current_user.id }\n```\n\n#### Updating Delayed Jobs\n\nPreviously delayed jobs may be delayed even further into the future like so:\n\n```ruby\n# after you've enqueued a job like:\nResque.enqueue_at(1.minute.from_now, SendNotifications, :user_id =\u003e current_user.id)\n# delay running the job until two minutes from now\nResque.delay_or_enqueue_at(2.minutes.from_now, SendNotifications, :user_id =\u003e current_user.id)\n```\n\nYou don't need to worry if a matching job has already been queued, because if no matching jobs are found a new job is created and enqueued as if you had called `enqueue_at`. This means you don't need any special conditionals to know if a job has already been queued. You simply create the job like so:\n\n```ruby\nResque.delay_or_enqueue_at(1.minute.from_now, SendNotifications, :user_id =\u003e current_user.id)\n```\n\nIf multiple matching jobs are found, all of the matching jobs will be updated to have the same timestamp even if their original timestamps were not the same.\n\n```ruby\n# enqueue multiple jobs with different delay timestamps\nResque.enqueue_at(1.minute.from_now, SendNotifications, :user_id =\u003e current_user.id)\nResque.enqueue_at(2.minutes.from_now, SendNotifications, :user_id =\u003e current_user.id)\n\n# delay running the two jobs until 5 minutes from now\nResque.delay_or_enqueue_at(5.minutes.from_now, SendNotifications, :user_id =\u003e current_user.id)\n```\n\nThe most useful case for increasing the delay of an already delayed job is to batch together work based on multiple events. For example, if you wanted to send a notification email to a user when an event triggers but didn't want to send 10 emails if many events happened within a short period, you could use this technique to delay the noficication email until no events have triggered for a period of time. This way you could send 1 email containing the 10 notifications once no events have triggered for 2 minutes. You could implement this like so:\n\n```ruby\n# Send a notification when an event is created.\n# app/models/event.rb\nafter_commit on: :create do\n  Resque.delay_or_enqueue_in(2.minutes, SendNotifications, :user_id =\u003e user.id)\nend\n```\n\nWhen the first event is created a job will be scheduled to send unsent notifications to the associated user. If another event is created within the 2 minute window, the timer will be reset to 2 minutes. This will continue as long as new events are created for the specific user before the 2 minute timer expires. Once the timer expires and the job is scheduled any new events that are created will schedule a new job and start the process over. By adjusting the window you can tweak the trade-off between sending notification emails quickly after an event happens and sending fewer emails.\n\nRead more in the [original PR](https://github.com/resque/resque-scheduler/pull/645)\n\n\n### Scheduled Jobs (Recurring Jobs)\n\nScheduled (or recurring) jobs are logically no different than a standard cron\njob.  They are jobs that run based on a schedule which can be static or dynamic.\n\n#### Static schedules\n\nStatic schedules are set when `resque-scheduler` starts by passing a schedule file\nto `resque-scheduler` initialization like this (see *Installation* above for a more complete example):\n\n```ruby\nResque.schedule = YAML.load_file('your_resque_schedule.yml')\n```\n\nIf a static schedule is not set `resque-scheduler` will issue a \"Schedule empty!\" warning on\nstartup, but despite that warning setting a static schedule is totally optional. It is possible\nto use only dynamic schedules (see below).\n\nThe schedule file is a list of Resque job classes with arguments and a\nschedule frequency (in crontab syntax).  The schedule is just a hash, but\nis usually stored in a YAML like this:\n\n```yaml\nCancelAbandonedOrders:\n  cron: \"*/5 * * * *\"\n\nqueue_documents_for_indexing:\n  cron: \"0 0 * * *\"\n  # you can use rufus-scheduler \"every\" syntax in place of cron if you prefer\n  # every: 1h\n  # By default the job name (hash key) will be taken as worker class name.\n  # If you want to have a different job name and class name, provide the 'class' option\n  class: \"QueueDocuments\"\n  queue: high\n  args:\n  description: \"This job queues all content for indexing in solr\"\n\nclear_leaderboards_contributors:\n  cron: \"30 6 * * 1\"\n  class: \"ClearLeaderboards\"\n  queue: low\n  args: contributors\n  description: \"This job resets the weekly leaderboard for contributions\"\n```\n\nIf you would like to setup a job that is executed manually you can configure like this in your YAML file.\n\n```yaml\nImportOrdersManual:\n  custom_job_class: 'AmazonMws::ImportOrdersJob'\n  never: \"* * * * *\"\n  queue: high\n  description: \"This is a manual job for importing orders.\"\n  args:\n    days_in_arrears: 7\n```\n\nThe queue value is optional, but if left unspecified resque-scheduler will\nattempt to get the queue from the job class, which means it needs to be\ndefined.  If you're getting \"uninitialized constant\" errors, you probably\nneed to either set the queue in the schedule or require your jobs in your\n\"resque:setup\" rake task.\n\nYou can provide options to \"every\" or \"cron\" via Array:\n\n```yaml\nclear_leaderboards_moderator:\n  every:\n    - \"30s\"\n    - :first_in: '120s'\n  class: \"CheckDaemon\"\n  queue: daemons\n  description: \"This job will check Daemon every 30 seconds after 120 seconds after start\"\n```\n\nIMPORTANT: Rufus `every` syntax will calculate jobs scheduling time starting from the moment of deploy,\nresulting in resetting schedule time on every deploy, so it's probably a good idea to use it only for\nfrequent jobs (like every 10-30 minutes), otherwise - when you use something like `every 20h` and deploy once-twice per day -\nit will schedule the job for 20 hours from deploy, resulting in a job to never be run.\n\n**NOTE**: Six parameter cron's are also supported (as they supported by\nrufus-scheduler which powers the resque-scheduler process).  This allows you\nto schedule jobs per second (ie: `\"30 * * * * *\"` would fire a job every 30\nseconds past the minute).\n\nA big shout out to [rufus-scheduler](http://github.com/jmettraux/rufus-scheduler)\nfor handling the heavy lifting of the actual scheduling engine.\n\n##### Queue with parameters\n\nIt's possible to specify parameters, that must be given by the user when they manually queue the job. To enable this feature add `parameters` key to scheduled job definition.\n\n```yaml\nqueue_documents_for_indexing:\n  cron: \"0 0 * * *\"\n  class: \"QueueDocuments\"\n  queue: high\n  args:\n    foo: \"bar\"\n    a: \"b\"\n  parameters:\n    foo:\n      description: \"value of foo\"\n      default: \"baz\"\n\n  description: \"This job queues all content for indexing in solr\"\n```\n\nOne can use following options for each parameter:\n* description - tooltip to be shown next to the parameter input\n* default - prefilled value in the parameter input\n\n**NOTE**: When sheduling the job, parameters are merged into job args. Assuming the example above and default parametr value, the job will be run with the following args:\n\n```ruby\n{\"foo\"=\u003e\"baz\", \"a\"=\u003e\"b\"}\n```\n\n**NOTE**: If user leaves the parameter value empty, it'll be sent as empty string.\n\n#### Dynamic schedules\n\nDynamic schedules are programmatically set on a running `resque-scheduler`.\nMost [rufus-scheduler](http://github.com/jmettraux/rufus-scheduler) options are supported\nwhen setting schedules. Specifically the `overlap` option will not work.\n\nDynamic schedules are not enabled by default. To be able to dynamically set schedules, you\nmust pass the following to `resque-scheduler` initialization (see *Installation* above for a more complete example):\n\n```ruby\nResque::Scheduler.dynamic = true\n```\n\n**NOTE**: In order to delete dynamic schedules via `resque-web` in the\n\"Schedule\" tab, you must include the `Rack::MethodOverride` middleware (in\n`config.ru` or equivalent).\n\nDynamic schedules allow for greater flexibility than static schedules as they can be set,\nunset or changed without having to restart `resque-scheduler`. You can specify, if the schedule\nmust survive a resque-scheduler restart or not. This is done by setting the `persist` configuration\nfor the schedule: it is a boolean value, if set the schedule will persist a restart. By default,\na schedule will not be persisted.\n\nThe job to be scheduled must be a valid Resque job class.\n\nFor example, suppose you have a SendEmail job which sends emails. The `perform` method of the\njob receives a string argument with the email subject. To run the SendEmail job every hour\nstarting five minutes from now, you can do:\n\n```ruby\nname = 'send_emails'\nconfig = {}\nconfig[:class] = 'SendEmail'\nconfig[:args] = 'POC email subject'\nconfig[:every] = ['1h', {first_in: 5.minutes}]\nconfig[:persist] = true\nResque.set_schedule(name, config)\n```\n\nSchedules can later be removed by passing their name to the `remove_schedule` method:\n\n```ruby\nname = 'send_emails'\nResque.remove_schedule(name)\n```\n\nSchedule names are unique; i.e. two dynamic schedules cannot have the same name. If `set_schedule` is\npassed the name of an existing schedule, that schedule is updated. E.g. if after setting the above schedule\n we want the job to run every day instead of every hour from now on, we can do:\n\n```ruby\nname = 'send_emails'\nconfig = {}\nconfig[:class] = 'SendEmail'\nconfig[:args] = 'POC email subject'\nconfig[:every] = '1d'\nResque.set_schedule(name, config)\n```\n\n#### Time zones\n\nIf you use the cron syntax, by default it is interpreted in the server time zone.\nYou can explicitly specify the time zone that rufus-scheduler will use:\n```yaml\ncron: \"30 6 * * 1 Europe/Stockholm\"\n```\n\n##### Rails\nIn Rails, `config.time_zone` will be used to determine the time zone for `resque-scheduler`.\n\nNote that `config.time_zone` allows for a shorthand (e.g. \"Stockholm\")\nthat rufus-scheduler does not accept, so make sure it's the right format, e.g. with:\n\n```ruby\nActiveSupport::TimeZone.find_tzinfo(Rails.configuration.time_zone).name\n```\n\nA future version of resque-scheduler may do this for you.\n\n#### Hooks\n\nSimilar to the `before_enqueue`- and `after_enqueue`-hooks provided in Resque\n(\u003e= 1.19.1), your jobs can specify one or more of the following hooks:\n\n* `before_schedule`: Called with the job args before a job is placed on\n  the delayed queue. If the hook returns `false`, the job will not be placed on\n  the queue.\n* `after_schedule`: Called with the job args after a job is placed on the\n  delayed queue. Any exception raised propagates up to the code with queued the\n  job.\n* `before_delayed_enqueue`: Called with the job args after the job has been\n  removed from the delayed queue, but not yet put on a normal queue. It is\n  called before `before_enqueue`-hooks, and on the same job instance as the\n  `before_enqueue`-hooks will be invoked on. Return values are ignored.\n* `on_enqueue_failure`: Called with the job args and the exception that was raised\n  while enqueueing a job to resque or external application fails.  Return\n  values are ignored. For example:\n\n  ```ruby\n  Resque::Scheduler.failure_handler = ExceptionHandlerClass\n  ```\n\n#### Support for resque-status (and other custom jobs)\n\nSome Resque extensions like\n[resque-status](http://github.com/quirkey/resque-status) use custom job\nclasses with a slightly different API signature.  Resque-scheduler isn't\ntrying to support all existing and future custom job classes, instead it\nsupports a schedule flag so you can extend your custom class and make it\nsupport scheduled job.\n\nLet's pretend we have a `JobWithStatus` class called `FakeLeaderboard`\n\n```ruby\nclass FakeLeaderboard \u003c Resque::JobWithStatus\n  def perform\n    # do something and keep track of the status\n  end\nend\n```\n\nAnd then a schedule:\n\n```yaml\ncreate_fake_leaderboards:\n  cron: \"30 6 * * 1\"\n  queue: scoring\n  custom_job_class: \"FakeLeaderboard\"\n  args:\n  rails_env: demo\n  description: \"This job will auto-create leaderboards for our online demo and the status will update as the worker makes progress\"\n```\n\nIf your extension doesn't support scheduled job, you would need to extend the\ncustom job class to support the #scheduled method:\n\n```ruby\nmodule Resque\n  class JobWithStatus\n    # Wrapper API to forward a Resque::Job creation API call into\n    # a JobWithStatus call.\n    def self.scheduled(queue, klass, *args)\n      create(*args)\n    end\n  end\nend\n```\n\n### Redundancy and Fail-Over\n\n*\u003e= 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.*\n\nYou may want to have resque-scheduler running on multiple machines for\nredundancy.  Electing a master and failover is built in and default.  Simply\nrun resque-scheduler on as many machine as you want pointing to the same\nredis instance and schedule.  The scheduler processes will use redis to\nelect a master process and detect failover when the master dies.  Precautions are\ntaken to prevent jobs from potentially being queued twice during failover even\nwhen the clocks of the scheduler machines are slightly out of sync (or load affects\nscheduled job firing time).  If you want the gory details, look at Resque::Scheduler::Locking.\n\nIf the scheduler process(es) goes down for whatever reason, the delayed items\nthat should have fired during the outage will fire once the scheduler process\nis started back up again (regardless of it being on a new machine).  Missed\nscheduled jobs, however, will not fire upon recovery of the scheduler process.\nThink of scheduled (recurring) jobs as cron jobs - if you stop cron, it doesn't fire\nmissed jobs once it starts back up.\n\nYou might want to share a redis instance amongst multiple Rails applications with different\nscheduler with different config yaml files. If this is the case, normally, only one will ever\nrun, leading to undesired behaviour. To allow different scheduler configs run at the same time\non one redis, you can either namespace your redis connections, or supply an environment variable\nto split the shared lock key resque-scheduler uses thus:\n\n``` bash\nRESQUE_SCHEDULER_MASTER_LOCK_PREFIX=MyApp: rake resque:scheduler\n```\n\n### resque-web Additions\n\nResque-scheduler also adds two tabs to the resque-web UI.  One is for viewing\n(and manually queueing) the schedule and one is for viewing pending jobs in\nthe delayed queue.\n\nThe Schedule tab:\n\n![The Schedule Tab](https://f.cloud.github.com/assets/45143/1178456/c99e5568-21b0-11e3-8c57-e1305d0ee8ef.png)\n\nThe Delayed tab:\n\n![The Delayed Tab](http://img.skitch.com/20100111-ne4fcqtc5emkcuwc5qtais2kwx.jpg)\n\n#### How do I get the schedule tabs to show up???\n\nTo get these to show up you need to pass a file to `resque-web` to tell it to\ninclude the `resque-scheduler` plugin and the resque-schedule server extension\nto the resque-web sinatra app.  Unless you're running redis on localhost, you\nprobably already have this file.  It probably looks something like this:\n\n```ruby\nrequire 'resque' # include resque so we can configure it\nResque.redis = \"redis_server:6379\" # tell Resque where redis lives\n```\n\nNow, you want to add the following:\n\n```ruby\n# This will make the tabs show up.\nrequire 'resque-scheduler'\nrequire 'resque/scheduler/server'\n```\n\nThat should make the scheduler tabs show up in `resque-web`.\n\nYou'll want to make sure you load the schedule in this file as well.\nSomething like this:\n\n```ruby\nResque.schedule = YAML.load_file(File.join(RAILS_ROOT, 'config/resque_schedule.yml')) # load the schedule\n```\n\nNow make sure you're passing that file to resque-web like so:\n\n    resque-web ~/yourapp/config/resque_config.rb\n\n\n### Running in the background\n\nThere are scenarios where it's helpful for\nthe resque worker to run itself in the background (usually in combination with\nPIDFILE).  Use the BACKGROUND option so that rake will return as soon as the\nworker is started.\n\n    $ PIDFILE=./resque-scheduler.pid BACKGROUND=yes \\\n        rake resque:scheduler\n\n\n### Logging\n\nThere are several options to toggle the way scheduler logs its actions. They\nare toggled by environment variables:\n\n  - `QUIET` will stop logging anything. Completely silent.\n  - `VERBOSE` opposite of 'QUIET'; will log even debug information\n  - `LOGFILE` specifies the file to write logs to. (default standard output)\n  - `LOGFORMAT` specifies either \"text\", \"json\" or \"logfmt\" output format\n    (default \"text\")\n\nAll of these variables are optional and will be given the following default\nvalues:\n\n```ruby\nResque::Scheduler.configure do |c|\n  c.quiet = false\n  c.verbose = false\n  c.logfile = nil # meaning all messages go to $stdout\n  c.logformat = 'text'\nend\n```\n\n### Polling frequency\n\nYou can pass a `RESQUE_SCHEDULER_INTERVAL` option which is an integer or\nfloat representing the polling frequency. The default is 5 seconds, but\nfor a semi-active app you may want to use a smaller value.\n\n    $ RESQUE_SCHEDULER_INTERVAL=1 rake resque:scheduler\n\n**NOTE** This value was previously `INTERVAL` but was renamed to\n`RESQUE_SCHEDULER_INTERVAL` to avoid clashing with the interval Resque\nuses for its jobs.\n\n### Plagiarism alert\n\nThis was intended to be an extension to resque and so resulted in a lot\nof the code looking very similar to resque, particularly in resque-web\nand the views. I wanted it to be similar enough that someone familiar\nwith resque could easily work on resque-scheduler.\n\n### Development\n\nWorking on resque-scheduler requires the following:\n\n* A relatively modern Ruby interpreter\n* bundler\n\nThe development setup looks like this, which is roughly the same thing\nthat happens on Travis CI and Appveyor:\n\n``` bash\n# Install everything\nbundle install\n\n# Make sure tests are green before you change stuff\nbundle exec rubocop \u0026\u0026 bundle exec rake\n# Change stuff\n# Repeat\n```\n\nIf you have [vagrant](http://www.vagrantup.com) installed, there is a\ndevelopment box available that requires no plugins or external\nprovisioners:\n\n``` bash\nvagrant up\n```\n\n### Deployment Notes\n\nIt is recommended that a production deployment of `resque-scheduler` be hosted\non a dedicated Redis database.  While making and managing scheduled tasks,\n`resque-scheduler` currently scans the entire Redis keyspace, which may cause\nlatency and stability issues if `resque-scheduler` is hosted on a Redis instance\nstoring a large number of keys (such as those written by a different system\nhosted on the same Redis instance).\n\n#### Compatibility Notes\n\nDifferent versions of the `redis` and `rufus-scheduler` gems are needed\ndepending on your version of `resque-scheduler`.  This is typically not a\nproblem with `resque-scheduler` itself, but when mixing dependencies with an\nexisting application.\n\nThis table explains the version requirements for redis gem\n\n| resque-scheduler | redis gem  |\n|:-----------------|-----------:|\n| `~\u003e 2.0`         | `\u003e= 3.0.0` |\n| `\u003e= 0.0.1`       | `~\u003e 1.3`   |\n\nThis table explains the version requirements for rufus-scheduler\n\n| resque-scheduler | rufus-scheduler |\n|:-----------------|----------------:|\n| `~\u003e 4.0`         | `~\u003e 3.0`        |\n| `\u003c 4.0`          | `~\u003e 2.0`        |\n\n\n### Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md)\n\n### Authors\n\nSee [AUTHORS.md](AUTHORS.md)\n\n### License\n\nSee [LICENSE](LICENSE)\n","funding_links":["https://github.com/sponsors/iloveitaly"],"categories":["Scheduling","Gems"],"sub_categories":["Scheduling"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fresque%2Fresque-scheduler","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fresque%2Fresque-scheduler","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fresque%2Fresque-scheduler/lists"}