sidekiq 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of sidekiq might be problematic. Click here for more details.
- data/.gitignore +5 -0
 - data/.rvmrc +2 -1
 - data/Changes.md +11 -0
 - data/LICENSE +11 -4
 - data/README.md +1 -7
 - data/TODO.md +0 -1
 - data/bin/sidekiq +2 -0
 - data/examples/por.rb +17 -0
 - data/examples/sinkiq.rb +57 -0
 - data/lib/sidekiq.rb +1 -1
 - data/lib/sidekiq/cli.rb +72 -34
 - data/lib/sidekiq/client.rb +33 -16
 - data/lib/sidekiq/manager.rb +37 -47
 - data/lib/sidekiq/middleware/chain.rb +92 -0
 - data/lib/sidekiq/middleware/client/resque_web_compatibility.rb +17 -0
 - data/lib/sidekiq/middleware/client/unique_jobs.rb +30 -0
 - data/lib/sidekiq/middleware/server/active_record.rb +13 -0
 - data/lib/sidekiq/middleware/server/airbrake.rb +30 -0
 - data/lib/sidekiq/middleware/server/unique_jobs.rb +17 -0
 - data/lib/sidekiq/processor.rb +74 -16
 - data/lib/sidekiq/redis_connection.rb +23 -0
 - data/lib/sidekiq/testing.rb +34 -0
 - data/lib/sidekiq/util.rb +21 -12
 - data/lib/sidekiq/version.rb +1 -1
 - data/lib/sidekiq/worker.rb +6 -7
 - data/myapp/Gemfile +4 -1
 - data/myapp/Gemfile.lock +29 -6
 - data/myapp/app/controllers/work_controller.rb +9 -0
 - data/myapp/app/views/work/index.html.erb +1 -0
 - data/myapp/app/workers/hard_worker.rb +4 -2
 - data/myapp/config/environments/development.rb +1 -0
 - data/myapp/config/initializers/sidekiq.rb +1 -0
 - data/myapp/config/routes.rb +4 -56
 - data/sidekiq.gemspec +1 -0
 - data/test/fake_env.rb +0 -0
 - data/test/helper.rb +3 -0
 - data/test/test_cli.rb +49 -0
 - data/test/test_client.rb +52 -10
 - data/test/test_manager.rb +11 -6
 - data/test/test_middleware.rb +39 -20
 - data/test/test_processor.rb +3 -2
 - data/test/test_stats.rb +79 -0
 - data/test/test_testing.rb +32 -0
 - metadata +47 -18
 - data/Gemfile.lock +0 -32
 - data/lib/sidekiq/middleware.rb +0 -89
 - data/test/timed_queue.rb +0 -42
 
    
        data/.rvmrc
    CHANGED
    
    
    
        data/Changes.md
    CHANGED
    
    | 
         @@ -1,3 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            0.6.0
         
     | 
| 
      
 2 
     | 
    
         
            +
            -----------
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            - Resque-compatible processing stats in redis (mperham)
         
     | 
| 
      
 5 
     | 
    
         
            +
            - Simple client testing support in sidekiq/testing (mperham)
         
     | 
| 
      
 6 
     | 
    
         
            +
            - Plain old Ruby support via the -r cli flag (mperham)
         
     | 
| 
      
 7 
     | 
    
         
            +
            - Refactored middleware support, introducing ability to add client-side middleware (ryanlecompte)
         
     | 
| 
      
 8 
     | 
    
         
            +
            - Added middleware for ignoring duplicate jobs (ryanlecompte)
         
     | 
| 
      
 9 
     | 
    
         
            +
            - Added middleware for displaying jobs in resque-web dashboard (maxjustus)
         
     | 
| 
      
 10 
     | 
    
         
            +
            - Added redis namespacing support (maxjustus)
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
       1 
12 
     | 
    
         
             
            0.5.1
         
     | 
| 
       2 
13 
     | 
    
         
             
            -----------
         
     | 
| 
       3 
14 
     | 
    
         | 
    
        data/LICENSE
    CHANGED
    
    | 
         @@ -1,9 +1,16 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            Copyright (c) Mike Perham
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
      
 3 
     | 
    
         
            +
            You may choose to license Sidekiq in one of two ways:
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            - Open Source under the GPLv3
         
     | 
| 
       4 
6 
     | 
    
         | 
| 
       5 
7 
     | 
    
         
             
              Please see <http://www.gnu.org/licenses/gpl-3.0.html> for license text.
         
     | 
| 
       6 
8 
     | 
    
         | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
      
 9 
     | 
    
         
            +
            - Commercial License
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              The Sencha commercial software license in COMM-LICENSE.  You must pledge
         
     | 
| 
      
 12 
     | 
    
         
            +
              $50 to my Pledgie fund at http://www.pledgie.com/campaigns/16623 to use
         
     | 
| 
      
 13 
     | 
    
         
            +
              this license.
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            This commercial license is just meant to help support my OSS work.  If
         
     | 
| 
      
 16 
     | 
    
         
            +
            you do buy the commercial licensing option, thank you for your support!
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -47,13 +47,7 @@ Please see the [sidekiq wiki](https://github.com/mperham/sidekiq/wiki) for more 
     | 
|
| 
       47 
47 
     | 
    
         
             
            License
         
     | 
| 
       48 
48 
     | 
    
         
             
            -----------------
         
     | 
| 
       49 
49 
     | 
    
         | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
       51 
     | 
    
         
            -
            license, you must give $50 to my [Pledgie campaign](http://www.pledgie.com/campaigns/16623).
         
     | 
| 
       52 
     | 
    
         
            -
            Considering the hundreds of hours I've spent writing OSS, I hope you
         
     | 
| 
       53 
     | 
    
         
            -
            think this is a reasonable price.  BTW, the commercial license is in
         
     | 
| 
       54 
     | 
    
         
            -
            COMM-LICENSE and is the [Sencha commercial license v1.10](http://www.sencha.com/legal/sencha-commercial-software-license-agreement/) with the Support (section 11) terms removed.
         
     | 
| 
       55 
     | 
    
         
            -
            Support is provided through GitHub Issues.  You are welcome to try the
         
     | 
| 
       56 
     | 
    
         
            -
            software for 2 weeks.
         
     | 
| 
      
 50 
     | 
    
         
            +
            Please see LICENSE for licensing details.
         
     | 
| 
       57 
51 
     | 
    
         | 
| 
       58 
52 
     | 
    
         
             
            <a href='http://www.pledgie.com/campaigns/16623'><img alt='Click here to lend your support to Open Source and make a donation at www.pledgie.com !' src='http://www.pledgie.com/campaigns/16623.png?skin_name=chrome' border='0' /></a>
         
     | 
| 
       59 
53 
     | 
    
         | 
    
        data/TODO.md
    CHANGED
    
    
    
        data/bin/sidekiq
    CHANGED
    
    
    
        data/examples/por.rb
    ADDED
    
    | 
         @@ -0,0 +1,17 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'sidekiq'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            # Start up sidekiq via
         
     | 
| 
      
 4 
     | 
    
         
            +
            # ./bin/sidekiq -r ./examples/por.rb
         
     | 
| 
      
 5 
     | 
    
         
            +
            # and then you can open up an IRB session like so:
         
     | 
| 
      
 6 
     | 
    
         
            +
            # irb -r ./examples/por.rb
         
     | 
| 
      
 7 
     | 
    
         
            +
            # where you can then say
         
     | 
| 
      
 8 
     | 
    
         
            +
            # PlainOldRuby.perform_async "like a dog", 3
         
     | 
| 
      
 9 
     | 
    
         
            +
            #
         
     | 
| 
      
 10 
     | 
    
         
            +
            class PlainOldRuby
         
     | 
| 
      
 11 
     | 
    
         
            +
              include Sidekiq::Worker
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              def perform(how_hard="super hard", how_long=1)
         
     | 
| 
      
 14 
     | 
    
         
            +
                sleep how_long
         
     | 
| 
      
 15 
     | 
    
         
            +
                puts "Workin' #{how_hard}"
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
            end
         
     | 
    
        data/examples/sinkiq.rb
    ADDED
    
    | 
         @@ -0,0 +1,57 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Make sure you have Sinatra installed, then start sidekiq with
         
     | 
| 
      
 2 
     | 
    
         
            +
            # ./bin/sidekiq -r ./examples/sinkiq.rb
         
     | 
| 
      
 3 
     | 
    
         
            +
            # Simply run Sinatra with
         
     | 
| 
      
 4 
     | 
    
         
            +
            # ruby examples/sinkiq.rb
         
     | 
| 
      
 5 
     | 
    
         
            +
            # and then browse to http://localhost:4567
         
     | 
| 
      
 6 
     | 
    
         
            +
            #
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'sinatra'
         
     | 
| 
      
 8 
     | 
    
         
            +
            require 'sidekiq/worker'
         
     | 
| 
      
 9 
     | 
    
         
            +
            $redis = Sidekiq::RedisConnection.create
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            class SinatraWorker
         
     | 
| 
      
 12 
     | 
    
         
            +
              include Sidekiq::Worker
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              def perform(msg="lulz you forgot a msg!")
         
     | 
| 
      
 15 
     | 
    
         
            +
                $redis.lpush("sinkiq-example-messages", msg)      
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
            end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            get '/' do
         
     | 
| 
      
 20 
     | 
    
         
            +
              @failed = $redis.get('stat:failed')
         
     | 
| 
      
 21 
     | 
    
         
            +
              @processed = $redis.get('stat:processed')
         
     | 
| 
      
 22 
     | 
    
         
            +
              @messages = $redis.lrange('sinkiq-example-messages', 0, -1)
         
     | 
| 
      
 23 
     | 
    
         
            +
              erb :index
         
     | 
| 
      
 24 
     | 
    
         
            +
            end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
            post '/msg' do
         
     | 
| 
      
 27 
     | 
    
         
            +
              SinatraWorker.perform_async params[:msg]
         
     | 
| 
      
 28 
     | 
    
         
            +
              redirect to('/')
         
     | 
| 
      
 29 
     | 
    
         
            +
            end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            __END__
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            @@ layout
         
     | 
| 
      
 34 
     | 
    
         
            +
            <html>
         
     | 
| 
      
 35 
     | 
    
         
            +
              <head>
         
     | 
| 
      
 36 
     | 
    
         
            +
                <title>Sinatra + Sidekiq</title>
         
     | 
| 
      
 37 
     | 
    
         
            +
                <body>
         
     | 
| 
      
 38 
     | 
    
         
            +
                  <%= yield %>
         
     | 
| 
      
 39 
     | 
    
         
            +
                </body>
         
     | 
| 
      
 40 
     | 
    
         
            +
            </html>
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
            @@ index
         
     | 
| 
      
 43 
     | 
    
         
            +
              <h1>Sinata + Sidekiq Example</h1>
         
     | 
| 
      
 44 
     | 
    
         
            +
              <h2>Failed: <%= @failed %></h2>
         
     | 
| 
      
 45 
     | 
    
         
            +
              <h2>Processed: <%= @processed %></h2>
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
              <form method="post" action="/msg">
         
     | 
| 
      
 48 
     | 
    
         
            +
                <input type="text" name="msg">
         
     | 
| 
      
 49 
     | 
    
         
            +
                <input type="submit" value="Add Message">
         
     | 
| 
      
 50 
     | 
    
         
            +
              </form>
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
              <a href="/">Refresh page</a>
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
              <h3>Messages</h3>
         
     | 
| 
      
 55 
     | 
    
         
            +
              <% @messages.each do |msg| %>
         
     | 
| 
      
 56 
     | 
    
         
            +
                <p><%= msg %></p>
         
     | 
| 
      
 57 
     | 
    
         
            +
              <% end %>
         
     | 
    
        data/lib/sidekiq.rb
    CHANGED
    
    
    
        data/lib/sidekiq/cli.rb
    CHANGED
    
    | 
         @@ -1,34 +1,50 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            trap 'INT' do
         
     | 
| 
      
 2 
     | 
    
         
            +
              # Handle Ctrl-C in JRuby like MRI
         
     | 
| 
      
 3 
     | 
    
         
            +
              # http://jira.codehaus.org/browse/JRUBY-4637
         
     | 
| 
      
 4 
     | 
    
         
            +
              Thread.main.raise Interrupt
         
     | 
| 
      
 5 
     | 
    
         
            +
            end
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            trap 'TERM' do
         
     | 
| 
      
 8 
     | 
    
         
            +
              # Heroku sends TERM and then waits 10 seconds for process to exit.
         
     | 
| 
      
 9 
     | 
    
         
            +
              Thread.main.raise Interrupt
         
     | 
| 
      
 10 
     | 
    
         
            +
            end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
       1 
12 
     | 
    
         
             
            require 'optparse'
         
     | 
| 
       2 
13 
     | 
    
         
             
            require 'sidekiq/version'
         
     | 
| 
       3 
14 
     | 
    
         
             
            require 'sidekiq/util'
         
     | 
| 
       4 
     | 
    
         
            -
            require 'sidekiq/ 
     | 
| 
      
 15 
     | 
    
         
            +
            require 'sidekiq/redis_connection'
         
     | 
| 
       5 
16 
     | 
    
         
             
            require 'sidekiq/manager'
         
     | 
| 
       6 
     | 
    
         
            -
            require 'connection_pool'
         
     | 
| 
       7 
17 
     | 
    
         | 
| 
       8 
18 
     | 
    
         
             
            module Sidekiq
         
     | 
| 
       9 
19 
     | 
    
         
             
              class CLI
         
     | 
| 
       10 
20 
     | 
    
         
             
                include Util
         
     | 
| 
       11 
21 
     | 
    
         | 
| 
      
 22 
     | 
    
         
            +
                # Used for CLI testing
         
     | 
| 
      
 23 
     | 
    
         
            +
                attr_accessor :options, :code
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
       12 
25 
     | 
    
         
             
                def initialize
         
     | 
| 
       13 
     | 
    
         
            -
                   
     | 
| 
       14 
     | 
    
         
            -
                  validate!
         
     | 
| 
       15 
     | 
    
         
            -
                  boot_rails
         
     | 
| 
      
 26 
     | 
    
         
            +
                  @code = nil
         
     | 
| 
       16 
27 
     | 
    
         
             
                end
         
     | 
| 
       17 
28 
     | 
    
         | 
| 
       18 
     | 
    
         
            -
                 
     | 
| 
      
 29 
     | 
    
         
            +
                def parse(args=ARGV)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  Sidekiq::Util.logger
         
     | 
| 
      
 31 
     | 
    
         
            +
                  parse_options(args)
         
     | 
| 
      
 32 
     | 
    
         
            +
                  validate!
         
     | 
| 
      
 33 
     | 
    
         
            +
                  boot_system
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
       19 
35 
     | 
    
         | 
| 
       20 
36 
     | 
    
         
             
                def run
         
     | 
| 
       21 
     | 
    
         
            -
                   
     | 
| 
       22 
     | 
    
         
            -
                  manager = Sidekiq::Manager.new(@options 
     | 
| 
      
 37 
     | 
    
         
            +
                  Sidekiq::Manager.redis = RedisConnection.create(:url => @options[:server], :namespace => @options[:namespace])
         
     | 
| 
      
 38 
     | 
    
         
            +
                  manager = Sidekiq::Manager.new(@options)
         
     | 
| 
       23 
39 
     | 
    
         
             
                  begin
         
     | 
| 
       24 
     | 
    
         
            -
                     
     | 
| 
      
 40 
     | 
    
         
            +
                    logger.info 'Starting processing, hit Ctrl-C to stop'
         
     | 
| 
       25 
41 
     | 
    
         
             
                    manager.start!
         
     | 
| 
       26 
42 
     | 
    
         
             
                    # HACK need to determine how to pause main thread while
         
     | 
| 
       27 
43 
     | 
    
         
             
                    # waiting for signals.
         
     | 
| 
       28 
     | 
    
         
            -
                    sleep 
     | 
| 
      
 44 
     | 
    
         
            +
                    sleep
         
     | 
| 
       29 
45 
     | 
    
         
             
                  rescue Interrupt
         
     | 
| 
       30 
46 
     | 
    
         
             
                    # TODO Need clean shutdown support from Celluloid
         
     | 
| 
       31 
     | 
    
         
            -
                     
     | 
| 
      
 47 
     | 
    
         
            +
                    logger.info 'Shutting down, pausing 5 seconds to let workers finish...'
         
     | 
| 
       32 
48 
     | 
    
         
             
                    manager.stop!
         
     | 
| 
       33 
49 
     | 
    
         
             
                    manager.wait(:shutdown)
         
     | 
| 
       34 
50 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -36,54 +52,76 @@ module Sidekiq 
     | 
|
| 
       36 
52 
     | 
    
         | 
| 
       37 
53 
     | 
    
         
             
                private
         
     | 
| 
       38 
54 
     | 
    
         | 
| 
       39 
     | 
    
         
            -
                def  
     | 
| 
       40 
     | 
    
         
            -
                   
     | 
| 
       41 
     | 
    
         
            -
                  require File.expand_path("#{@options[:rails]}/config/environment.rb")
         
     | 
| 
       42 
     | 
    
         
            -
                  ::Rails.application.eager_load!
         
     | 
| 
      
 55 
     | 
    
         
            +
                def die(code)
         
     | 
| 
      
 56 
     | 
    
         
            +
                  exit(code)
         
     | 
| 
       43 
57 
     | 
    
         
             
                end
         
     | 
| 
       44 
58 
     | 
    
         | 
| 
       45 
     | 
    
         
            -
                def  
     | 
| 
       46 
     | 
    
         
            -
                   
     | 
| 
      
 59 
     | 
    
         
            +
                def detected_environment
         
     | 
| 
      
 60 
     | 
    
         
            +
                  @options[:environment] || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
         
     | 
| 
      
 61 
     | 
    
         
            +
                end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                def boot_system
         
     | 
| 
      
 64 
     | 
    
         
            +
                  ENV['RACK_ENV'] = ENV['RAILS_ENV'] = detected_environment
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                  raise ArgumentError, "#{@options[:require]} does not exist" if !File.exist?(@options[:require])
         
     | 
| 
       47 
67 
     | 
    
         | 
| 
       48 
     | 
    
         
            -
                  if  
     | 
| 
       49 
     | 
    
         
            -
                     
     | 
| 
       50 
     | 
    
         
            -
                     
     | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
      
 68 
     | 
    
         
            +
                  if File.directory?(@options[:require])
         
     | 
| 
      
 69 
     | 
    
         
            +
                    require File.expand_path("#{@options[:require]}/config/environment.rb")
         
     | 
| 
      
 70 
     | 
    
         
            +
                    ::Rails.application.eager_load!
         
     | 
| 
      
 71 
     | 
    
         
            +
                  else
         
     | 
| 
      
 72 
     | 
    
         
            +
                    require @options[:require]
         
     | 
| 
       52 
73 
     | 
    
         
             
                  end
         
     | 
| 
       53 
74 
     | 
    
         
             
                end
         
     | 
| 
       54 
75 
     | 
    
         | 
| 
       55 
     | 
    
         
            -
                def  
     | 
| 
      
 76 
     | 
    
         
            +
                def validate!
         
     | 
| 
      
 77 
     | 
    
         
            +
                  @options[:queues] << 'default' if @options[:queues].empty?
         
     | 
| 
      
 78 
     | 
    
         
            +
                  @options[:queues].shuffle!
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                  if !File.exist?(@options[:require]) ||
         
     | 
| 
      
 81 
     | 
    
         
            +
                     (File.directory?(@options[:require]) && !File.exist?("#{@options[:require]}/config/application.rb"))
         
     | 
| 
      
 82 
     | 
    
         
            +
                    logger.info "=================================================================="
         
     | 
| 
      
 83 
     | 
    
         
            +
                    logger.info "  Please point sidekiq to a Rails 3 application or a Ruby file    "
         
     | 
| 
      
 84 
     | 
    
         
            +
                    logger.info "  to load your worker classes with -r [DIR|FILE]."
         
     | 
| 
      
 85 
     | 
    
         
            +
                    logger.info "=================================================================="
         
     | 
| 
      
 86 
     | 
    
         
            +
                    logger.info @parser
         
     | 
| 
      
 87 
     | 
    
         
            +
                    die(1)
         
     | 
| 
      
 88 
     | 
    
         
            +
                  end
         
     | 
| 
      
 89 
     | 
    
         
            +
                end
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                def parse_options(argv)
         
     | 
| 
       56 
92 
     | 
    
         
             
                  @options = {
         
     | 
| 
       57 
     | 
    
         
            -
                    : 
     | 
| 
       58 
     | 
    
         
            -
                    :queues => ['default'],
         
     | 
| 
      
 93 
     | 
    
         
            +
                    :queues => [],
         
     | 
| 
       59 
94 
     | 
    
         
             
                    :processor_count => 25,
         
     | 
| 
       60 
     | 
    
         
            -
                    : 
     | 
| 
       61 
     | 
    
         
            -
                    : 
     | 
| 
       62 
     | 
    
         
            -
                    :environment => 'production',
         
     | 
| 
      
 95 
     | 
    
         
            +
                    :require => '.',
         
     | 
| 
      
 96 
     | 
    
         
            +
                    :environment => nil,
         
     | 
| 
       63 
97 
     | 
    
         
             
                  }
         
     | 
| 
       64 
98 
     | 
    
         | 
| 
       65 
99 
     | 
    
         
             
                  @parser = OptionParser.new do |o|
         
     | 
| 
       66 
100 
     | 
    
         
             
                    o.on "-q", "--queue QUEUE,WEIGHT", "Queue to process, with optional weight" do |arg|
         
     | 
| 
       67 
101 
     | 
    
         
             
                      (q, weight) = arg.split(",")
         
     | 
| 
       68 
     | 
    
         
            -
                      (weight || 1).times do
         
     | 
| 
      
 102 
     | 
    
         
            +
                      (weight || 1).to_i.times do
         
     | 
| 
       69 
103 
     | 
    
         
             
                        @options[:queues] << q
         
     | 
| 
       70 
104 
     | 
    
         
             
                      end
         
     | 
| 
       71 
105 
     | 
    
         
             
                    end
         
     | 
| 
       72 
106 
     | 
    
         | 
| 
       73 
107 
     | 
    
         
             
                    o.on "-v", "--verbose", "Print more verbose output" do
         
     | 
| 
       74 
     | 
    
         
            -
                       
     | 
| 
      
 108 
     | 
    
         
            +
                      Sidekiq::Util.logger.level = Logger::DEBUG
         
     | 
| 
      
 109 
     | 
    
         
            +
                    end
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
                    o.on "-n", "--namespace NAMESPACE", "namespace worker queues are under" do |arg|
         
     | 
| 
      
 112 
     | 
    
         
            +
                      @options[:namespace] = arg
         
     | 
| 
       75 
113 
     | 
    
         
             
                    end
         
     | 
| 
       76 
114 
     | 
    
         | 
| 
       77 
115 
     | 
    
         
             
                    o.on "-s", "--server LOCATION", "Where to find Redis" do |arg|
         
     | 
| 
       78 
116 
     | 
    
         
             
                      @options[:server] = arg
         
     | 
| 
       79 
117 
     | 
    
         
             
                    end
         
     | 
| 
       80 
118 
     | 
    
         | 
| 
       81 
     | 
    
         
            -
                    o.on '-e', '--environment ENV', " 
     | 
| 
      
 119 
     | 
    
         
            +
                    o.on '-e', '--environment ENV', "Application environment" do |arg|
         
     | 
| 
       82 
120 
     | 
    
         
             
                      @options[:environment] = arg
         
     | 
| 
       83 
121 
     | 
    
         
             
                    end
         
     | 
| 
       84 
122 
     | 
    
         | 
| 
       85 
     | 
    
         
            -
                    o.on '-r', '-- 
     | 
| 
       86 
     | 
    
         
            -
                      @options[: 
     | 
| 
      
 123 
     | 
    
         
            +
                    o.on '-r', '--require [PATH|DIR]', "Location of Rails application with workers or file to require" do |arg|
         
     | 
| 
      
 124 
     | 
    
         
            +
                      @options[:require] = arg
         
     | 
| 
       87 
125 
     | 
    
         
             
                    end
         
     | 
| 
       88 
126 
     | 
    
         | 
| 
       89 
127 
     | 
    
         
             
                    o.on '-c', '--concurrency INT', "processor threads to use" do |arg|
         
     | 
| 
         @@ -93,8 +131,8 @@ module Sidekiq 
     | 
|
| 
       93 
131 
     | 
    
         | 
| 
       94 
132 
     | 
    
         
             
                  @parser.banner = "sidekiq [options]"
         
     | 
| 
       95 
133 
     | 
    
         
             
                  @parser.on_tail "-h", "--help", "Show help" do
         
     | 
| 
       96 
     | 
    
         
            -
                     
     | 
| 
       97 
     | 
    
         
            -
                     
     | 
| 
      
 134 
     | 
    
         
            +
                    logger.info @parser
         
     | 
| 
      
 135 
     | 
    
         
            +
                    die 1
         
     | 
| 
       98 
136 
     | 
    
         
             
                  end
         
     | 
| 
       99 
137 
     | 
    
         
             
                  @parser.parse!(argv)
         
     | 
| 
       100 
138 
     | 
    
         
             
                end
         
     | 
    
        data/lib/sidekiq/client.rb
    CHANGED
    
    | 
         @@ -1,30 +1,53 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'multi_json'
         
     | 
| 
       2 
2 
     | 
    
         
             
            require 'redis'
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
      
 4 
     | 
    
         
            +
            require 'sidekiq/redis_connection'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'sidekiq/middleware/chain'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'sidekiq/middleware/client/resque_web_compatibility'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'sidekiq/middleware/client/unique_jobs'
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
       4 
9 
     | 
    
         
             
            module Sidekiq
         
     | 
| 
       5 
10 
     | 
    
         
             
              class Client
         
     | 
| 
       6 
11 
     | 
    
         | 
| 
       7 
     | 
    
         
            -
                def self. 
     | 
| 
       8 
     | 
    
         
            -
                  @ 
     | 
| 
       9 
     | 
    
         
            -
                     
     | 
| 
       10 
     | 
    
         
            -
                     
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
      
 12 
     | 
    
         
            +
                def self.middleware
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @middleware ||= begin
         
     | 
| 
      
 14 
     | 
    
         
            +
                    m = Middleware::Chain.new
         
     | 
| 
      
 15 
     | 
    
         
            +
                    m.register do
         
     | 
| 
      
 16 
     | 
    
         
            +
                      use Middleware::Client::UniqueJobs, Client.redis
         
     | 
| 
      
 17 
     | 
    
         
            +
                      use Middleware::Client::ResqueWebCompatibility, Client.redis
         
     | 
| 
      
 18 
     | 
    
         
            +
                    end
         
     | 
| 
      
 19 
     | 
    
         
            +
                    m
         
     | 
| 
       13 
20 
     | 
    
         
             
                  end
         
     | 
| 
       14 
21 
     | 
    
         
             
                end
         
     | 
| 
       15 
22 
     | 
    
         | 
| 
      
 23 
     | 
    
         
            +
                def self.queues
         
     | 
| 
      
 24 
     | 
    
         
            +
                  @queues ||= {}
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                def self.redis
         
     | 
| 
      
 28 
     | 
    
         
            +
                  @redis ||= RedisConnection.create
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
       16 
31 
     | 
    
         
             
                def self.redis=(redis)
         
     | 
| 
       17 
32 
     | 
    
         
             
                  @redis = redis
         
     | 
| 
       18 
33 
     | 
    
         
             
                end
         
     | 
| 
       19 
34 
     | 
    
         | 
| 
       20 
35 
     | 
    
         
             
                # Example usage:
         
     | 
| 
       21 
36 
     | 
    
         
             
                # Sidekiq::Client.push('my_queue', 'class' => MyWorker, 'args' => ['foo', 1, :bat => 'bar'])
         
     | 
| 
       22 
     | 
    
         
            -
                def self.push(queue= 
     | 
| 
      
 37 
     | 
    
         
            +
                def self.push(queue=nil, item)
         
     | 
| 
       23 
38 
     | 
    
         
             
                  raise(ArgumentError, "Message must be a Hash of the form: { 'class' => SomeClass, 'args' => ['bob', 1, :foo => 'bar'] }") unless item.is_a?(Hash)
         
     | 
| 
       24 
39 
     | 
    
         
             
                  raise(ArgumentError, "Message must include a class and set of arguments: #{item.inspect}") if !item['class'] || !item['args']
         
     | 
| 
       25 
40 
     | 
    
         | 
| 
      
 41 
     | 
    
         
            +
                  queue = queue || queues[item['class'].to_s] || 'default'
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
       26 
43 
     | 
    
         
             
                  item['class'] = item['class'].to_s if !item['class'].is_a?(String)
         
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                  pushed = false
         
     | 
| 
      
 46 
     | 
    
         
            +
                  middleware.invoke(item, queue) do
         
     | 
| 
      
 47 
     | 
    
         
            +
                    redis.rpush("queue:#{queue}", MultiJson.encode(item))
         
     | 
| 
      
 48 
     | 
    
         
            +
                    pushed = true
         
     | 
| 
      
 49 
     | 
    
         
            +
                  end
         
     | 
| 
      
 50 
     | 
    
         
            +
                  pushed
         
     | 
| 
       28 
51 
     | 
    
         
             
                end
         
     | 
| 
       29 
52 
     | 
    
         | 
| 
       30 
53 
     | 
    
         
             
                # Please use .push if possible instead.
         
     | 
| 
         @@ -33,16 +56,10 @@ module Sidekiq 
     | 
|
| 
       33 
56 
     | 
    
         
             
                #
         
     | 
| 
       34 
57 
     | 
    
         
             
                #   Sidekiq::Client.enqueue(MyWorker, 'foo', 1, :bat => 'bar')
         
     | 
| 
       35 
58 
     | 
    
         
             
                #
         
     | 
| 
       36 
     | 
    
         
            -
                # Messages are enqueued to the 'default' queue. 
     | 
| 
       37 
     | 
    
         
            -
                # MyWorker can define a queue class method:
         
     | 
| 
       38 
     | 
    
         
            -
                #
         
     | 
| 
       39 
     | 
    
         
            -
                #   def self.queue
         
     | 
| 
       40 
     | 
    
         
            -
                #     'my_queue'
         
     | 
| 
       41 
     | 
    
         
            -
                #   end
         
     | 
| 
      
 59 
     | 
    
         
            +
                # Messages are enqueued to the 'default' queue.
         
     | 
| 
       42 
60 
     | 
    
         
             
                #
         
     | 
| 
       43 
61 
     | 
    
         
             
                def self.enqueue(klass, *args)
         
     | 
| 
       44 
     | 
    
         
            -
                   
     | 
| 
       45 
     | 
    
         
            -
                  push(queue, { 'class' => klass.name, 'args' => args })
         
     | 
| 
      
 62 
     | 
    
         
            +
                  push(nil, { 'class' => klass.name, 'args' => args })
         
     | 
| 
       46 
63 
     | 
    
         
             
                end
         
     | 
| 
       47 
64 
     | 
    
         
             
              end
         
     | 
| 
       48 
65 
     | 
    
         
             
            end
         
     | 
    
        data/lib/sidekiq/manager.rb
    CHANGED
    
    | 
         @@ -18,22 +18,20 @@ module Sidekiq 
     | 
|
| 
       18 
18 
     | 
    
         | 
| 
       19 
19 
     | 
    
         
             
                trap_exit :processor_died
         
     | 
| 
       20 
20 
     | 
    
         | 
| 
       21 
     | 
    
         
            -
                 
     | 
| 
       22 
     | 
    
         
            -
                   
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
      
 21 
     | 
    
         
            +
                class << self
         
     | 
| 
      
 22 
     | 
    
         
            +
                  attr_accessor :redis
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                def initialize(options={})
         
     | 
| 
      
 26 
     | 
    
         
            +
                  logger.info "Booting sidekiq #{Sidekiq::VERSION} with Redis at #{redis.client.location}"
         
     | 
| 
      
 27 
     | 
    
         
            +
                  logger.debug { options.inspect }
         
     | 
| 
       24 
28 
     | 
    
         
             
                  @count = options[:processor_count] || 25
         
     | 
| 
       25 
29 
     | 
    
         
             
                  @queues = options[:queues]
         
     | 
| 
       26 
     | 
    
         
            -
                  @queue_idx = 0
         
     | 
| 
       27 
     | 
    
         
            -
                  @queues_size = @queues.size
         
     | 
| 
       28 
     | 
    
         
            -
                  @redis = Redis.connect(:url => location)
         
     | 
| 
       29 
30 
     | 
    
         
             
                  @done_callback = nil
         
     | 
| 
       30 
31 
     | 
    
         | 
| 
       31 
32 
     | 
    
         
             
                  @done = false
         
     | 
| 
       32 
33 
     | 
    
         
             
                  @busy = []
         
     | 
| 
       33 
     | 
    
         
            -
                  @ready =  
     | 
| 
       34 
     | 
    
         
            -
                  @count.times do
         
     | 
| 
       35 
     | 
    
         
            -
                    @ready << Processor.new_link(current_actor)
         
     | 
| 
       36 
     | 
    
         
            -
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
                  @ready = @count.times.map { Processor.new_link(current_actor) }
         
     | 
| 
       37 
35 
     | 
    
         
             
                end
         
     | 
| 
       38 
36 
     | 
    
         | 
| 
       39 
37 
     | 
    
         
             
                def stop
         
     | 
| 
         @@ -44,35 +42,38 @@ module Sidekiq 
     | 
|
| 
       44 
42 
     | 
    
         
             
                  after(5) do
         
     | 
| 
       45 
43 
     | 
    
         
             
                    signal(:shutdown)
         
     | 
| 
       46 
44 
     | 
    
         
             
                  end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                  redis.with_connection do |conn|
         
     | 
| 
      
 47 
     | 
    
         
            +
                    conn.smembers('workers').each do |name|
         
     | 
| 
      
 48 
     | 
    
         
            +
                      conn.srem('workers', name) if name =~ /:#{Process.pid}:/
         
     | 
| 
      
 49 
     | 
    
         
            +
                    end
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
       47 
51 
     | 
    
         
             
                end
         
     | 
| 
       48 
52 
     | 
    
         | 
| 
       49 
53 
     | 
    
         
             
                def start
         
     | 
| 
       50 
54 
     | 
    
         
             
                  dispatch(true)
         
     | 
| 
       51 
55 
     | 
    
         
             
                end
         
     | 
| 
       52 
56 
     | 
    
         | 
| 
       53 
     | 
    
         
            -
                def when_done
         
     | 
| 
       54 
     | 
    
         
            -
                  @done_callback =  
     | 
| 
      
 57 
     | 
    
         
            +
                def when_done(&blk)
         
     | 
| 
      
 58 
     | 
    
         
            +
                  @done_callback = blk
         
     | 
| 
       55 
59 
     | 
    
         
             
                end
         
     | 
| 
       56 
60 
     | 
    
         | 
| 
       57 
61 
     | 
    
         
             
                def processor_done(processor)
         
     | 
| 
       58 
     | 
    
         
            -
                   
     | 
| 
       59 
     | 
    
         
            -
             
     | 
| 
       60 
     | 
    
         
            -
             
     | 
| 
       61 
     | 
    
         
            -
                     
     | 
| 
       62 
     | 
    
         
            -
             
     | 
| 
       63 
     | 
    
         
            -
                     
     | 
| 
      
 62 
     | 
    
         
            +
                  watchdog('sidekiq processor_done crashed!') do
         
     | 
| 
      
 63 
     | 
    
         
            +
                    @done_callback.call(processor) if @done_callback
         
     | 
| 
      
 64 
     | 
    
         
            +
                    @busy.delete(processor)
         
     | 
| 
      
 65 
     | 
    
         
            +
                    if stopped?
         
     | 
| 
      
 66 
     | 
    
         
            +
                      processor.terminate
         
     | 
| 
      
 67 
     | 
    
         
            +
                    else
         
     | 
| 
      
 68 
     | 
    
         
            +
                      @ready << processor
         
     | 
| 
      
 69 
     | 
    
         
            +
                    end
         
     | 
| 
      
 70 
     | 
    
         
            +
                    dispatch
         
     | 
| 
       64 
71 
     | 
    
         
             
                  end
         
     | 
| 
       65 
     | 
    
         
            -
                  dispatch
         
     | 
| 
       66 
72 
     | 
    
         
             
                end
         
     | 
| 
       67 
73 
     | 
    
         | 
| 
       68 
74 
     | 
    
         
             
                def processor_died(processor, reason)
         
     | 
| 
       69 
75 
     | 
    
         
             
                  @busy.delete(processor)
         
     | 
| 
       70 
76 
     | 
    
         | 
| 
       71 
     | 
    
         
            -
                  if reason
         
     | 
| 
       72 
     | 
    
         
            -
                    log "Processor death: #{reason}"
         
     | 
| 
       73 
     | 
    
         
            -
                    log reason.backtrace.join("\n")
         
     | 
| 
       74 
     | 
    
         
            -
                  end
         
     | 
| 
       75 
     | 
    
         
            -
             
     | 
| 
       76 
77 
     | 
    
         
             
                  unless stopped?
         
     | 
| 
       77 
78 
     | 
    
         
             
                    @ready << Processor.new_link(current_actor)
         
     | 
| 
       78 
79 
     | 
    
         
             
                    dispatch
         
     | 
| 
         @@ -81,13 +82,12 @@ module Sidekiq 
     | 
|
| 
       81 
82 
     | 
    
         | 
| 
       82 
83 
     | 
    
         
             
                private
         
     | 
| 
       83 
84 
     | 
    
         | 
| 
       84 
     | 
    
         
            -
                def find_work( 
     | 
| 
       85 
     | 
    
         
            -
                   
     | 
| 
       86 
     | 
    
         
            -
                  msg = @redis.lpop("queue:#{current_queue}")
         
     | 
| 
      
 85 
     | 
    
         
            +
                def find_work(queue)
         
     | 
| 
      
 86 
     | 
    
         
            +
                  msg = redis.lpop("queue:#{queue}")
         
     | 
| 
       87 
87 
     | 
    
         
             
                  if msg
         
     | 
| 
       88 
88 
     | 
    
         
             
                    processor = @ready.pop
         
     | 
| 
       89 
89 
     | 
    
         
             
                    @busy << processor
         
     | 
| 
       90 
     | 
    
         
            -
                    processor.process! 
     | 
| 
      
 90 
     | 
    
         
            +
                    processor.process!(MultiJson.decode(msg), queue)
         
     | 
| 
       91 
91 
     | 
    
         
             
                  end
         
     | 
| 
       92 
92 
     | 
    
         
             
                  !!msg
         
     | 
| 
       93 
93 
     | 
    
         
             
                end
         
     | 
| 
         @@ -96,32 +96,22 @@ module Sidekiq 
     | 
|
| 
       96 
96 
     | 
    
         
             
                  watchdog("Fatal error in sidekiq, dispatch loop died") do
         
     | 
| 
       97 
97 
     | 
    
         
             
                    return if stopped?
         
     | 
| 
       98 
98 
     | 
    
         | 
| 
       99 
     | 
    
         
            -
                    #  
     | 
| 
       100 
     | 
    
         
            -
                    # Loop through the queues, looking for a message in each.
         
     | 
| 
       101 
     | 
    
         
            -
                    queue_idx = 0
         
     | 
| 
       102 
     | 
    
         
            -
                    found = false
         
     | 
| 
      
 99 
     | 
    
         
            +
                    # Dispatch loop
         
     | 
| 
       103 
100 
     | 
    
         
             
                    loop do
         
     | 
| 
       104 
     | 
    
         
            -
                       
     | 
| 
       105 
     | 
    
         
            -
                       
     | 
| 
       106 
     | 
    
         
            -
             
     | 
| 
       107 
     | 
    
         
            -
             
     | 
| 
       108 
     | 
    
         
            -
                      queue_idx += 1
         
     | 
| 
       109 
     | 
    
         
            -
             
     | 
| 
       110 
     | 
    
         
            -
                      # if we find no messages in any of the queues, we can break
         
     | 
| 
       111 
     | 
    
         
            -
                      # out of the loop.  Otherwise we loop again.
         
     | 
| 
       112 
     | 
    
         
            -
                      lastq = (queue_idx % @queues.size == 0)
         
     | 
| 
       113 
     | 
    
         
            -
                      if lastq && !found
         
     | 
| 
       114 
     | 
    
         
            -
                        verbose('nothing to process'); break
         
     | 
| 
       115 
     | 
    
         
            -
                      elsif lastq
         
     | 
| 
       116 
     | 
    
         
            -
                        queue_idx = 0
         
     | 
| 
       117 
     | 
    
         
            -
                        found = false
         
     | 
| 
      
 101 
     | 
    
         
            +
                      break logger.debug('no processors') if @ready.empty?
         
     | 
| 
      
 102 
     | 
    
         
            +
                      found = false
         
     | 
| 
      
 103 
     | 
    
         
            +
                      @ready.size.times do
         
     | 
| 
      
 104 
     | 
    
         
            +
                        found ||= find_work(@queues.sample)
         
     | 
| 
       118 
105 
     | 
    
         
             
                      end
         
     | 
| 
      
 106 
     | 
    
         
            +
                      break logger.debug('nothing to process') unless found
         
     | 
| 
       119 
107 
     | 
    
         
             
                    end
         
     | 
| 
       120 
108 
     | 
    
         | 
| 
       121 
109 
     | 
    
         
             
                    # This is the polling loop that ensures we check Redis every
         
     | 
| 
       122 
110 
     | 
    
         
             
                    # second for work, even if there was nothing to do this time
         
     | 
| 
       123 
111 
     | 
    
         
             
                    # around.
         
     | 
| 
       124 
     | 
    
         
            -
                    after(1)  
     | 
| 
      
 112 
     | 
    
         
            +
                    after(1) do
         
     | 
| 
      
 113 
     | 
    
         
            +
                      dispatch(schedule)
         
     | 
| 
      
 114 
     | 
    
         
            +
                    end if schedule
         
     | 
| 
       125 
115 
     | 
    
         
             
                  end
         
     | 
| 
       126 
116 
     | 
    
         
             
                end
         
     | 
| 
       127 
117 
     | 
    
         |