{"id":13395064,"url":"https://github.com/resque/resque","last_synced_at":"2025-05-12T18:38:00.850Z","repository":{"id":634535,"uuid":"275604","full_name":"resque/resque","owner":"resque","description":"Resque is a Redis-backed Ruby library for creating background jobs, placing them on multiple queues, and processing them later.","archived":false,"fork":false,"pushed_at":"2025-01-06T12:56:33.000Z","size":2614,"stargazers_count":9457,"open_issues_count":86,"forks_count":1660,"subscribers_count":251,"default_branch":"master","last_synced_at":"2025-05-05T16:01:22.249Z","etag":null,"topics":["asynchronous-tasks","asynctask","background-jobs","background-service","background-worker","job-management","job-queue","job-scheduler","queue","ruby"],"latest_commit_sha":null,"homepage":"http://resque.github.io/","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.markdown","changelog":"HISTORY.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["iloveitaly"]}},"created_at":"2009-08-12T00:27:35.000Z","updated_at":"2025-05-05T07:45:41.000Z","dependencies_parsed_at":"2023-01-16T17:48:30.925Z","dependency_job_id":"fff7d83e-d020-4640-8f52-ba1719d742ed","html_url":"https://github.com/resque/resque","commit_stats":{"total_commits":1497,"total_committers":300,"mean_commits":4.99,"dds":0.5871743486973948,"last_synced_commit":"da70131fb6d48aa6cb6f58a8a28b9014f620bfb0"},"previous_names":[],"tags_count":85,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/resque%2Fresque","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/resque%2Fresque/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/resque%2Fresque/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/resque%2Fresque/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/resque","download_url":"https://codeload.github.com/resque/resque/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252663601,"owners_count":21784787,"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":["asynchronous-tasks","asynctask","background-jobs","background-service","background-worker","job-management","job-queue","job-scheduler","queue","ruby"],"created_at":"2024-07-30T17:01:40.816Z","updated_at":"2025-05-12T18:38:00.812Z","avatar_url":"https://github.com/resque.png","language":"Ruby","readme":"Resque\n======\n\n[![Gem Version](https://badge.fury.io/rb/resque.svg)](https://rubygems.org/gems/resque)\n[![Build Status](https://github.com/resque/resque/actions/workflows/ci.yml/badge.svg)](https://github.com/resque/resque/actions/workflows/ci.yml)\n\nIntroduction\n------------\n\nResque (pronounced like \"rescue\") is a Redis-backed library for creating\nbackground jobs, placing those jobs on multiple queues, and processing\nthem later.\n\nFor the backstory, philosophy, and history of Resque's beginnings, please see [the blog post](http://github.com/blog/542-introducing-resque) (2009).\n\nBackground jobs can be any Ruby class or module that responds to\n`perform`. Your existing classes can easily be converted to background\njobs or you can create new classes specifically to do work. Or, you\ncan do both.\n\nResque is heavily inspired by DelayedJob (which rocks) and comprises\nthree parts:\n\n1. A Ruby library for creating, querying, and processing jobs\n2. A Rake task for starting a worker which processes jobs\n3. A Sinatra app for monitoring queues, jobs, and workers.\n\nResque workers can be  given multiple queues (a \"queue list\"),\ndistributed between multiple machines,\nrun anywhere with network access to the Redis server,\nsupport priorities, are resilient to memory bloat / \"leaks,\"\ntell you what they're doing, and expect failure.\n\nResque queues are persistent; support constant time, atomic push and\npop (thanks to Redis); provide visibility into their contents; and\nstore jobs as simple JSON packages.\n\nThe Resque frontend tells you what workers are doing, what workers are\nnot doing, what queues you're using, what's in those queues, provides\ngeneral usage stats, and helps you track failures.\n\nResque now supports Ruby 2.3.0 and above.\nWe will also only be supporting Redis 3.0 and above going forward.\n\n### Note on the future of Resque\n\nWould you like to be involved in Resque? Do you have thoughts about what\nResque should be and do going forward? There's currently an [open discussion here](https://github.com/resque/resque/issues/1759)\non just that topic, so please feel free to join in. We'd love to hear your thoughts\nand/or have people volunteer to be a part of the project!\n\nExample\n-------\n\nResque jobs are Ruby classes (or modules) which respond to the\n`perform` method. Here's an example:\n\n\n``` ruby\nclass Archive\n  @queue = :file_serve\n\n  def self.perform(repo_id, branch = 'master')\n    repo = Repository.find(repo_id)\n    repo.create_archive(branch)\n  end\nend\n```\n\nThe `@queue` class instance variable determines which queue `Archive`\njobs will be placed in. Queues are arbitrary and created on the fly -\nyou can name them whatever you want and have as many as you want.\n\nTo place an `Archive` job on the `file_serve` queue, we might add this\nto our application's pre-existing `Repository` class:\n\n``` ruby\nclass Repository\n  def async_create_archive(branch)\n    Resque.enqueue(Archive, self.id, branch)\n  end\nend\n```\n\nNow when we call `repo.async_create_archive('masterbrew')` in our\napplication, a job will be created and placed on the `file_serve`\nqueue.\n\nLater, a worker will run something like this code to process the job:\n\n``` ruby\nklass, args = Resque.reserve(:file_serve)\nklass.perform(*args) if klass.respond_to? :perform\n```\n\nWhich translates to:\n\n``` ruby\nArchive.perform(44, 'masterbrew')\n```\n\nLet's start a worker to run `file_serve` jobs:\n\n    $ cd app_root\n    $ QUEUE=file_serve rake resque:work\n\nThis starts one Resque worker and tells it to work off the\n`file_serve` queue. As soon as it's ready it'll try to run the\n`Resque.reserve` code snippet above and process jobs until it can't\nfind any more, at which point it will sleep for a small period and\nrepeatedly poll the queue for more jobs.\n\nInstallation\n------------\n\nAdd the gem to your Gemfile:\n\n    gem 'resque'\n\nNext, install it with Bundler:\n\n    $ bundle\n\n#### Rack\n\nIn your Rakefile, or some other file in `lib/tasks` (ex: `lib/tasks/resque.rake`), load the resque rake tasks:\n\n``` ruby\nrequire 'resque'\nrequire 'resque/tasks'\nrequire 'your/app' # Include this line if you want your workers to have access to your application\n```\n\n#### Rails\n\n##### Rails 7.1\n\nIf you're using Rails 7.1.x, use [rack-session version 1.0.2](https://rubygems.org/gems/rack-session/versions/1.0.2). This is because resque-web's dependency, [Sinatra, isn't compatible with rack 3.0](https://github.com/sinatra/sinatra/issues/1797), which is [required by rack-session 2.0.0](https://rubygems.org/gems/rack-session/versions/2.0.0).\n\n```\n  gem 'rails', '~\u003e 7.1'\n  gem 'rack-session', '~\u003e 1.0', '\u003e= 1.0.2'\n```\n\nTo make resque specific changes, you can override the `resque:setup` job in `lib/tasks` (ex: `lib/tasks/resque.rake`). GitHub's setup task looks like this:\n\n``` ruby\ntask \"resque:setup\" =\u003e :environment do\n  Grit::Git.git_timeout = 10.minutes\nend\n```\n\nWe don't want the `git_timeout` as high as 10 minutes in our web app,\nbut in the Resque workers it's fine.\n\nRunning Workers\n---------------\n\nResque workers are rake tasks that run forever. They basically do this:\n\n``` ruby\nstart\nloop do\n  if job = reserve\n    job.process\n  else\n    sleep 5 # Polling frequency = 5\n  end\nend\nshutdown\n```\n\nStarting a worker is simple:\n\n    $ QUEUE=* rake resque:work\n\nOr, you can start multiple workers:\n\n    $ COUNT=2 QUEUE=* rake resque:workers\n\nThis will spawn two Resque workers, each in its own process. Hitting\nctrl-c should be sufficient to stop them all.\n\n#### Priorities and Queue Lists\n\nResque doesn't support numeric priorities but instead uses the order\nof queues you give it. We call this list of queues the \"queue list.\"\n\nLet's say we add a `warm_cache` queue in addition to our `file_serve`\nqueue. We'd now start a worker like so:\n\n    $ QUEUES=file_serve,warm_cache rake resque:work\n\nWhen the worker looks for new jobs, it will first check\n`file_serve`. If it finds a job, it'll process it then check\n`file_serve` again. It will keep checking `file_serve` until no more\njobs are available. At that point, it will check `warm_cache`. If it\nfinds a job it'll process it then check `file_serve` (repeating the\nwhole process).\n\nIn this way you can prioritize certain queues. At GitHub we start our\nworkers with something like this:\n\n    $ QUEUES=critical,archive,high,low rake resque:work\n\nNotice the `archive` queue - it is specialized and in our future\narchitecture will only be run from a single machine.\n\nAt that point we'll start workers on our generalized background\nmachines with this command:\n\n    $ QUEUES=critical,high,low rake resque:work\n\nAnd workers on our specialized archive machine with this command:\n\n    $ QUEUE=archive rake resque:work\n\n#### Running All Queues\n\nIf you want your workers to work off of every queue, including new\nqueues created on the fly, you can use a splat:\n\n    $ QUEUE=* rake resque:work\n\nQueues will be processed in alphabetical order.\n\nOr, prioritize some queues above `*`:\n\n    # QUEUE=critical,* rake resque:work\n\n#### Running All Queues Except for Some\n\nIf you want your workers to work off of all queues except for some,\nyou can use negation:\n\n    $ QUEUE=*,!low rake resque:work\n\nNegated globs also work. The following will instruct workers to work\noff of all queues except those beginning with `file_`:\n\n    $ QUEUE=*,!file_* rake resque:work\n\nNote that the order in which negated queues are specified does not\nmatter, so `QUEUE=*,!file_*` and `QUEUE=!file_*,*` will have the same\neffect.\n\n#### Process IDs (PIDs)\n\nThere are scenarios where it's helpful to record the PID of a resque\nworker process.  Use the PIDFILE option for easy access to the PID:\n\n    $ PIDFILE=./resque.pid QUEUE=file_serve rake resque:work\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.pid BACKGROUND=yes QUEUE=file_serve rake resque:work\n\n#### Polling frequency\n\nYou can pass an INTERVAL option which is a float representing the polling frequency.\nThe default is 5 seconds, but for a semi-active app you may want to use a smaller value.\n\n    $ INTERVAL=0.1 QUEUE=file_serve rake resque:work\n\nWhen INTERVAL is set to 0 it will run until the queue is empty and then\nshutdown the worker, instead of waiting for new jobs.\n\nThe Front End\n-------------\n\nResque comes with a Sinatra-based front end for seeing what's up with\nyour queue.\n\n![The Front End](https://camo.githubusercontent.com/64d150a243987ffbc33f588bd6d7722a0bb8d69a/687474703a2f2f7475746f7269616c732e6a756d7073746172746c61622e636f6d2f696d616765732f7265737175655f6f766572766965772e706e67)\n\n#### Standalone\n\nIf you've installed Resque as a gem running the front end standalone is easy:\n\n    $ resque-web\n\nIt's a thin layer around `rackup` so it's configurable as well:\n\n    $ resque-web -p 8282\n\nIf you have a Resque config file you want evaluated just pass it to\nthe script as the final argument:\n\n    $ resque-web -p 8282 rails_root/config/initializers/resque.rb\n\nYou can also set the namespace directly using `resque-web`:\n\n    $ resque-web -p 8282 -N myapp\n\nor set the Redis connection string if you need to do something like select a different database:\n\n    $ resque-web -p 8282 -r localhost:6379:2\n\n#### Passenger\n\nUsing Passenger? Resque ships with a `config.ru` you can use. See\nPhusion's guide:\n\nApache: \u003chttps://www.phusionpassenger.com/library/deploy/apache/deploy/ruby/\u003e\nNginx: \u003chttps://www.phusionpassenger.com/library/deploy/nginx/deploy/ruby/\u003e\n\n#### Rack::URLMap\n\nIf you want to load Resque on a subpath, possibly alongside other\napps, it's easy to do with Rack's `URLMap`:\n\n``` ruby\nrequire 'resque/server'\n\nrun Rack::URLMap.new \\\n  \"/\"       =\u003e Your::App.new,\n  \"/resque\" =\u003e Resque::Server.new\n```\n\nCheck `examples/demo/config.ru` for a functional example (including\nHTTP basic auth).\n\n#### Rails\n\nYou can also mount Resque on a subpath in your existing Rails app by adding `require 'resque/server'` to the top of your routes file or in an initializer then adding this to `routes.rb`:\n\n``` ruby\nmount Resque::Server.new, :at =\u003e \"/resque\"\n```\n\nJobs\n----\n\nWhat should you run in the background? Anything that takes any time at\nall. Slow INSERT statements, disk manipulating, data processing, etc.\n\nAt GitHub we use Resque to process the following types of jobs:\n\n* Warming caches\n* Counting disk usage\n* Building tarballs\n* Building Rubygems\n* Firing off web hooks\n* Creating events in the db and pre-caching them\n* Building graphs\n* Deleting users\n* Updating our search index\n\nAs of writing we have about 35 different types of background jobs.\n\nKeep in mind that you don't need a web app to use Resque - we just\nmention \"foreground\" and \"background\" because they make conceptual\nsense. You could easily be spidering sites and sticking data which\nneeds to be crunched later into a queue.\n\n#### Persistence\n\nJobs are persisted to queues as JSON objects. Let's take our `Archive`\nexample from above. We'll run the following code to create a job:\n\n``` ruby\nrepo = Repository.find(44)\nrepo.async_create_archive('masterbrew')\n```\n\nThe following JSON will be stored in the `file_serve` queue:\n\n``` javascript\n{\n    'class': 'Archive',\n    'args': [ 44, 'masterbrew' ]\n}\n```\n\nBecause of this your jobs must only accept arguments that can be JSON encoded.\n\nSo instead of doing this:\n\n``` ruby\nResque.enqueue(Archive, self, branch)\n```\n\ndo this:\n\n``` ruby\nResque.enqueue(Archive, self.id, branch)\n```\n\nThis is why our above example (and all the examples in `examples/`)\nuses object IDs instead of passing around the objects.\n\nWhile this is less convenient than just sticking a marshaled object\nin the database, it gives you a slight advantage: your jobs will be\nrun against the most recent version of an object because they need to\npull from the DB or cache.\n\nIf your jobs were run against marshaled objects, they could\npotentially be operating on a stale record with out-of-date information.\n\n\n#### send_later / async\n\nWant something like DelayedJob's `send_later` or the ability to use\ninstance methods instead of just methods for jobs? See the `examples/`\ndirectory for goodies.\n\nWe plan to provide first class `async` support in a future release.\n\n\n#### Failure\n\nIf a job raises an exception, it is logged and handed off to the\n`Resque::Failure` module. Failures are logged either locally in Redis\nor using some different backend. To see exceptions while developing,\nsee details below under Logging.\n\nFor example, Resque ships with Airbrake support. To configure it, put\nthe following into an initialisation file or into your rake job:\n\n``` ruby\n# send errors which occur in background jobs to redis and airbrake\nrequire 'resque/failure/multiple'\nrequire 'resque/failure/redis'\nrequire 'resque/failure/airbrake'\n\nResque::Failure::Multiple.classes = [Resque::Failure::Redis, Resque::Failure::Airbrake]\nResque::Failure.backend = Resque::Failure::Multiple\n```\n\nKeep this in mind when writing your jobs: you may want to throw\nexceptions you would not normally throw in order to assist debugging.\n\n\n#### Rails example\n\nIf you are using ActiveJob here's how your job definition will look:\n\n``` ruby\nclass ArchiveJob \u003c ApplicationJob\n  queue_as :file_serve\n\n  def perform(repo_id, branch = 'master')\n    repo = Repository.find(repo_id)\n    repo.create_archive(branch)\n  end\nend\n```\n\n``` ruby\nclass Repository\n  def async_create_archive(branch)\n    ArchiveJob.perform_later(self.id, branch)\n  end\nend\n```\n\nIt is important to run `ArchiveJob.perform_later(self.id, branch)` rather than `Resque.enqueue(Archive, self.id, branch)`.\nOtherwise Resque will process the job without actually doing anything.\nEven if you put an obviously buggy line like `0/0` in the `perform` method,\nthe job will still succeed.\n\n\nConfiguration\n-------------\n\n#### Redis\n\nYou may want to change the Redis host and port Resque connects to, or\nset various other options at startup.\n\nResque has a `redis` setter which can be given a string or a Redis\nobject. This means if you're already using Redis in your app, Resque\ncan re-use the existing connection.\n\nString: `Resque.redis = 'localhost:6379'`\n\nRedis: `Resque.redis = $redis`\n\nFor our rails app we have a `config/initializers/resque.rb` file where\nwe load `config/resque.yml` by hand and set the Redis information\nappropriately.\n\nHere's our `config/resque.yml`:\n\n    development: localhost:6379\n    test: localhost:6379\n    staging: redis1.se.github.com:6379\n    fi: localhost:6379\n    production: \u003c%= ENV['REDIS_URL'] %\u003e\n\nAnd our initializer:\n\n``` ruby\nrails_root = ENV['RAILS_ROOT'] || File.dirname(__FILE__) + '/../..'\nrails_env = ENV['RAILS_ENV'] || 'development'\nconfig_file = rails_root + '/config/resque.yml'\n\nresque_config = YAML::load(ERB.new(IO.read(config_file)).result)\nResque.redis = resque_config[rails_env]\n```\n\nEasy peasy! Why not just use `RAILS_ROOT` and `RAILS_ENV`? Because\nthis way we can tell our Sinatra app about the config file:\n\n    $ RAILS_ENV=production resque-web rails_root/config/initializers/resque.rb\n\nNow everyone is on the same page.\n\nAlso, you could disable jobs queueing by setting 'inline' attribute.\nFor example, if you want to run all jobs in the same process for cucumber, try:\n\n``` ruby\nResque.inline = ENV['RAILS_ENV'] == \"cucumber\"\n```\n\n#### Logging\n\nWorkers support basic logging to STDOUT.\n\nYou can control the logging threshold using `Resque.logger.level`:\n\n```ruby\n# config/initializers/resque.rb\nResque.logger.level = Logger::DEBUG\n```\n\nIf you want Resque to log to a file, in Rails do:\n\n```ruby\n# config/initializers/resque.rb\nResque.logger = Logger.new(Rails.root.join('log', \"#{Rails.env}_resque.log\"))\n```\n\n#### Namespaces\n\nIf you're running multiple, separate instances of Resque you may want\nto namespace the keyspaces so they do not overlap. This is not unlike\nthe approach taken by many memcached clients.\n\nThis feature is provided by the [redis-namespace](http://github.com/resque/redis-namespace) library, which\nResque uses by default to separate the keys it manages from other keys\nin your Redis server.\n\nSimply use the `Resque.redis.namespace` accessor:\n\n``` ruby\nResque.redis.namespace = \"resque:GitHub\"\n```\n\nWe recommend sticking this in your initializer somewhere after Redis\nis configured.\n\n#### Storing Statistics\n Resque allows to store count of processed and failed jobs.\n\n By default it will store it in Redis using the keys `stats:processed` and `stats:failed`.\n\n Some apps would want another stats store, or even a null store:\n\n ```ruby\n# config/initializers/resque.rb\nclass NullDataStore\n  def stat(stat)\n    0\n  end\n\n  def increment_stat(stat, by)\n  end\n\n  def decrement_stat(stat, by)\n  end\n\n  def clear_stat(stat)\n  end\nend\n\nResque.stat_data_store = NullDataStore.new\n```\n\nPlugins and Hooks\n-----------------\n\nFor a list of available plugins see\n\u003chttps://github.com/resque/resque/wiki/plugins\u003e.\n\nIf you'd like to write your own plugin, or want to customize Resque\nusing hooks (such as `Resque.after_fork`), see\n[docs/HOOKS.md](http://github.com/resque/resque/blob/master/docs/HOOKS.md).\n\n\nAdditional Information\n----------------------\n\n#### Resque vs DelayedJob\n\nHow does Resque compare to DelayedJob, and why would you choose one\nover the other?\n\n* Resque supports multiple queues\n* DelayedJob supports finer grained priorities\n* Resque workers are resilient to memory leaks / bloat\n* DelayedJob workers are extremely simple and easy to modify\n* Resque requires Redis\n* DelayedJob requires ActiveRecord\n* Resque can only place JSONable Ruby objects on a queue as arguments\n* DelayedJob can place _any_ Ruby object on its queue as arguments\n* Resque includes a Sinatra app for monitoring what's going on\n* DelayedJob can be queried from within your Rails app if you want to\n  add an interface\n\nIf you're doing Rails development, you already have a database and\nActiveRecord. DelayedJob is super easy to setup and works great.\nGitHub used it for many months to process almost 200 million jobs.\n\nChoose Resque if:\n\n* You need multiple queues\n* You don't care / dislike numeric priorities\n* You don't need to persist every Ruby object ever\n* You have potentially huge queues\n* You want to see what's going on\n* You expect a lot of failure / chaos\n* You can setup Redis\n* You're not running short on RAM\n\nChoose DelayedJob if:\n\n* You like numeric priorities\n* You're not doing a gigantic amount of jobs each day\n* Your queue stays small and nimble\n* There is not a lot failure / chaos\n* You want to easily throw anything on the queue\n* You don't want to setup Redis\n\nIn no way is Resque a \"better\" DelayedJob, so make sure you pick the\ntool that's best for your app.\n\n#### Forking\n\nOn certain platforms, when a Resque worker reserves a job it\nimmediately forks a child process. The child processes the job then\nexits. When the child has exited successfully, the worker reserves\nanother job and repeats the process.\n\nWhy?\n\nBecause Resque assumes chaos.\n\nResque assumes your background workers will lock up, run too long, or\nhave unwanted memory growth.\n\nIf Resque workers processed jobs themselves, it'd be hard to whip them\ninto shape. Let's say one is using too much memory: you send it a\nsignal that says \"shutdown after you finish processing the current\njob,\" and it does so. It then starts up again - loading your entire\napplication environment. This adds useless CPU cycles and causes a\ndelay in queue processing.\n\nPlus, what if it's using too much memory and has stopped responding to\nsignals?\n\nThanks to Resque's parent / child architecture, jobs that use too much memory\nrelease that memory upon completion. No unwanted growth.\n\nAnd what if a job is running too long? You'd need to `kill -9` it then\nstart the worker again. With Resque's parent / child architecture you\ncan tell the parent to forcefully kill the child then immediately\nstart processing more jobs. No startup delay or wasted cycles.\n\nThe parent / child architecture helps us keep tabs on what workers are\ndoing, too. By eliminating the need to `kill -9` workers we can have\nparents remove themselves from the global listing of workers. If we\njust ruthlessly killed workers, we'd need a separate watchdog process\nto add and remove them to the global listing - which becomes\ncomplicated.\n\nWorkers instead handle their own state.\n\n#### `at_exit` Callbacks\n\nResque uses `Kernel#exit!` for exiting its workers' child processes. So any `at_exit` callback defined in your application won't be executed when the job is finished and the child process exits.\n\nYou can alter this behavior by setting the `RUN_AT_EXIT_HOOKS` environment variable.\n\n#### Parents and Children\n\nHere's a parent / child pair doing some work:\n\n    $ ps -e -o pid,command | grep [r]esque\n    92099 resque: Forked 92102 at 1253142769\n    92102 resque: Processing file_serve since 1253142769\n\nYou can clearly see that process 92099 forked 92102, which has been\nworking since 1253142769.\n\n(By advertising the time they began processing you can easily use monit\nor god to kill stale workers.)\n\nWhen a parent process is idle, it lets you know what queues it is\nwaiting for work on:\n\n    $ ps -e -o pid,command | grep [r]esque\n    92099 resque: Waiting for file_serve,warm_cache\n\n\n#### Signals\n\nResque workers respond to a few different signals:\n\n* `QUIT` - Wait for child to finish processing then exit\n* `TERM` / `INT` - Immediately kill child then exit\n* `USR1` - Immediately kill child but don't exit\n* `USR2` - Don't start to process any new jobs\n* `CONT` - Start to process new jobs again after a USR2\n\nIf you want to gracefully shutdown a Resque worker, use `QUIT`.\n\nIf you want to kill a stale or stuck child, use `USR1`. Processing\nwill continue as normal unless the child was not found. In that case\nResque assumes the parent process is in a bad state and shuts down.\n\nIf you want to kill a stale or stuck child and shutdown, use `TERM`\n\nIf you want to stop processing jobs, but want to leave the worker running\n(for example, to temporarily alleviate load), use `USR2` to stop processing,\nthen `CONT` to start it again. It's also possible to [pause all workers](#pausing-all-workers).\n\n#### Heroku\n\nWhen shutting down processes, Heroku sends every process a TERM signal at the\nsame time. By default this causes an immediate shutdown of any running job\nleading to frequent `Resque::TermException` errors.  For short running jobs, a simple\nsolution is to give a small amount of time for the job to finish\nbefore killing it.\n\nResque doesn't handle this out of the box (for both cedar-14 and heroku-16), you need to\ninstall the [`resque-heroku-signals`](https://github.com/iloveitaly/resque-heroku-signals)\naddon which adds the required signal handling to make the behavior described above work.\nRelated issue: https://github.com/resque/resque/issues/1559\n\nTo accomplish this set the following environment variables:\n\n* `RESQUE_PRE_SHUTDOWN_TIMEOUT` - The time between the parent receiving a shutdown signal (TERM by default) and it sending that signal on to the child process. Designed to give the child process\ntime to complete before being forced to die.\n\n* `TERM_CHILD` - Must be set for `RESQUE_PRE_SHUTDOWN_TIMEOUT` to be used. After the timeout, if the child is still running it will raise a `Resque::TermException` and exit.\n\n* `RESQUE_TERM_TIMEOUT` - By default you have a few seconds to handle `Resque::TermException` in your job. `RESQUE_TERM_TIMEOUT` and `RESQUE_PRE_SHUTDOWN_TIMEOUT` must be lower than the [heroku dyno timeout](https://devcenter.heroku.com/articles/limits#exit-timeout).\n\n#### Pausing all workers\n\nWorkers will not process pending jobs if the Redis key `pause-all-workers` is set with the string value \"true\".\n\n``` ruby\nResque.redis.set('pause-all-workers', 'true')\n```\n\nNothing happens to jobs that are already being processed by workers.\n\nUnpause by removing the Redis key `pause-all-workers`.\n\n``` ruby\nResque.redis.del('pause-all-workers')\n```\n\n#### Monitoring\n\n##### god\n\nIf you're using god to monitor Resque, we have provided example\nconfigs in `examples/god/`. One is for starting / stopping workers,\nthe other is for killing workers that have been running too long.\n\n##### monit\n\nIf you're using monit, `examples/monit/resque.monit` is provided free\nof charge. This is **not** used by GitHub in production, so please\nsend patches for any tweaks or improvements you can make to it.\n\n#### Mysql::Error: MySQL server has gone away\n\nIf your workers remain idle for too long they may lose their MySQL connection. Depending on your version of Rails, we recommend the following:\n\n##### Rails\nIn your `perform` method, add the following line:\n\n``` ruby\nclass MyTask\n  def self.perform\n    ActiveRecord::Base.verify_active_connections!\n    # rest of your code\n  end\nend\n```\n\nThe Rails doc says the following about `verify_active_connections!`:\n\n    Verify active connections and remove and disconnect connections associated with stale threads.\n\n##### Rails 4.x\n\nIn your `perform` method, instead of `verify_active_connections!`, use:\n\n``` ruby\nclass MyTask\n  def self.perform\n    ActiveRecord::Base.clear_active_connections!\n    # rest of your code\n  end\nend\n```\n\nFrom the Rails docs on [`clear_active_connections!`](http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/ConnectionHandler.html#method-i-clear_active_connections-21):\n\n    Returns any connections in use by the current thread back to the pool, and also returns connections to the pool cached by threads that are no longer alive.\n\nDevelopment\n-----------\n\nWant to hack on Resque?\n\nFirst clone the repo and run the tests:\n\n    git clone git://github.com/resque/resque.git\n    cd resque\n    rake test\n\nIf the tests do not pass make sure you have Redis installed\ncorrectly (though we make an effort to tell you if we feel this is the\ncase). The tests attempt to start an isolated instance of Redis to\nrun against.\n\nAlso make sure you've installed all the dependencies correctly. For\nexample, try loading the `redis-namespace` gem after you've installed\nit:\n\n    $ irb\n    \u003e\u003e require 'rubygems'\n    =\u003e true\n    \u003e\u003e require 'redis/namespace'\n    =\u003e true\n\nIf you get an error requiring any of the dependencies, you may have\nfailed to install them or be seeing load path issues.\n\n#### Demo\nResque ships with a demo Sinatra app for creating jobs that are later\nprocessed in the background.\n\nTry it out by looking at the README, found at `examples/demo/README.markdown`.\n\n#### Contributing\n\nRead [CONTRIBUTING.md](CONTRIBUTING.md) first.\n\nOnce you've made your great commits:\n\n1. [Fork](http://help.github.com/forking/) Resque\n2. Create a topic branch - `git checkout -b my_branch`\n3. Push to your branch - `git push origin my_branch`\n4. Create a [Pull Request](http://help.github.com/pull-requests/) from your branch\n\nQuestions\n---------\n\nPlease add them to the [FAQ](https://github.com/resque/resque/wiki/FAQ) or open an issue on this repo.\n\nMeta\n----\n\n* Code: `git clone git://github.com/resque/resque.git`\n* Home: \u003chttp://github.com/resque/resque\u003e\n* Docs: \u003chttp://rubydoc.info/gems/resque\u003e\n* Bugs: \u003chttp://github.com/resque/resque/issues\u003e\n* Gems: \u003chttps://rubygems.org/gems/resque\u003e\n\nThis project uses [Semantic Versioning](http://semver.org/)\n\nAuthor\n------\n\nChris Wanstrath :: chris@ozmm.org :: @defunkt\n","funding_links":["https://github.com/sponsors/iloveitaly"],"categories":["Ruby","Scheduled/Recurrence Jobs","Background Processing","HarmonyOS","定时任务","Gems","Queue","Queues and Messaging","Most Stars Project on Github"],"sub_categories":["Omniauth","Background Jobs","Windows Manager"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fresque%2Fresque","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fresque%2Fresque","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fresque%2Fresque/lists"}