GithubHelp home page GithubHelp logo

resque-cleaner's Introduction

ResqueCleaner

github.com/ono/resque-cleaner

This project is not active. Please read this before you use the library.

Description

ResqueCleaner is a Resque plugin which aims to help you to clean up failed jobs on Resque by:

  • Showing stats of failed jobs
  • Retrying failed jobs
  • Removing failed jobs
  • Filtering failed jobs

Installation

Install as a gem:

$ gem install resque-cleaner

Resque-Web integration

Screen 1 Screen 2

Configuration

At first, you have to load ResqueCleaner to enable the Cleaner tab. Here is an example step.

  1. Create a configuration file for resque-web
    touch [app_dir]/config/resque-web.rb

  2. Add the following line into the file
    require 'resque-cleaner'

  3. Then pass the file when you start resque-web
    % resque-web [app_dir]/config/resque-web.rb

You can also configure limiter in the file.

e.g.

require 'resque-cleaner'
module Resque::Plugins
  ResqueCleaner::Limiter.default_maximum = 10_000
end

Console

Hopefully a situation of your failed jobs is simple enough to get figured out through the web interface. But, if not, a powerful filtering feature of ResqueCleaner may help you to understand what is going on with your console(irb).

Create Instance

    > cleaner = Resque::Plugins::ResqueCleaner.new

Show Stats

Shows stats of failed jobs grouped by date.

    > cleaner.stats_by_date
    2009/03/13:    6
    2009/11/13:   14
    2010/08/13:   22
         total:   42
    => {'2009/03/10' => 6, ...}

You could also group them by class.

    > cleaner.stats_by_class
         BadJob:    3
    HorribleJob:    7
          total:   10
    => {'BadJob' => 3, ...}

Or you could also group them by exception.

    > cleaner.stats_by_exception
	 RuntimeError:   35
    SyntaxError:    7
          total:   42
    => {'RuntimeError' => 35, ...}

You can get the ones filtered with a block: it targets only jobs which the block evaluates true.

e.g. Show stats only of jobs entered with some arguments:

    > cleaner.stats_by_date {|j| j["payload"]["args"].size > 0}
    2009/03/13:    3
    2009/11/13:    7
    2010/08/13:   11
         total:   22
    => {'2009/03/10' => 3, ...}

A convenience helper for searching for failed jobs which satisfy a regular expression:

cleaner.select_by_regex(/Jason/) # => all failed jobs that have "Jason" in them

Retry(Requeue) Jobs

You can retry all failed jobs with this method.

    > cleaner.requeue

Of course, you can filter jobs with a block; it requeues only jobs which the block evaluates true.

e.g. Retry only jobs with some arguments:

    > cleaner.requeue {|j| j["payload"]["args"].size > 0}

The job hash is extended with a module which defines some useful methods. You can use it in the block.

e.g. Retry only jobs entered within a day:

    > cleaner.requeue {|j| j.after?(1.day.ago)}

e.g. Retry EmailJob entered with arguments within 3 days:

    > cleaner.requeue {|j| j.after?(3.days.ago) && j.klass?(EmailJob) && j["payload"]["args"].size>0}

See Helper Methods section bellow for more information.

NOTE: 1.day.ago is not in standard library. Using it for making explanation more understandable. It is equivalent to Time.now - 60*60*24*3.

Clear Jobs

You can clear all failed jobs with this method:

    > cleaner.clear

Like you can do with the retry method, the clear method takes a block. Here are some examples:

    > cleaner.clear {|j| j.retried?}
    => clears all jobs already retried and returns number of the jobs.

    > cleaner.clear {|j| j.queue?(:low) && j.before?('2010-10-10')}
    => clears all jobs entried in :low queue before 10th October, 2010.

    > cleaner.clear {|j| j.exception?("RuntimeError") && j.queue?(:low)}
    => clears all jobs raised RuntimeError and queued :low queue

Retry and Clear Jobs

You can retry(requeue) and clear failed jobs at the same time; just pass true as an argument.

e.g. Retry EmailJob and remove from failed jobs:

    > cleaner.requeue(true) {|j| j.klass?(EmailJob)}

Retry with other queue

You can requeue failed jobs into other queue. In this way, you can retry failed jobs without blocking jobs being entered by your service running in the live.

e.g. Retry failed jobs on :retry queue

    > cleaner.requeue(false, :queue => :retry)

Don't forget to launch resque worker for the queue.

% QUEUE=retry rake resque:work

Select Jobs

You can just select the jobs of course. Here are some examples:

    > cleaner.select {|j| j["payload"]["args"][0]=="Johonson"}
    > cleaner.select {|j| j.after?(2.days.ago)}
    > cleaner.select #=> returns all jobs

Helper Methods

Here is a list of methods a failed job retained through ResqueCleaner has:

retried?: returns true if the job has already been retried.
requeued?: alias of retried?.
before?(time): returns true if the job failed before the time.
after?(time): returns true if the job failed after the time.
klass?(klass_or_name): returns true if the class of job matches.
queue?(queue_name): returns true if the queue of job matches.
exception?(exception_name): returns true if the exception matches.

Failed Job

Here is a sample of failed jobs:

{"failed_at": "2009/03/13 00:00:00",
 "payload": {"args": ["Johnson"], "class": "BadJob"},
 "queue": "jobs",
 "worker": "localhost:7327:jobs,jobs2",
 "exception": "RuntimeError",
 "error": "Bad job, Johnson",
 "backtrace": 
  ["./test/test_helper.rb:108:in `perform'",
   "/opt/local/lib/ruby/gems/1.8/gems/resque-1.10.0/lib/resque/job.rb:133:in `perform'",
   "/opt/local/lib/ruby/gems/1.8/gems/resque-1.10.0/lib/resque/worker.rb:157:in `perform'",
   "/opt/local/lib/ruby/gems/1.8/gems/resque-1.10.0/lib/resque/worker.rb:124:in `work'",
   "....(omitted)....",
   "./test/test_helper.rb:41",
   "test/resque_cleaner_test.rb:3"]
}

Limiter

ResqueCleaner expects a disaster situation like a huge number of failed jobs are out there. Since ResqueCleaner's filter function is running on your application process but on your Redis, it would not respond ages if you try to deal with all of those jobs.

ResqueCleaner supposes recent jobs are more important than old jobs. Therefore ResqueCleaner deals with ONLY LAST X(default=1000) JOBS. In this way, you could avoid slow responses. You can change the number through limiter attribute.

Let's see how it works with an following example.

Sample Situation

  • Number of failed jobs: 100,000

Default limiter is 1000 so that the limiter returns 1000 as a count.

    > cleaner.limiter.count
    => 1,000
    > cleaner.failure.count
    => 100,000

You could know if the limiter is on with on? method.

    > cleaner.limiter.on?
    => true

You can change the maximum number of the limiter with maximum attribute.

    > cleaner.limiter.maximum = 3000
    => 3,000
    > cleaner.limiter.count
    => 3,000
    > cleaner.limiter.on?
    => true

With limiter, ResqueCleaner's filtering targets only the last X(3000 in this sample) failed jobs.

    > cleaner.select.size
    => 3,000

The clear_stale method deletes all jobs entered prior to the last X(3000 in this sample) failed jobs. This calls Redis API and no iteration occurs on Ruby application; it should be quick even if there are huge number of failed jobs.

    > cleaner.clear_stale
    > cleaner.failure.count
    => 3,000
    > cleaner.limiter.count
    => 3,000
    > cleaner.limiter.on?
    => false

Many Thanks!

To our Contributors

resque-cleaner's People

Contributors

doncote avatar flori avatar gyllen avatar hamin avatar ktdreyer avatar mauro-oto avatar michaelxavier avatar narnach avatar ono avatar relistan avatar staszek-arsdata avatar thrillcall avatar wandenberg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

resque-cleaner's Issues

ResqueCleaner#requeue not working

Hi guys.

When I try to requeue a job from the console as the readme example says:

cleaner = Resque::Plugins::ResqueCleaner.new
cleaner.requeue {|j| j["payload"]["args"].size > 0}

I'm getting the same error that @devnut described here: resque/resque-loner#49

However, when I run it from the resque-web interface, it works.

Do you have any idea why this behavior?

Thanks.

ActionController::RoutingError (No route matches [GET] "/resque/cleaner/public/cleaner.css")

Using Rails 5.0.0.1 and getting the following error:

Started GET "/resque/cleaner/public/cleaner.css" for ::1 at 2016-10-31 22:27:45 +0100

ActionController::RoutingError (No route matches [GET] "/resque/cleaner/public/cleaner.css"):

actionpack (5.0.0.1) lib/action_dispatch/middleware/debug_exceptions.rb:53:in `call'
web-console (3.4.0) lib/web_console/middleware.rb:135:in `call_app'
web-console (3.4.0) lib/web_console/middleware.rb:28:in `block in call'
web-console (3.4.0) lib/web_console/middleware.rb:18:in `catch'
web-console (3.4.0) lib/web_console/middleware.rb:18:in `call'
actionpack (5.0.0.1) lib/action_dispatch/middleware/show_exceptions.rb:31:in `call'
railties (5.0.0.1) lib/rails/rack/logger.rb:36:in `call_app'
railties (5.0.0.1) lib/rails/rack/logger.rb:24:in `block in call'
activesupport (5.0.0.1) lib/active_support/tagged_logging.rb:70:in `block in tagged'
activesupport (5.0.0.1) lib/active_support/tagged_logging.rb:26:in `tagged'
activesupport (5.0.0.1) lib/active_support/tagged_logging.rb:70:in `tagged'
railties (5.0.0.1) lib/rails/rack/logger.rb:24:in `call'
sprockets-rails (3.2.0) lib/sprockets/rails/quiet_assets.rb:13:in `call'
actionpack (5.0.0.1) lib/action_dispatch/middleware/request_id.rb:24:in `call'
rack (2.0.1) lib/rack/method_override.rb:22:in `call'
rack (2.0.1) lib/rack/runtime.rb:22:in `call'
activesupport (5.0.0.1) lib/active_support/cache/strategy/local_cache_middleware.rb:28:in `call'
actionpack (5.0.0.1) lib/action_dispatch/middleware/executor.rb:12:in `call'
actionpack (5.0.0.1) lib/action_dispatch/middleware/static.rb:136:in `call'
rack (2.0.1) lib/rack/sendfile.rb:111:in `call'
railties (5.0.0.1) lib/rails/engine.rb:522:in `call'
puma (3.6.0) lib/puma/configuration.rb:225:in `call'
puma (3.6.0) lib/puma/server.rb:578:in `handle_request'
puma (3.6.0) lib/puma/server.rb:415:in `process_client'
puma (3.6.0) lib/puma/server.rb:275:in `block in run'
puma (3.6.0) lib/puma/thread_pool.rb:116:in `block in spawn_thread'
  Rendering /Users/stefanahman/.rvm/gems/ruby-2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb within rescues/layout
  Rendering /Users/stefanahman/.rvm/gems/ruby-2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb
  Rendered /Users/stefanahman/.rvm/gems/ruby-2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (1.3ms)
  Rendered collection of /Users/stefanahman/.rvm/gems/ruby-2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/routes/_route.html.erb [17 times] (5.4ms)
  Rendered /Users/stefanahman/.rvm/gems/ruby-2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/routes/_table.html.erb (1.2ms)
  Rendering /Users/stefanahman/.rvm/gems/ruby-2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb
  Rendered /Users/stefanahman/.rvm/gems/ruby-2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (0.9ms)
  Rendered /Users/stefanahman/.rvm/gems/ruby-2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb within rescues/layout (82.6ms)
Started GET "/resque/jquery.relatize_date.js" for ::1 at 2016-10-31 22:27:45 +0100

resque 2.0 support

Hi,
thank you for this useful gem.

Are you planing to support resque 2.0.0

Error on old version of Sinatra

Attempting to load resque-web results in:

/usr/local/lib/ruby/gems/1.8/gems/resque-cleaner-0.2.5/lib/resque_cleaner/server.rb:102:in included': undefined methodmime_type' for Resque::Server:Class (NoMethodError)
from /usr/local/lib/ruby/gems/1.8/gems/resque-cleaner-0.2.5/lib/resque_cleaner/server.rb:65:in class_eval' from /usr/local/lib/ruby/gems/1.8/gems/resque-cleaner-0.2.5/lib/resque_cleaner/server.rb:65:inincluded'
from /usr/local/lib/ruby/gems/1.8/gems/resque-cleaner-0.2.5/lib/resque_cleaner/server.rb:232:in include' from /usr/local/lib/ruby/gems/1.8/gems/resque-cleaner-0.2.5/lib/resque_cleaner/server.rb:232 from /usr/local/lib/ruby/gems/1.8/gems/resque-cleaner-0.2.5/lib/resque_cleaner/server.rb:231:inclass_eval'
from /usr/local/lib/ruby/gems/1.8/gems/resque-cleaner-0.2.5/lib/resque_cleaner/server.rb:231
from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in gem_original_require' from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:inrequire'
from /usr/local/lib/ruby/gems/1.8/gems/resque-cleaner-0.2.5/lib/resque_cleaner.rb:282
from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in gem_original_require' from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:inrequire'
from /usr/local/lib/ruby/gems/1.8/gems/resque-cleaner-0.2.5/lib/resque-cleaner.rb:1
from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:36:in gem_original_require' from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:36:inrequire'
from ./config/initializers/resque.rb:1
from /usr/local/lib/ruby/gems/1.8/gems/resque-1.17.1/bin/resque-web:16:in load' from /usr/local/lib/ruby/gems/1.8/gems/resque-1.17.1/bin/resque-web:16 from /usr/local/lib/ruby/gems/1.8/gems/vegas-0.1.3/lib/vegas/runner.rb:48:incall'
from /usr/local/lib/ruby/gems/1.8/gems/vegas-0.1.3/lib/vegas/runner.rb:48:in initialize' from /usr/local/lib/ruby/gems/1.8/gems/resque-1.17.1/bin/resque-web:13:innew'
from /usr/local/lib/ruby/gems/1.8/gems/resque-1.17.1/bin/resque-web:13
from /usr/local/bin/resque-web:19:in `load'
from /usr/local/bin/resque-web:19

cleaner tab broken when there is bad failed job

When click on Cleaner tab it shows:

NoMethodError at /cleaner
undefined method `[]' for nil:NilClass

job variable at line https://github.com/ono/resque-cleaner/blob/master/lib/resque_cleaner.rb#L56 has value {"failed_at"=>"2011/10/13 04:35:36", "payload"=>nil, "exception"=>"Resque::DirtyExit", "queue"=>nil, "worker"=>"rems3-1.dcjp02.reallyenglish.com:61035:high,low,seibido,n2r", "error"=>"Resque::DirtyExit", "backtrace"=>[]} which is not expected hash structure so it fails.

Class with slashes causes Bad Request error

When using with php-resque and namespaced classes (\Acme\Jobs\TestJob), the links from the Cleaner tab are broken

http://host:5678/cleaner_list?c=\Acme\Jobs\TestJob
Bad Request
bad URI `/cleaner_list?c=\\Acme\\Jobs\\TestJob'.

Manually going to /cleaner_list then selecting the class and hitting Filter works, because the URL is escaped:

http://host:5678//cleaner_list?c=%5CAcme%5CJobs%5CTestJob

Notes for Resque 2.0

Most code of this repo was written years ago and it made me cry when I read it again. I have been thinking of refactoring but probably it makes more sense to do that when Resque 2.0 is officially out (although I am not really sure about the schedule and scope...). I put some notes about things I want to fix here.

  • Split lib/resque_cleaner into several files
  • Rewrite server(sinatra) code and templates
  • Rewrite tests
  • Have a simpler README. Migrate information about the console to wiki.

css not showing up

can you think of a reason why cleaner.css might end up rendering as a zero byte file and have no content?

require resque-cleaner error

When I required the gem in console, I got this error message:
undefined method ssl?' for classSinatra::Request'

My resque version is 1.23.0

support for resque 2.0

Hi,

We are using your gem a lot. Thank you.

Are u planing to add support for resque 2.0.0?

Form for cleaner_exec not aware of used regex filter

I'm using resque cleaner a lot. I've found an issue with regex filter and cleaner_exec.
When trying to retry or clear only jobs matching the regex, the regex filter is not taken into filtering and all jobs are being processed (as there's no regex specified).

For example there are total 300 jobs of class Shops::Jobs::Parse and 250 jobs of the class Shops::Jobs::Parse and matching to some regex. Web UI shows 250 jobs matching the regex, but when checking 'select all 250 jobs' and doing 'Clear', all 300 Jobs are removed :(

I've found the issue in the code. There's missinginput type="hidden" name="regex" for the cleaner_exec form in the file lib/resque_cleaner/server/views/cleaner_list.erb I will try to fork and do a pull request.

Requeue-ing failed jobs with args/cleaning failed jobs with no args

Recently our app had an whole load of failed jobs due to incorrect worker configs and we ended up about 10000 failed jobs. About 70% them is stateless scheduled jobs with no arguments we want to clear. And other jobs have arguments, so we want to retry and clear.

I did it opening rails console and running this 2 until it all gone:

cleaner.clear {|j| j["payload"]["args"].size == 0}

and

cleaner.requeue(true) {|j| j["payload"]["args"].size > 0}

It would be nice if it was possible to do these on the resque-cleaner web interface like 'Clear all jobs older than 1000th'.

Allow configuration of the limiter maximum in ResqueCleaner::Server

@ono This is both a question and a request...

Basically, I've got more than 1,000 failed jobs to deal with and I'd like to be able to set limiter.maximum in an options hash for ResqueCleaner::Server such that the following limiter doesn't show up in the resque-web interface:

failed-jobs

I dug through the code and found that an instance of the Resque::Plugins::ResqueCleaner class is being instantiated here:

Would you be down for extending ResqueCleaner::Server to (somehow) read an options hash, in order allow configuration of limiter.maximum?

I know that you can make this change if you do...

Resque::Plugins::ResqueCleaner.new.limiter.maximum = 5000

...but I need a way to leverage that change from the resque-web interface.

Any tips on how to do this in a Resque::Server extension? I'd be happy to submit a pull request.

Thanks for the resque-cleaner gem!

Status of the project

I notice that there are still many people using this library. I am very thankful to everyone and feel some responsibility to explain the status of the project.

I no longer use this library by myself. In fact, I haven't used Resque for long time. For day to day job, I mainly use Elixir. I have to admit that I'm quite behind the scene.

I would say that this library is maintenance status and here are some notes to clarify.

  • I don't merge any pull requests for new feature
  • I will merge pull requests which are relatively small changes for bug/security fixes e.g. #45, #46
  • If Resque makes backward incompatible update, Resque-cleaner won't support the new version

You might ask for transferring the ownership but I am reluctant to do that in following reasons.

  • The library was written long time ago and the codebase doesn't follow some good practices discussed recently. If you are motivated to maintain the library, you should rewrite the library and publish as a brand new gem
  • It's MIT license. You are free to fork and publish as new gem as long as you publish it under the same permissions and add my name in copyright.

I hope you don't have a huge objection to the decision as Resque itself is not much active for years.

Thank you so much for your interest on this project.
And thank you especially to all people who have contributed! ๐Ÿ…

help testing against edge Resque

Hey there!

I'm gearing up to work on Resque 2.0, and I'd like to coordinate better with plugin authors to make sure stuff doesn't break.

I'd like to know a few things:

  1. Can I do something to help get you testing against edge Resque?
  2. Are you monkey-patching anything in Resque currently? Can 2.0 expose an API to help you not have to do that any more?
  3. Do you need any help in bringing your plugin up-to-date with the latest Resque?

Thanks!

Related: https://github.com/defunkt/resque/issues/880

setup via resque web engine?

When you are using the resque web engine:

  # Resque Engine
  mount ResqueWeb::Engine => 'resque' if AppSettings.settings[:mount_resque_web]

How do you set this up? I can add this to the readme too.

JSON Error on Dump

Hi.

I get an error from Sinatra when using the dump feature of resque-cleaner. Am using...

# bundle list | grep resque
  * resque (1.17.1)
  * resque-cleaner (0.2.5)
  * resque-scheduler (1.9.9)
# bundle list | grep sinatra
  * sinatra (1.2.6)

When I look at a failed job and click dump I get the following sinatra error.

#<NoMethodError: undefined method `merge' for #<JSON::Ext::Generator::State:0x000000185191a0>>
    file: encoding.rb
    location: options_for
    line: 61

I only got this when having a look at cleaner (nice plugin by the way) and it's features. I probably won't use it for this, but thought I'd pass on the error.

Presumed it was a JSON error (I haven't got JSON installed in this rails app, although multi-json is used by another Gem), so added it anyway, but still get the same message.

# bundle list | grep json
  * json (1.5.1)
  * multi_json (1.0.1)

Not sure if related, but found the following issue on stackoverflow (http://stackoverflow.com/questions/4934917/rails-json-conversion-error) which looks very similar.

Thanks

Dan

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.