kulesa-sidekiq 1.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/.rvmrc +4 -0
- data/COMM-LICENSE +83 -0
- data/Changes.md +207 -0
- data/Gemfile +12 -0
- data/LICENSE +22 -0
- data/README.md +61 -0
- data/Rakefile +9 -0
- data/bin/client +7 -0
- data/bin/sidekiq +14 -0
- data/bin/sidekiqctl +74 -0
- data/config.ru +18 -0
- data/examples/chef/cookbooks/sidekiq/README.rdoc +11 -0
- data/examples/chef/cookbooks/sidekiq/recipes/default.rb +55 -0
- data/examples/chef/cookbooks/sidekiq/templates/default/monitrc.conf.erb +8 -0
- data/examples/chef/cookbooks/sidekiq/templates/default/sidekiq.erb +219 -0
- data/examples/chef/cookbooks/sidekiq/templates/default/sidekiq.yml.erb +22 -0
- data/examples/clockwork.rb +44 -0
- data/examples/config.yml +10 -0
- data/examples/monitrc.conf +6 -0
- data/examples/por.rb +27 -0
- data/examples/scheduling.rb +37 -0
- data/examples/sinkiq.rb +59 -0
- data/examples/web-ui.png +0 -0
- data/lib/sidekiq.rb +98 -0
- data/lib/sidekiq/capistrano.rb +35 -0
- data/lib/sidekiq/cli.rb +214 -0
- data/lib/sidekiq/client.rb +72 -0
- data/lib/sidekiq/extensions/action_mailer.rb +26 -0
- data/lib/sidekiq/extensions/active_record.rb +27 -0
- data/lib/sidekiq/extensions/generic_proxy.rb +21 -0
- data/lib/sidekiq/fetch.rb +76 -0
- data/lib/sidekiq/logging.rb +46 -0
- data/lib/sidekiq/manager.rb +163 -0
- data/lib/sidekiq/middleware/chain.rb +96 -0
- data/lib/sidekiq/middleware/client/unique_jobs.rb +36 -0
- data/lib/sidekiq/middleware/server/active_record.rb +13 -0
- data/lib/sidekiq/middleware/server/exception_handler.rb +38 -0
- data/lib/sidekiq/middleware/server/failure_jobs.rb +25 -0
- data/lib/sidekiq/middleware/server/logging.rb +31 -0
- data/lib/sidekiq/middleware/server/retry_jobs.rb +69 -0
- data/lib/sidekiq/middleware/server/timeout.rb +21 -0
- data/lib/sidekiq/middleware/server/unique_jobs.rb +17 -0
- data/lib/sidekiq/processor.rb +92 -0
- data/lib/sidekiq/rails.rb +21 -0
- data/lib/sidekiq/redis_connection.rb +27 -0
- data/lib/sidekiq/retry.rb +59 -0
- data/lib/sidekiq/testing.rb +44 -0
- data/lib/sidekiq/testing/inline.rb +37 -0
- data/lib/sidekiq/util.rb +40 -0
- data/lib/sidekiq/version.rb +3 -0
- data/lib/sidekiq/web.rb +185 -0
- data/lib/sidekiq/worker.rb +62 -0
- data/lib/sidekiq/yaml_patch.rb +21 -0
- data/myapp/.gitignore +15 -0
- data/myapp/Capfile +5 -0
- data/myapp/Gemfile +19 -0
- data/myapp/Rakefile +7 -0
- data/myapp/app/controllers/application_controller.rb +3 -0
- data/myapp/app/controllers/work_controller.rb +38 -0
- data/myapp/app/helpers/application_helper.rb +2 -0
- data/myapp/app/mailers/.gitkeep +0 -0
- data/myapp/app/mailers/user_mailer.rb +9 -0
- data/myapp/app/models/.gitkeep +0 -0
- data/myapp/app/models/post.rb +5 -0
- data/myapp/app/views/layouts/application.html.erb +14 -0
- data/myapp/app/views/user_mailer/greetings.html.erb +3 -0
- data/myapp/app/views/work/index.html.erb +1 -0
- data/myapp/app/workers/hard_worker.rb +10 -0
- data/myapp/config.ru +4 -0
- data/myapp/config/application.rb +59 -0
- data/myapp/config/boot.rb +6 -0
- data/myapp/config/database.yml +25 -0
- data/myapp/config/deploy.rb +15 -0
- data/myapp/config/environment.rb +5 -0
- data/myapp/config/environments/development.rb +38 -0
- data/myapp/config/environments/production.rb +67 -0
- data/myapp/config/environments/test.rb +37 -0
- data/myapp/config/initializers/backtrace_silencers.rb +7 -0
- data/myapp/config/initializers/inflections.rb +15 -0
- data/myapp/config/initializers/mime_types.rb +5 -0
- data/myapp/config/initializers/secret_token.rb +7 -0
- data/myapp/config/initializers/session_store.rb +8 -0
- data/myapp/config/initializers/sidekiq.rb +6 -0
- data/myapp/config/initializers/wrap_parameters.rb +14 -0
- data/myapp/config/locales/en.yml +5 -0
- data/myapp/config/routes.rb +10 -0
- data/myapp/db/migrate/20120123214055_create_posts.rb +10 -0
- data/myapp/db/seeds.rb +7 -0
- data/myapp/lib/assets/.gitkeep +0 -0
- data/myapp/lib/tasks/.gitkeep +0 -0
- data/myapp/log/.gitkeep +0 -0
- data/myapp/script/rails +6 -0
- data/sidekiq.gemspec +27 -0
- data/test/config.yml +9 -0
- data/test/fake_env.rb +0 -0
- data/test/helper.rb +16 -0
- data/test/test_cli.rb +168 -0
- data/test/test_client.rb +119 -0
- data/test/test_extensions.rb +69 -0
- data/test/test_manager.rb +51 -0
- data/test/test_middleware.rb +92 -0
- data/test/test_processor.rb +32 -0
- data/test/test_retry.rb +125 -0
- data/test/test_stats.rb +68 -0
- data/test/test_testing.rb +97 -0
- data/test/test_testing_inline.rb +75 -0
- data/test/test_web.rb +122 -0
- data/web/assets/images/bootstrap/glyphicons-halflings-white.png +0 -0
- data/web/assets/images/bootstrap/glyphicons-halflings.png +0 -0
- data/web/assets/javascripts/application.js +20 -0
- data/web/assets/javascripts/vendor/bootstrap.js +12 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-alert.js +91 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-button.js +98 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-carousel.js +154 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-collapse.js +136 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-dropdown.js +92 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-modal.js +210 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-popover.js +95 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-scrollspy.js +125 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-tab.js +130 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-tooltip.js +270 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-transition.js +51 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-typeahead.js +271 -0
- data/web/assets/javascripts/vendor/jquery.js +9266 -0
- data/web/assets/javascripts/vendor/jquery.timeago.js +148 -0
- data/web/assets/stylesheets/application.css +27 -0
- data/web/assets/stylesheets/vendor/bootstrap-responsive.css +567 -0
- data/web/assets/stylesheets/vendor/bootstrap.css +3365 -0
- data/web/views/index.slim +48 -0
- data/web/views/layout.slim +26 -0
- data/web/views/queue.slim +11 -0
- data/web/views/retries.slim +29 -0
- data/web/views/retry.slim +52 -0
- metadata +371 -0
data/examples/sinkiq.rb
ADDED
@@ -0,0 +1,59 @@
|
|
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'
|
9
|
+
require 'redis'
|
10
|
+
|
11
|
+
$redis = Redis.connect
|
12
|
+
|
13
|
+
class SinatraWorker
|
14
|
+
include Sidekiq::Worker
|
15
|
+
|
16
|
+
def perform(msg="lulz you forgot a msg!")
|
17
|
+
$redis.lpush("sinkiq-example-messages", msg)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
get '/' do
|
22
|
+
@failed = $redis.get('stat:failed')
|
23
|
+
@processed = $redis.get('stat:processed')
|
24
|
+
@messages = $redis.lrange('sinkiq-example-messages', 0, -1)
|
25
|
+
erb :index
|
26
|
+
end
|
27
|
+
|
28
|
+
post '/msg' do
|
29
|
+
SinatraWorker.perform_async params[:msg]
|
30
|
+
redirect to('/')
|
31
|
+
end
|
32
|
+
|
33
|
+
__END__
|
34
|
+
|
35
|
+
@@ layout
|
36
|
+
<html>
|
37
|
+
<head>
|
38
|
+
<title>Sinatra + Sidekiq</title>
|
39
|
+
<body>
|
40
|
+
<%= yield %>
|
41
|
+
</body>
|
42
|
+
</html>
|
43
|
+
|
44
|
+
@@ index
|
45
|
+
<h1>Sinatra + Sidekiq Example</h1>
|
46
|
+
<h2>Failed: <%= @failed %></h2>
|
47
|
+
<h2>Processed: <%= @processed %></h2>
|
48
|
+
|
49
|
+
<form method="post" action="/msg">
|
50
|
+
<input type="text" name="msg">
|
51
|
+
<input type="submit" value="Add Message">
|
52
|
+
</form>
|
53
|
+
|
54
|
+
<a href="/">Refresh page</a>
|
55
|
+
|
56
|
+
<h3>Messages</h3>
|
57
|
+
<% @messages.each do |msg| %>
|
58
|
+
<p><%= msg %></p>
|
59
|
+
<% end %>
|
data/examples/web-ui.png
ADDED
Binary file
|
data/lib/sidekiq.rb
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'sidekiq/version'
|
2
|
+
require 'sidekiq/logging'
|
3
|
+
require 'sidekiq/client'
|
4
|
+
require 'sidekiq/worker'
|
5
|
+
require 'sidekiq/redis_connection'
|
6
|
+
require 'sidekiq/util'
|
7
|
+
|
8
|
+
require 'sidekiq/extensions/action_mailer'
|
9
|
+
require 'sidekiq/extensions/active_record'
|
10
|
+
require 'sidekiq/rails' if defined?(::Rails)
|
11
|
+
|
12
|
+
module Sidekiq
|
13
|
+
|
14
|
+
DEFAULTS = {
|
15
|
+
:queues => [],
|
16
|
+
:concurrency => 25,
|
17
|
+
:require => '.',
|
18
|
+
:environment => nil,
|
19
|
+
:timeout => 8,
|
20
|
+
:enable_rails_extensions => true,
|
21
|
+
}
|
22
|
+
|
23
|
+
def self.options
|
24
|
+
@options ||= DEFAULTS.dup
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.options=(opts)
|
28
|
+
@options = opts
|
29
|
+
end
|
30
|
+
|
31
|
+
##
|
32
|
+
# Configuration for Sidekiq server, use like:
|
33
|
+
#
|
34
|
+
# Sidekiq.configure_server do |config|
|
35
|
+
# config.redis = { :namespace => 'myapp', :size => 25, :url => 'redis://myhost:8877/mydb' }
|
36
|
+
# config.server_middleware do |chain|
|
37
|
+
# chain.add MyServerHook
|
38
|
+
# end
|
39
|
+
# end
|
40
|
+
def self.configure_server
|
41
|
+
yield self if server?
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# Configuration for Sidekiq client, use like:
|
46
|
+
#
|
47
|
+
# Sidekiq.configure_client do |config|
|
48
|
+
# config.redis = { :namespace => 'myapp', :size => 1, :url => 'redis://myhost:8877/mydb' }
|
49
|
+
# end
|
50
|
+
def self.configure_client
|
51
|
+
yield self unless server?
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.server?
|
55
|
+
defined?(Sidekiq::CLI)
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.redis(&block)
|
59
|
+
@redis ||= Sidekiq::RedisConnection.create
|
60
|
+
raise ArgumentError, "requires a block" if !block
|
61
|
+
@redis.with(&block)
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.redis=(hash)
|
65
|
+
if hash.is_a?(Hash)
|
66
|
+
@redis = RedisConnection.create(hash)
|
67
|
+
elsif hash.is_a?(ConnectionPool)
|
68
|
+
@redis = hash
|
69
|
+
else
|
70
|
+
raise ArgumentError, "redis= requires a Hash or ConnectionPool"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.client_middleware
|
75
|
+
@client_chain ||= Client.default_middleware
|
76
|
+
yield @client_chain if block_given?
|
77
|
+
@client_chain
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.server_middleware
|
81
|
+
@server_chain ||= Processor.default_middleware
|
82
|
+
yield @server_chain if block_given?
|
83
|
+
@server_chain
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.load_json(string)
|
87
|
+
MultiJson.decode(string)
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.dump_json(object)
|
91
|
+
MultiJson.encode(object)
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.logger
|
95
|
+
Sidekiq::Logging.logger
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
Capistrano::Configuration.instance.load do
|
2
|
+
before "deploy", "sidekiq:quiet"
|
3
|
+
after "deploy:stop", "sidekiq:stop"
|
4
|
+
after "deploy:start", "sidekiq:start"
|
5
|
+
after "deploy:restart", "sidekiq:restart"
|
6
|
+
|
7
|
+
_cset(:sidekiq_timeout) { 10 }
|
8
|
+
_cset(:sidekiq_role) { :app }
|
9
|
+
|
10
|
+
namespace :sidekiq do
|
11
|
+
|
12
|
+
desc "Quiet sidekiq (stop accepting new work)"
|
13
|
+
task :quiet, :roles => lambda { fetch(:sidekiq_role) }, :on_no_matching_servers => :continue do
|
14
|
+
run "cd #{current_path} && if [ -f #{current_path}/tmp/pids/sidekiq.pid ]; then #{fetch(:bundle_cmd, "bundle")} exec sidekiqctl quiet #{current_path}/tmp/pids/sidekiq.pid ; fi"
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "Stop sidekiq"
|
18
|
+
task :stop, :roles => lambda { fetch(:sidekiq_role) }, :on_no_matching_servers => :continue do
|
19
|
+
run "cd #{current_path} && if [ -f #{current_path}/tmp/pids/sidekiq.pid ]; then #{fetch(:bundle_cmd, "bundle")} exec sidekiqctl stop #{current_path}/tmp/pids/sidekiq.pid #{fetch :sidekiq_timeout} ; fi"
|
20
|
+
end
|
21
|
+
|
22
|
+
desc "Start sidekiq"
|
23
|
+
task :start, :roles => lambda { fetch(:sidekiq_role) }, :on_no_matching_servers => :continue do
|
24
|
+
rails_env = fetch(:rails_env, "production")
|
25
|
+
run "cd #{current_path} ; nohup #{fetch(:bundle_cmd, "bundle")} exec sidekiq -e #{rails_env} -C #{current_path}/config/sidekiq.yml -P #{current_path}/tmp/pids/sidekiq.pid >> #{current_path}/log/sidekiq.log 2>&1 &", :pty => false
|
26
|
+
end
|
27
|
+
|
28
|
+
desc "Restart sidekiq"
|
29
|
+
task :restart, :roles => lambda { fetch(:sidekiq_role) }, :on_no_matching_servers => :continue do
|
30
|
+
stop
|
31
|
+
start
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
data/lib/sidekiq/cli.rb
ADDED
@@ -0,0 +1,214 @@
|
|
1
|
+
trap 'INT' do
|
2
|
+
# Handle Ctrl-C in JRuby like MRI
|
3
|
+
# http://jira.codehaus.org/browse/JRUBY-4637
|
4
|
+
Sidekiq::CLI.instance.interrupt
|
5
|
+
end
|
6
|
+
|
7
|
+
trap 'TERM' do
|
8
|
+
# Heroku sends TERM and then waits 10 seconds for process to exit.
|
9
|
+
Sidekiq::CLI.instance.interrupt
|
10
|
+
end
|
11
|
+
|
12
|
+
trap 'USR1' do
|
13
|
+
Sidekiq.logger.info "Received USR1, no longer accepting new work"
|
14
|
+
mgr = Sidekiq::CLI.instance.manager
|
15
|
+
mgr.stop! if mgr
|
16
|
+
end
|
17
|
+
|
18
|
+
trap 'TTIN' do
|
19
|
+
Thread.list.each do |thread|
|
20
|
+
puts "Thread TID-#{thread.object_id.to_s(36)} #{thread['label']}"
|
21
|
+
puts thread.backtrace.join("\n")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
require 'yaml'
|
26
|
+
require 'singleton'
|
27
|
+
require 'optparse'
|
28
|
+
require 'celluloid'
|
29
|
+
|
30
|
+
require 'sidekiq'
|
31
|
+
require 'sidekiq/util'
|
32
|
+
require 'sidekiq/manager'
|
33
|
+
require 'sidekiq/retry'
|
34
|
+
|
35
|
+
module Sidekiq
|
36
|
+
class CLI
|
37
|
+
include Util
|
38
|
+
include Singleton
|
39
|
+
|
40
|
+
# Used for CLI testing
|
41
|
+
attr_accessor :code
|
42
|
+
attr_accessor :manager
|
43
|
+
|
44
|
+
def initialize
|
45
|
+
@code = nil
|
46
|
+
@interrupt_mutex = Mutex.new
|
47
|
+
@interrupted = false
|
48
|
+
end
|
49
|
+
|
50
|
+
def parse(args=ARGV)
|
51
|
+
@code = nil
|
52
|
+
Sidekiq.logger
|
53
|
+
|
54
|
+
cli = parse_options(args)
|
55
|
+
config = parse_config(cli)
|
56
|
+
options.merge!(config.merge(cli))
|
57
|
+
|
58
|
+
Sidekiq.logger.level = Logger::DEBUG if options[:verbose]
|
59
|
+
Celluloid.logger = nil
|
60
|
+
|
61
|
+
validate!
|
62
|
+
write_pid
|
63
|
+
boot_system
|
64
|
+
end
|
65
|
+
|
66
|
+
def run
|
67
|
+
@manager = Sidekiq::Manager.new(options)
|
68
|
+
poller = Sidekiq::Retry::Poller.new
|
69
|
+
begin
|
70
|
+
logger.info 'Starting processing, hit Ctrl-C to stop'
|
71
|
+
@manager.start!
|
72
|
+
poller.poll!
|
73
|
+
sleep
|
74
|
+
rescue Interrupt
|
75
|
+
logger.info 'Shutting down'
|
76
|
+
poller.terminate! if poller.alive?
|
77
|
+
@manager.stop!(:shutdown => true, :timeout => options[:timeout])
|
78
|
+
@manager.wait(:shutdown)
|
79
|
+
# Explicitly exit so busy Processor threads can't block
|
80
|
+
# process shutdown.
|
81
|
+
exit(0)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def interrupt
|
86
|
+
@interrupt_mutex.synchronize do
|
87
|
+
unless @interrupted
|
88
|
+
@interrupted = true
|
89
|
+
Thread.main.raise Interrupt
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def die(code)
|
97
|
+
exit(code)
|
98
|
+
end
|
99
|
+
|
100
|
+
def options
|
101
|
+
Sidekiq.options
|
102
|
+
end
|
103
|
+
|
104
|
+
def detected_environment
|
105
|
+
options[:environment] ||= ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
|
106
|
+
end
|
107
|
+
|
108
|
+
def boot_system
|
109
|
+
ENV['RACK_ENV'] = ENV['RAILS_ENV'] = detected_environment
|
110
|
+
|
111
|
+
raise ArgumentError, "#{options[:require]} does not exist" unless File.exist?(options[:require])
|
112
|
+
|
113
|
+
if File.directory?(options[:require])
|
114
|
+
require 'rails'
|
115
|
+
require 'sidekiq/rails'
|
116
|
+
require File.expand_path("#{options[:require]}/config/environment.rb")
|
117
|
+
::Rails.application.eager_load!
|
118
|
+
else
|
119
|
+
require options[:require]
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def validate!
|
124
|
+
options[:queues] << 'default' if options[:queues].empty?
|
125
|
+
options[:queues].shuffle!
|
126
|
+
|
127
|
+
if !File.exist?(options[:require]) ||
|
128
|
+
(File.directory?(options[:require]) && !File.exist?("#{options[:require]}/config/application.rb"))
|
129
|
+
logger.info "=================================================================="
|
130
|
+
logger.info " Please point sidekiq to a Rails 3 application or a Ruby file "
|
131
|
+
logger.info " to load your worker classes with -r [DIR|FILE]."
|
132
|
+
logger.info "=================================================================="
|
133
|
+
logger.info @parser
|
134
|
+
die(1)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def parse_options(argv)
|
139
|
+
opts = {}
|
140
|
+
|
141
|
+
@parser = OptionParser.new do |o|
|
142
|
+
o.on "-q", "--queue QUEUE,WEIGHT", "Queue to process, with optional weight" do |arg|
|
143
|
+
q, weight = arg.split(",")
|
144
|
+
parse_queues(opts, q, weight)
|
145
|
+
end
|
146
|
+
|
147
|
+
o.on "-v", "--verbose", "Print more verbose output" do
|
148
|
+
Sidekiq.logger.level = ::Logger::DEBUG
|
149
|
+
end
|
150
|
+
|
151
|
+
o.on '-e', '--environment ENV', "Application environment" do |arg|
|
152
|
+
opts[:environment] = arg
|
153
|
+
end
|
154
|
+
|
155
|
+
o.on '-t', '--timeout NUM', "Shutdown timeout" do |arg|
|
156
|
+
opts[:timeout] = arg.to_i
|
157
|
+
end
|
158
|
+
|
159
|
+
o.on '-r', '--require [PATH|DIR]', "Location of Rails application with workers or file to require" do |arg|
|
160
|
+
opts[:require] = arg
|
161
|
+
end
|
162
|
+
|
163
|
+
o.on '-c', '--concurrency INT', "processor threads to use" do |arg|
|
164
|
+
opts[:concurrency] = arg.to_i
|
165
|
+
end
|
166
|
+
|
167
|
+
o.on '-P', '--pidfile PATH', "path to pidfile" do |arg|
|
168
|
+
opts[:pidfile] = arg
|
169
|
+
end
|
170
|
+
|
171
|
+
o.on '-C', '--config PATH', "path to YAML config file" do |arg|
|
172
|
+
opts[:config_file] = arg
|
173
|
+
end
|
174
|
+
|
175
|
+
o.on '-V', '--version', "Print version and exit" do |arg|
|
176
|
+
puts "Sidekiq #{Sidekiq::VERSION}"
|
177
|
+
die(0)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
@parser.banner = "sidekiq [options]"
|
182
|
+
@parser.on_tail "-h", "--help", "Show help" do
|
183
|
+
logger.info @parser
|
184
|
+
die 1
|
185
|
+
end
|
186
|
+
@parser.parse!(argv)
|
187
|
+
opts
|
188
|
+
end
|
189
|
+
|
190
|
+
def write_pid
|
191
|
+
if path = options[:pidfile]
|
192
|
+
File.open(path, 'w') do |f|
|
193
|
+
f.puts Process.pid
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def parse_config(cli)
|
199
|
+
opts = {}
|
200
|
+
if cli[:config_file] && File.exist?(cli[:config_file])
|
201
|
+
opts = YAML.load_file cli[:config_file]
|
202
|
+
queues = opts.delete(:queues) || []
|
203
|
+
queues.each { |name, weight| parse_queues(opts, name, weight) }
|
204
|
+
end
|
205
|
+
opts
|
206
|
+
end
|
207
|
+
|
208
|
+
def parse_queues(opts, q, weight)
|
209
|
+
(weight || 1).to_i.times do
|
210
|
+
(opts[:queues] ||= []) << q
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'multi_json'
|
2
|
+
|
3
|
+
require 'sidekiq/middleware/chain'
|
4
|
+
require 'sidekiq/middleware/client/unique_jobs'
|
5
|
+
|
6
|
+
module Sidekiq
|
7
|
+
class Client
|
8
|
+
|
9
|
+
def self.default_middleware
|
10
|
+
Middleware::Chain.new do |m|
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.registered_workers
|
15
|
+
Sidekiq.redis { |x| x.smembers('workers') }
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.registered_queues
|
19
|
+
Sidekiq.redis { |x| x.smembers('queues') }
|
20
|
+
end
|
21
|
+
|
22
|
+
##
|
23
|
+
# The main method used to push a job to Redis. Accepts a number of options:
|
24
|
+
#
|
25
|
+
# queue - the named queue to use, default 'default'
|
26
|
+
# class - the worker class to call, required
|
27
|
+
# args - an array of simple arguments to the perform method, must be JSON-serializable
|
28
|
+
# retry - whether to retry this job if it fails, true or false, default true
|
29
|
+
# backtrace - whether to save any error backtrace, default false
|
30
|
+
#
|
31
|
+
# All options must be strings, not symbols. NB: because we are serializing to JSON, all
|
32
|
+
# symbols in 'args' will be converted to strings.
|
33
|
+
#
|
34
|
+
# Example:
|
35
|
+
# Sidekiq::Client.push('queue' => 'my_queue', 'class' => MyWorker, 'args' => ['foo', 1, :bat => 'bar'])
|
36
|
+
#
|
37
|
+
def self.push(item)
|
38
|
+
raise(ArgumentError, "Message must be a Hash of the form: { 'class' => SomeWorker, 'args' => ['bob', 1, :foo => 'bar'] }") unless item.is_a?(Hash)
|
39
|
+
raise(ArgumentError, "Message must include a class and set of arguments: #{item.inspect}") if !item['class'] || !item['args']
|
40
|
+
raise(ArgumentError, "Message must include a Sidekiq::Worker class, not class name: #{item['class'].ancestors.inspect}") if !item['class'].is_a?(Class) || !item['class'].respond_to?('get_sidekiq_options')
|
41
|
+
|
42
|
+
worker_class = item['class']
|
43
|
+
item['class'] = item['class'].to_s
|
44
|
+
|
45
|
+
item = worker_class.get_sidekiq_options.merge(item)
|
46
|
+
item['retry'] = !!item['retry']
|
47
|
+
queue = item['queue']
|
48
|
+
|
49
|
+
pushed = false
|
50
|
+
Sidekiq.client_middleware.invoke(worker_class, item, queue) do
|
51
|
+
payload = Sidekiq.dump_json(item)
|
52
|
+
Sidekiq.redis do |conn|
|
53
|
+
_, pushed = conn.multi do
|
54
|
+
conn.sadd('queues', queue)
|
55
|
+
conn.rpush("queue:#{queue}", payload)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
!! pushed
|
60
|
+
end
|
61
|
+
|
62
|
+
# Redis compatibility helper. Example usage:
|
63
|
+
#
|
64
|
+
# Sidekiq::Client.enqueue(MyWorker, 'foo', 1, :bat => 'bar')
|
65
|
+
#
|
66
|
+
# Messages are enqueued to the 'default' queue.
|
67
|
+
#
|
68
|
+
def self.enqueue(klass, *args)
|
69
|
+
klass.perform_async(*args)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|