sidekiq 2.6.5 → 2.7.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sidekiq might be problematic. Click here for more details.
- data.tar.gz.sig +0 -0
- data/.gitignore +1 -0
- data/.public_cert.pem +20 -0
- data/Changes.md +33 -0
- data/Gemfile +1 -0
- data/examples/runit/README.md +16 -0
- data/examples/runit/log/run +2 -0
- data/examples/runit/run +4 -0
- data/examples/upstart.conf +39 -0
- data/lib/sidekiq.rb +3 -1
- data/lib/sidekiq/api.rb +50 -0
- data/lib/sidekiq/capistrano.rb +4 -4
- data/lib/sidekiq/cli.rb +106 -34
- data/lib/sidekiq/redis_connection.rb +2 -1
- data/lib/sidekiq/testing/inline.rb +1 -1
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web.rb +20 -7
- data/sidekiq.gemspec +2 -0
- data/test/env_based_config.yml +11 -0
- data/test/test_api.rb +39 -0
- data/test/test_cli.rb +42 -3
- data/test/test_redis_connection.rb +35 -0
- data/test/test_sidekiq.rb +13 -0
- data/test/test_web.rb +41 -10
- data/web/assets/javascripts/application.js +4 -0
- data/web/assets/javascripts/dashboard.js +14 -2
- data/web/views/_workers.slim +1 -1
- data/web/views/dashboard.slim +6 -5
- data/web/views/layout.slim +3 -0
- data/web/views/queue.slim +1 -1
- metadata +38 -5
- metadata.gz.sig +0 -0
- data/.rvmrc +0 -3
data.tar.gz.sig
ADDED
Binary file
|
data/.gitignore
CHANGED
data/.public_cert.pem
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIIDMDCCAhigAwIBAgIBADANBgkqhkiG9w0BAQUFADA+MRAwDgYDVQQDDAdtcGVy
|
3
|
+
aGFtMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZFgNjb20w
|
4
|
+
HhcNMTMwMTMwMTkyODU3WhcNMTQwMTMwMTkyODU3WjA+MRAwDgYDVQQDDAdtcGVy
|
5
|
+
aGFtMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZFgNjb20w
|
6
|
+
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC/rvUwLpOQEsPfi1T/QtRj
|
7
|
+
dc7+0DE8ljILJqJ+sUkZ881Uxit6M+8ZZoqNkwa2e2RCWRBdNx625RQh2bX4utpY
|
8
|
+
kloTWQ6PBbrDDVHVRAkuwDbaH4wE8rtwXDcKuto4xaHjN+EYWf2rHBNC4+qMX+ev
|
9
|
+
CD3MRBG7xOURthDpRTKBXTnDA6qPlFH+4BONLyUOPgz2j0hzVQbA/795KJXpIih9
|
10
|
+
goEiaWzvvqs8upsdFGQoVvaFUKE/Zr79Zm0kNC7dDtG0toHll0XMFUL/JjJT2Rh2
|
11
|
+
cALDwIxwVdL7r6l2O4qeuXL7HKSC5ZyNqx3JoVwrxfXk2I2DOGBqrGSJJFWUq3i1
|
12
|
+
AgMBAAGjOTA3MAkGA1UdEwQCMAAwHQYDVR0OBBYEFNGAnRmrLLc4NFfTSL2PjpAx
|
13
|
+
GJnfMAsGA1UdDwQEAwIEsDANBgkqhkiG9w0BAQUFAAOCAQEAf9vqK2frmnKcyDE7
|
14
|
+
dt9eLthYUxZ8HlctLSXDs4tjlEKKfwkD1Yalu4PNzhjrHqXa8hYTxqHPfWmV771q
|
15
|
+
qT/OLVvL4ofjrXmAG+hqwzcT7grSbYDAK14ITY8M8DpC2jvuGR3MnyChi9ep0pLa
|
16
|
+
E9Jy35lxa3UFBjr0neI9QxowMilmjUHnPDzVHbzmWAQxPoc18uiU9PXd0h+Jsx2F
|
17
|
+
y8Ix+zZ1LIOWk9O9WnMdLOTjUFnA/zutM3Nzv8zNBnUJjH5/A5igCIAL+6vU7+su
|
18
|
+
sLF+JCFPbBgvRqL5hX03CKuyOUNmUVT5AnCDnfIDUV/kJhX7Wfr6IqaUHmUcy/jn
|
19
|
+
ey6hlw==
|
20
|
+
-----END CERTIFICATE-----
|
data/Changes.md
CHANGED
@@ -1,3 +1,36 @@
|
|
1
|
+
2.7.0
|
2
|
+
-----------
|
3
|
+
|
4
|
+
- Add -d daemonize flag, capistrano recipe has been updated to use it [#662]
|
5
|
+
- Support profiling via `ruby-prof` with -p. When Sidekiq is stopped
|
6
|
+
via Ctrl-C, it will output `profile.html`. You must add `gem 'ruby-prof'` to your Gemfile for it to work.
|
7
|
+
- Dynamically update Redis stats on dashboard [brandonhilkert]
|
8
|
+
- Add Sidekiq::Workers API giving programmatic access to the current
|
9
|
+
set of active workers.
|
10
|
+
|
11
|
+
```
|
12
|
+
workers = Sidekiq::Workers.new
|
13
|
+
workers.size => 2
|
14
|
+
workers.each do |name, work|
|
15
|
+
# name is a unique identifier per Processor instance
|
16
|
+
# work is a Hash which looks like:
|
17
|
+
# { 'queue' => name, 'run_at' => timestamp, 'payload' => msg }
|
18
|
+
end
|
19
|
+
```
|
20
|
+
|
21
|
+
- Allow environment-specific sections within the config file which
|
22
|
+
override the global values [dtaniwaki, #630]
|
23
|
+
|
24
|
+
```
|
25
|
+
---
|
26
|
+
:concurrency: 50
|
27
|
+
:verbose: false
|
28
|
+
staging:
|
29
|
+
:verbose: true
|
30
|
+
:concurrency: 5
|
31
|
+
```
|
32
|
+
|
33
|
+
|
1
34
|
2.6.5
|
2
35
|
-----------
|
3
36
|
|
data/Gemfile
CHANGED
@@ -0,0 +1,16 @@
|
|
1
|
+
This is a "service" directory for sidekiq. You should probably modify
|
2
|
+
the relevant paths in the run script, and the log/run script, if
|
3
|
+
necessary. It assumes a "sidekiq" user is created that will run the
|
4
|
+
sidekiq process. To supervise under runit, link this directory to the
|
5
|
+
runsvdir for your system (e.g., `/etc/service` on Debian/Ubuntu).
|
6
|
+
|
7
|
+
If you're using Chef, use the
|
8
|
+
[example cookbook](https://github.com/mperham/sidekiq/tree/master/examples/chef/cookbooks/sidekiq)
|
9
|
+
(modified for your environment), and Opscode's
|
10
|
+
[runit cookbook](http://ckbk.it/runit) to set up the service.
|
11
|
+
|
12
|
+
Author: Joshua Timberman <joshua@opscode.com>
|
13
|
+
|
14
|
+
Runit is written by Gerrit Pape.
|
15
|
+
|
16
|
+
* http://smarden.org/runit
|
data/examples/runit/run
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# /etc/init/sidekiq.conf - Sidekiq config
|
2
|
+
|
3
|
+
# This example config should work with Ubuntu 12.04+
|
4
|
+
#
|
5
|
+
# Save this config as /etc/init/sidekiq.conf then mange sidekiq with:
|
6
|
+
# sudo start sidekiq
|
7
|
+
# sudo stop sidekiq
|
8
|
+
# sudo status sidekiq
|
9
|
+
#
|
10
|
+
# or use the service command:
|
11
|
+
# sudo service sidekiq {start,stop,restart,status}
|
12
|
+
#
|
13
|
+
# This is the exact script used to manage Sidekiq on TheClymb.com
|
14
|
+
#
|
15
|
+
|
16
|
+
description "Sidekiq Background Worker System"
|
17
|
+
|
18
|
+
start on runlevel [2345]
|
19
|
+
stop on shutdown
|
20
|
+
|
21
|
+
setuid deploy
|
22
|
+
setgid deploy
|
23
|
+
|
24
|
+
respawn
|
25
|
+
respawn limit 3 30
|
26
|
+
|
27
|
+
script
|
28
|
+
# this script runs in /bin/sh by default
|
29
|
+
# respawn as bash so we can source in rbenv
|
30
|
+
exec /bin/bash <<EOT
|
31
|
+
# use syslog for logging
|
32
|
+
exec >/dev/kmsg 2>&1
|
33
|
+
# pull in system rbenv
|
34
|
+
source /etc/profile.d/rbenv.sh
|
35
|
+
|
36
|
+
cd /opt/theclymb/current
|
37
|
+
exec bin/sidekiq -e production -C config/sidekiq.yml -P tmp/pids/sidekiq.pid
|
38
|
+
EOT
|
39
|
+
end script
|
data/lib/sidekiq.rb
CHANGED
@@ -23,6 +23,7 @@ module Sidekiq
|
|
23
23
|
:require => '.',
|
24
24
|
:environment => nil,
|
25
25
|
:timeout => 8,
|
26
|
+
:profile => false,
|
26
27
|
}
|
27
28
|
|
28
29
|
def self.options
|
@@ -61,14 +62,15 @@ module Sidekiq
|
|
61
62
|
end
|
62
63
|
|
63
64
|
def self.redis(&block)
|
64
|
-
@redis ||= Sidekiq::RedisConnection.create
|
65
65
|
raise ArgumentError, "requires a block" if !block
|
66
|
+
@redis ||= Sidekiq::RedisConnection.create
|
66
67
|
@redis.with(&block)
|
67
68
|
end
|
68
69
|
|
69
70
|
def self.redis=(hash)
|
70
71
|
if hash.is_a?(Hash)
|
71
72
|
@redis = RedisConnection.create(hash)
|
73
|
+
options[:namespace] ||= hash[:namespace]
|
72
74
|
elsif hash.is_a?(ConnectionPool)
|
73
75
|
@redis = hash
|
74
76
|
else
|
data/lib/sidekiq/api.rb
CHANGED
@@ -210,6 +210,11 @@ module Sidekiq
|
|
210
210
|
@parent.delete(score, jid)
|
211
211
|
end
|
212
212
|
|
213
|
+
def reschedule(at)
|
214
|
+
@parent.delete(score, jid)
|
215
|
+
@parent.schedule(at, item)
|
216
|
+
end
|
217
|
+
|
213
218
|
def retry
|
214
219
|
raise "Retry not available on jobs not in the Retry queue." unless item["failed_at"]
|
215
220
|
Sidekiq.redis do |conn|
|
@@ -235,6 +240,12 @@ module Sidekiq
|
|
235
240
|
Sidekiq.redis {|c| c.zcard(@zset) }
|
236
241
|
end
|
237
242
|
|
243
|
+
def schedule(timestamp, message)
|
244
|
+
Sidekiq.redis do |conn|
|
245
|
+
conn.zadd(@zset, timestamp.to_s, Sidekiq.dump_json(message))
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
238
249
|
def each(&block)
|
239
250
|
# page thru the sorted set backwards so deleting entries doesn't screw up indexing
|
240
251
|
page = -1
|
@@ -333,4 +344,43 @@ module Sidekiq
|
|
333
344
|
end
|
334
345
|
end
|
335
346
|
|
347
|
+
|
348
|
+
##
|
349
|
+
# Programmatic access to the current active worker set.
|
350
|
+
#
|
351
|
+
# WARNING WARNING WARNING
|
352
|
+
#
|
353
|
+
# This is live data that can change every millisecond.
|
354
|
+
# If you do #size => 5 and then expect #each to be
|
355
|
+
# called 5 times, you're going to have a bad time.
|
356
|
+
#
|
357
|
+
# workers = Sidekiq::Workers.new
|
358
|
+
# workers.size => 2
|
359
|
+
# workers.each do |name, work|
|
360
|
+
# # name is a unique identifier per Processor instance
|
361
|
+
# # work is a Hash which looks like:
|
362
|
+
# # { 'queue' => name, 'run_at' => timestamp, 'payload' => msg }
|
363
|
+
# end
|
364
|
+
|
365
|
+
class Workers
|
366
|
+
include Enumerable
|
367
|
+
|
368
|
+
def each(&block)
|
369
|
+
Sidekiq.redis do |conn|
|
370
|
+
workers = conn.smembers("workers")
|
371
|
+
workers.each do |w|
|
372
|
+
msg = conn.get("worker:#{w}")
|
373
|
+
next unless msg
|
374
|
+
block.call(w, Sidekiq.load_json(msg))
|
375
|
+
end
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
379
|
+
def size
|
380
|
+
Sidekiq.redis do |conn|
|
381
|
+
conn.scard("workers")
|
382
|
+
end.to_i
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
336
386
|
end
|
data/lib/sidekiq/capistrano.rb
CHANGED
@@ -2,7 +2,7 @@ Capistrano::Configuration.instance.load do
|
|
2
2
|
before "deploy:update_code", "sidekiq:quiet"
|
3
3
|
after "deploy:stop", "sidekiq:stop"
|
4
4
|
after "deploy:start", "sidekiq:start"
|
5
|
-
|
5
|
+
before "deploy:restart", "sidekiq:restart"
|
6
6
|
|
7
7
|
_cset(:sidekiq_cmd) { "#{fetch(:bundle_cmd, "bundle")} exec sidekiq" }
|
8
8
|
_cset(:sidekiqctl_cmd) { "#{fetch(:bundle_cmd, "bundle")} exec sidekiqctl" }
|
@@ -21,14 +21,14 @@ Capistrano::Configuration.instance.load do
|
|
21
21
|
desc "Quiet sidekiq (stop accepting new work)"
|
22
22
|
task :quiet, :roles => lambda { fetch(:sidekiq_role) }, :on_no_matching_servers => :continue do
|
23
23
|
for_each_process do |pid_file, idx|
|
24
|
-
run "if [ -d #{current_path} ] && [ -f #{pid_file} ]; then cd #{current_path} && #{fetch(:sidekiqctl_cmd)} quiet #{pid_file} ; fi"
|
24
|
+
run "if [ -d #{current_path} ] && [ -f #{pid_file} ] && kill -0 `cat #{pid_file}`> /dev/null 2>&1; then cd #{current_path} && #{fetch(:sidekiqctl_cmd)} quiet #{pid_file} ; else echo 'Sidekiq is not running'; fi"
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
28
|
desc "Stop sidekiq"
|
29
29
|
task :stop, :roles => lambda { fetch(:sidekiq_role) }, :on_no_matching_servers => :continue do
|
30
30
|
for_each_process do |pid_file, idx|
|
31
|
-
run "if [ -d #{current_path} ] && [ -f #{pid_file} ]; then cd #{current_path} && #{fetch(:sidekiqctl_cmd)} stop #{pid_file} #{fetch :sidekiq_timeout} ; fi"
|
31
|
+
run "if [ -d #{current_path} ] && [ -f #{pid_file} ] && kill -0 `cat #{pid_file}`> /dev/null 2>&1; then cd #{current_path} && #{fetch(:sidekiqctl_cmd)} stop #{pid_file} #{fetch :sidekiq_timeout} ; else echo 'Sidekiq is not running'; fi"
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
@@ -36,7 +36,7 @@ Capistrano::Configuration.instance.load do
|
|
36
36
|
task :start, :roles => lambda { fetch(:sidekiq_role) }, :on_no_matching_servers => :continue do
|
37
37
|
rails_env = fetch(:rails_env, "production")
|
38
38
|
for_each_process do |pid_file, idx|
|
39
|
-
run "cd #{current_path} ;
|
39
|
+
run "cd #{current_path} ; #{fetch(:sidekiq_cmd)} -d -e #{rails_env} -C #{current_path}/config/sidekiq.yml -i #{idx} -P #{pid_file} -L #{current_path}/log/sidekiq.log"
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
data/lib/sidekiq/cli.rb
CHANGED
@@ -1,4 +1,11 @@
|
|
1
1
|
trap 'INT' do
|
2
|
+
if Sidekiq.options[:profile]
|
3
|
+
result = RubyProf.stop
|
4
|
+
printer = RubyProf::GraphHtmlPrinter.new(result)
|
5
|
+
File.open("profile.html", 'w') do |f|
|
6
|
+
printer.print(f, :min_percent => 1)
|
7
|
+
end
|
8
|
+
end
|
2
9
|
# Handle Ctrl-C in JRuby like MRI
|
3
10
|
# http://jira.codehaus.org/browse/JRUBY-4637
|
4
11
|
Sidekiq::CLI.instance.interrupt
|
@@ -38,13 +45,10 @@ $stdout.sync = true
|
|
38
45
|
require 'yaml'
|
39
46
|
require 'singleton'
|
40
47
|
require 'optparse'
|
41
|
-
require 'celluloid'
|
42
48
|
require 'erb'
|
43
49
|
|
44
50
|
require 'sidekiq'
|
45
51
|
require 'sidekiq/util'
|
46
|
-
require 'sidekiq/manager'
|
47
|
-
require 'sidekiq/scheduled'
|
48
52
|
|
49
53
|
module Sidekiq
|
50
54
|
class CLI
|
@@ -54,6 +58,7 @@ module Sidekiq
|
|
54
58
|
# Used for CLI testing
|
55
59
|
attr_accessor :code
|
56
60
|
attr_accessor :manager
|
61
|
+
attr_accessor :environment
|
57
62
|
|
58
63
|
def initialize
|
59
64
|
@code = nil
|
@@ -64,13 +69,12 @@ module Sidekiq
|
|
64
69
|
def parse(args=ARGV)
|
65
70
|
@code = nil
|
66
71
|
|
67
|
-
|
68
|
-
config = parse_config(cli)
|
69
|
-
options.merge!(config.merge(cli))
|
70
|
-
|
72
|
+
setup_options(args)
|
71
73
|
initialize_logger
|
72
74
|
validate!
|
75
|
+
daemonize
|
73
76
|
write_pid
|
77
|
+
load_celluloid
|
74
78
|
boot_system
|
75
79
|
end
|
76
80
|
|
@@ -81,10 +85,17 @@ module Sidekiq
|
|
81
85
|
|
82
86
|
Sidekiq::Stats::History.cleanup
|
83
87
|
|
88
|
+
if !options[:daemon]
|
89
|
+
logger.info 'Starting processing, hit Ctrl-C to stop'
|
90
|
+
end
|
91
|
+
|
84
92
|
@manager = Sidekiq::Manager.new(options)
|
85
93
|
poller = Sidekiq::Scheduled::Poller.new
|
86
94
|
begin
|
87
|
-
|
95
|
+
if options[:profile]
|
96
|
+
require 'ruby-prof'
|
97
|
+
RubyProf.start
|
98
|
+
end
|
88
99
|
@manager.async.start
|
89
100
|
poller.async.poll(true)
|
90
101
|
sleep
|
@@ -110,20 +121,71 @@ module Sidekiq
|
|
110
121
|
|
111
122
|
private
|
112
123
|
|
124
|
+
def load_celluloid
|
125
|
+
# Celluloid can't be loaded until after we've daemonized
|
126
|
+
# because it spins up threads and creates locks which get
|
127
|
+
# into a very bad state if forked.
|
128
|
+
require 'celluloid'
|
129
|
+
Celluloid.logger = (options[:verbose] ? Sidekiq.logger : nil)
|
130
|
+
|
131
|
+
require 'sidekiq/manager'
|
132
|
+
require 'sidekiq/scheduled'
|
133
|
+
end
|
134
|
+
|
135
|
+
def daemonize
|
136
|
+
return unless options[:daemon]
|
137
|
+
|
138
|
+
raise ArgumentError, "You really should set a logfile if you're going to daemonize" unless options[:logfile]
|
139
|
+
files_to_reopen = []
|
140
|
+
ObjectSpace.each_object(File) do |file|
|
141
|
+
files_to_reopen << file unless file.closed?
|
142
|
+
end
|
143
|
+
|
144
|
+
Process.daemon(true, true)
|
145
|
+
|
146
|
+
files_to_reopen.each do |file|
|
147
|
+
begin
|
148
|
+
file.reopen file.path, "a+"
|
149
|
+
file.sync = true
|
150
|
+
rescue ::Exception
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
[$stdout, $stderr].each do |io|
|
155
|
+
File.open(options[:logfile], 'ab') do |f|
|
156
|
+
io.reopen(f)
|
157
|
+
end
|
158
|
+
io.sync = true
|
159
|
+
end
|
160
|
+
$stdin.reopen('/dev/null')
|
161
|
+
|
162
|
+
initialize_logger
|
163
|
+
end
|
164
|
+
|
165
|
+
def set_environment(cli_env)
|
166
|
+
@environment = cli_env || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
|
167
|
+
end
|
168
|
+
|
113
169
|
def die(code)
|
114
170
|
exit(code)
|
115
171
|
end
|
116
172
|
|
117
|
-
def
|
118
|
-
|
173
|
+
def setup_options(args)
|
174
|
+
cli = parse_options(args)
|
175
|
+
set_environment cli[:environment]
|
176
|
+
|
177
|
+
cfile = cli[:config_file]
|
178
|
+
|
179
|
+
config = (cfile ? parse_config(cfile) : {})
|
180
|
+
options.merge!(config.merge(cli))
|
119
181
|
end
|
120
182
|
|
121
|
-
def
|
122
|
-
options
|
183
|
+
def options
|
184
|
+
Sidekiq.options
|
123
185
|
end
|
124
186
|
|
125
187
|
def boot_system
|
126
|
-
ENV['RACK_ENV'] = ENV['RAILS_ENV'] =
|
188
|
+
ENV['RACK_ENV'] = ENV['RAILS_ENV'] = environment
|
127
189
|
|
128
190
|
raise ArgumentError, "#{options[:require]} does not exist" unless File.exist?(options[:require])
|
129
191
|
|
@@ -167,41 +229,45 @@ module Sidekiq
|
|
167
229
|
opts = {}
|
168
230
|
|
169
231
|
@parser = OptionParser.new do |o|
|
170
|
-
o.on
|
171
|
-
|
172
|
-
parse_queues opts, queues_and_weights
|
232
|
+
o.on '-c', '--concurrency INT', "processor threads to use" do |arg|
|
233
|
+
opts[:concurrency] = Integer(arg)
|
173
234
|
end
|
174
235
|
|
175
|
-
o.on
|
176
|
-
opts[:
|
236
|
+
o.on '-d', '--daemon', "Daemonize process" do |arg|
|
237
|
+
opts[:daemon] = arg
|
177
238
|
end
|
178
239
|
|
179
240
|
o.on '-e', '--environment ENV', "Application environment" do |arg|
|
180
241
|
opts[:environment] = arg
|
181
242
|
end
|
182
243
|
|
183
|
-
o.on '-t', '--timeout NUM', "Shutdown timeout" do |arg|
|
184
|
-
opts[:timeout] = Integer(arg)
|
185
|
-
end
|
186
|
-
|
187
244
|
o.on '-g', '--tag TAG', "Process tag for procline" do |arg|
|
188
245
|
opts[:tag] = arg
|
189
246
|
end
|
190
247
|
|
191
|
-
o.on '-r', '--require [PATH|DIR]', "Location of Rails application with workers or file to require" do |arg|
|
192
|
-
opts[:require] = arg
|
193
|
-
end
|
194
|
-
|
195
248
|
o.on '-i', '--index INT', "unique process index on this machine" do |arg|
|
196
249
|
opts[:index] = Integer(arg)
|
197
250
|
end
|
198
251
|
|
199
|
-
o.on '-
|
200
|
-
opts[:
|
252
|
+
o.on '-p', '--profile', "Profile all code run by Sidekiq" do |arg|
|
253
|
+
opts[:profile] = arg
|
201
254
|
end
|
202
255
|
|
203
|
-
o.on
|
204
|
-
|
256
|
+
o.on "-q", "--queue QUEUE[,WEIGHT]...", "Queues to process with optional weights" do |arg|
|
257
|
+
queues_and_weights = arg.scan(/([\w\.-]+),?(\d*)/)
|
258
|
+
parse_queues opts, queues_and_weights
|
259
|
+
end
|
260
|
+
|
261
|
+
o.on '-r', '--require [PATH|DIR]', "Location of Rails application with workers or file to require" do |arg|
|
262
|
+
opts[:require] = arg
|
263
|
+
end
|
264
|
+
|
265
|
+
o.on '-t', '--timeout NUM', "Shutdown timeout" do |arg|
|
266
|
+
opts[:timeout] = Integer(arg)
|
267
|
+
end
|
268
|
+
|
269
|
+
o.on "-v", "--verbose", "Print more verbose output" do |arg|
|
270
|
+
opts[:verbose] = arg
|
205
271
|
end
|
206
272
|
|
207
273
|
o.on '-C', '--config PATH', "path to YAML config file" do |arg|
|
@@ -212,6 +278,10 @@ module Sidekiq
|
|
212
278
|
opts[:logfile] = arg
|
213
279
|
end
|
214
280
|
|
281
|
+
o.on '-P', '--pidfile PATH', "path to pidfile" do |arg|
|
282
|
+
opts[:pidfile] = arg
|
283
|
+
end
|
284
|
+
|
215
285
|
o.on '-V', '--version', "Print version and exit" do |arg|
|
216
286
|
puts "Sidekiq #{Sidekiq::VERSION}"
|
217
287
|
die(0)
|
@@ -231,7 +301,6 @@ module Sidekiq
|
|
231
301
|
Sidekiq::Logging.initialize_logger(options[:logfile]) if options[:logfile]
|
232
302
|
|
233
303
|
Sidekiq.logger.level = Logger::DEBUG if options[:verbose]
|
234
|
-
Celluloid.logger = nil unless options[:verbose]
|
235
304
|
end
|
236
305
|
|
237
306
|
def write_pid
|
@@ -242,11 +311,14 @@ module Sidekiq
|
|
242
311
|
end
|
243
312
|
end
|
244
313
|
|
245
|
-
def parse_config(
|
314
|
+
def parse_config(cfile)
|
246
315
|
opts = {}
|
247
|
-
if
|
248
|
-
opts = YAML.load(ERB.new(IO.read(
|
316
|
+
if File.exist?(cfile)
|
317
|
+
opts = YAML.load(ERB.new(IO.read(cfile)).result)
|
318
|
+
opts = opts.merge(opts.delete(environment) || {})
|
249
319
|
parse_queues opts, opts.delete(:queues) || []
|
320
|
+
else
|
321
|
+
raise ArgumentError, "can't find config file #{cfile}"
|
250
322
|
end
|
251
323
|
opts
|
252
324
|
end
|
@@ -9,9 +9,10 @@ module Sidekiq
|
|
9
9
|
driver = options[:driver] || 'ruby'
|
10
10
|
# need a connection for Fetcher and Retry
|
11
11
|
size = options[:size] || (Sidekiq.server? ? (Sidekiq.options[:concurrency] + 2) : 5)
|
12
|
+
namespace = options[:namespace] || Sidekiq.options[:namespace]
|
12
13
|
|
13
14
|
ConnectionPool.new(:timeout => 1, :size => size) do
|
14
|
-
build_client(url,
|
15
|
+
build_client(url, namespace, driver)
|
15
16
|
end
|
16
17
|
end
|
17
18
|
|
@@ -29,7 +29,7 @@ module Sidekiq
|
|
29
29
|
singleton_class.class_eval do
|
30
30
|
alias_method :raw_push_old, :raw_push
|
31
31
|
def raw_push(normed, payload)
|
32
|
-
Array
|
32
|
+
Array(payload).each do |hash|
|
33
33
|
normed['class'].constantize.new.perform(*Sidekiq.load_json(hash)['args'])
|
34
34
|
end
|
35
35
|
|
data/lib/sidekiq/version.rb
CHANGED
data/lib/sidekiq/web.rb
CHANGED
@@ -49,6 +49,10 @@ module Sidekiq
|
|
49
49
|
Sidekiq.redis { |conn| conn.client.location }
|
50
50
|
end
|
51
51
|
|
52
|
+
def namespace
|
53
|
+
Sidekiq.options[:namespace]
|
54
|
+
end
|
55
|
+
|
52
56
|
def root_path
|
53
57
|
"#{env['SCRIPT_NAME']}/"
|
54
58
|
end
|
@@ -95,6 +99,10 @@ module Sidekiq
|
|
95
99
|
parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{options[:delimiter]}")
|
96
100
|
parts.join(options[:separator])
|
97
101
|
end
|
102
|
+
|
103
|
+
def redis_keys
|
104
|
+
["redis_stats", "uptime_in_days", "connected_clients", "used_memory_human", "used_memory_peak_human"]
|
105
|
+
end
|
98
106
|
end
|
99
107
|
|
100
108
|
get "/" do
|
@@ -196,7 +204,7 @@ module Sidekiq
|
|
196
204
|
end
|
197
205
|
|
198
206
|
get '/dashboard' do
|
199
|
-
@redis_info = Sidekiq.redis { |conn| conn.info }
|
207
|
+
@redis_info = Sidekiq.redis { |conn| conn.info }.select{ |k, v| redis_keys.include? k }
|
200
208
|
stats_history = Sidekiq::Stats::History.new((params[:days] || 30).to_i)
|
201
209
|
@processed_history = stats_history.processed
|
202
210
|
@failed_history = stats_history.failed
|
@@ -204,14 +212,19 @@ module Sidekiq
|
|
204
212
|
end
|
205
213
|
|
206
214
|
get '/dashboard/stats' do
|
207
|
-
|
215
|
+
sidekiq_stats = Sidekiq::Stats.new
|
216
|
+
redis_stats = Sidekiq.redis { |conn| conn.info }.select{ |k, v| redis_keys.include? k }
|
217
|
+
|
208
218
|
content_type :json
|
209
219
|
Sidekiq.dump_json({
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
220
|
+
sidekiq: {
|
221
|
+
processed: sidekiq_stats.processed,
|
222
|
+
failed: sidekiq_stats.failed,
|
223
|
+
enqueued: sidekiq_stats.enqueued,
|
224
|
+
scheduled: sidekiq_stats.scheduled_size,
|
225
|
+
retries: sidekiq_stats.retry_size,
|
226
|
+
},
|
227
|
+
redis: redis_stats
|
215
228
|
})
|
216
229
|
end
|
217
230
|
|
data/sidekiq.gemspec
CHANGED
@@ -14,6 +14,8 @@ Gem::Specification.new do |gem|
|
|
14
14
|
gem.name = "sidekiq"
|
15
15
|
gem.require_paths = ["lib"]
|
16
16
|
gem.version = Sidekiq::VERSION
|
17
|
+
gem.signing_key = File.expand_path('~/.ssh/gem-private_key.pem')
|
18
|
+
gem.cert_chain = ['.public_cert.pem']
|
17
19
|
gem.add_dependency 'redis', '~> 3'
|
18
20
|
gem.add_dependency 'redis-namespace'
|
19
21
|
gem.add_dependency 'connection_pool', '~> 1.0'
|
data/test/test_api.rb
CHANGED
@@ -269,6 +269,45 @@ class TestApi < MiniTest::Unit::TestCase
|
|
269
269
|
assert_equal 0, r.size
|
270
270
|
end
|
271
271
|
|
272
|
+
it 'can enumerate workers' do
|
273
|
+
w = Sidekiq::Workers.new
|
274
|
+
assert_equal 0, w.size
|
275
|
+
w.each do |x, y|
|
276
|
+
assert false
|
277
|
+
end
|
278
|
+
|
279
|
+
s = '12345'
|
280
|
+
data = Sidekiq.dump_json({ 'payload' => {}, 'queue' => 'default', 'run_at' => Time.now.to_i })
|
281
|
+
Sidekiq.redis do |c|
|
282
|
+
c.multi do
|
283
|
+
c.sadd('workers', s)
|
284
|
+
c.set("worker:#{s}", data)
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
assert_equal 1, w.size
|
289
|
+
w.each do |x, y|
|
290
|
+
assert_equal s, x
|
291
|
+
assert_equal 'default', y['queue']
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
it 'can reschedule jobs' do
|
296
|
+
add_retry('foo1')
|
297
|
+
add_retry('foo2')
|
298
|
+
|
299
|
+
retries = Sidekiq::RetrySet.new
|
300
|
+
assert_equal 2, retries.size
|
301
|
+
refute(retries.map { |r| r.score > (Time.now.to_f + 9) }.any?)
|
302
|
+
|
303
|
+
retries.each do |retri|
|
304
|
+
retri.reschedule(Time.now.to_f + 10) if retri.jid == 'foo2'
|
305
|
+
end
|
306
|
+
|
307
|
+
assert_equal 2, retries.size
|
308
|
+
assert(retries.map { |r| r.score > (Time.now.to_f + 9) }.any?)
|
309
|
+
end
|
310
|
+
|
272
311
|
def add_retry(jid = 'bob', at = Time.now.to_f)
|
273
312
|
payload = Sidekiq.dump_json('class' => 'ApiWorker', 'args' => [1, 'mike'], 'queue' => 'default', 'jid' => jid, 'retry_count' => 2, 'failed_at' => Time.now.utc)
|
274
313
|
Sidekiq.redis do |conn|
|
data/test/test_cli.rb
CHANGED
@@ -112,7 +112,7 @@ class TestCli < MiniTest::Unit::TestCase
|
|
112
112
|
|
113
113
|
Sidekiq.logger.info('test message')
|
114
114
|
|
115
|
-
assert_match
|
115
|
+
assert_match(/test message/, File.read(@tmp_log_path), "didn't include the log message")
|
116
116
|
end
|
117
117
|
|
118
118
|
it 'appends messages to a logfile' do
|
@@ -125,8 +125,8 @@ class TestCli < MiniTest::Unit::TestCase
|
|
125
125
|
Sidekiq.logger.info('test message')
|
126
126
|
|
127
127
|
log_file_content = File.read(@tmp_log_path)
|
128
|
-
assert_match
|
129
|
-
assert_match
|
128
|
+
assert_match(/already existant/, log_file_content, "didn't include the old message")
|
129
|
+
assert_match(/test message/, log_file_content, "didn't include the new message")
|
130
130
|
end
|
131
131
|
end
|
132
132
|
|
@@ -191,6 +191,45 @@ class TestCli < MiniTest::Unit::TestCase
|
|
191
191
|
end
|
192
192
|
end
|
193
193
|
|
194
|
+
describe 'with env based config file' do
|
195
|
+
before do
|
196
|
+
@cli.parse(['sidekiq', '-e', 'staging', '-C', './test/env_based_config.yml'])
|
197
|
+
end
|
198
|
+
|
199
|
+
it 'takes a path' do
|
200
|
+
assert_equal './test/env_based_config.yml', Sidekiq.options[:config_file]
|
201
|
+
end
|
202
|
+
|
203
|
+
it 'sets verbose' do
|
204
|
+
refute Sidekiq.options[:verbose]
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'sets require file' do
|
208
|
+
assert_equal './test/fake_env.rb', Sidekiq.options[:require]
|
209
|
+
end
|
210
|
+
|
211
|
+
it 'sets environment' do
|
212
|
+
assert_equal 'staging', Sidekiq.options[:environment]
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'sets concurrency' do
|
216
|
+
assert_equal 5, Sidekiq.options[:concurrency]
|
217
|
+
end
|
218
|
+
|
219
|
+
it 'sets pid file' do
|
220
|
+
assert_equal '/tmp/sidekiq-config-test.pid', Sidekiq.options[:pidfile]
|
221
|
+
end
|
222
|
+
|
223
|
+
it 'sets logfile' do
|
224
|
+
assert_equal '/tmp/sidekiq.log', Sidekiq.options[:logfile]
|
225
|
+
end
|
226
|
+
|
227
|
+
it 'sets queues' do
|
228
|
+
assert_equal 2, Sidekiq.options[:queues].count { |q| q == 'very_often' }
|
229
|
+
assert_equal 1, Sidekiq.options[:queues].count { |q| q == 'seldom' }
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
194
233
|
describe 'with config file and flags' do
|
195
234
|
before do
|
196
235
|
# We need an actual file here.
|
@@ -5,6 +5,41 @@ class TestRedisConnection < MiniTest::Unit::TestCase
|
|
5
5
|
|
6
6
|
describe ".create" do
|
7
7
|
|
8
|
+
it "creates a pooled redis connection" do
|
9
|
+
pool = Sidekiq::RedisConnection.create
|
10
|
+
assert_equal Redis, pool.checkout.class
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "namespace" do
|
14
|
+
before do
|
15
|
+
Sidekiq.options[:namespace] = "xxx"
|
16
|
+
end
|
17
|
+
|
18
|
+
after do
|
19
|
+
Sidekiq.options[:namespace] = nil
|
20
|
+
end
|
21
|
+
|
22
|
+
it "uses a given :namespace" do
|
23
|
+
pool = Sidekiq::RedisConnection.create(:namespace => "xxx")
|
24
|
+
assert_equal "xxx", pool.checkout.namespace
|
25
|
+
end
|
26
|
+
|
27
|
+
it "uses :namespace from Sidekiq.options" do
|
28
|
+
pool = Sidekiq::RedisConnection.create
|
29
|
+
assert_equal "xxx", pool.checkout.namespace
|
30
|
+
end
|
31
|
+
|
32
|
+
it "uses given :namespace over :namespace from Sidekiq.options" do
|
33
|
+
Sidekiq.options[:namespace] = "xxx"
|
34
|
+
pool = Sidekiq::RedisConnection.create(:namespace => "yyy")
|
35
|
+
assert_equal "yyy", pool.checkout.namespace
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe ".determine_redis_provider" do
|
42
|
+
|
8
43
|
def with_env_var(var, uri, skip_provider=false)
|
9
44
|
vars = ['REDISTOGO_URL', 'REDIS_PROVIDER', 'REDIS_URL'] - [var]
|
10
45
|
vars.each do |v|
|
data/test/test_sidekiq.rb
CHANGED
@@ -11,4 +11,17 @@ class TestSidekiq < MiniTest::Unit::TestCase
|
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
+
describe "redis connection" do
|
15
|
+
it "returns error without creating a connection if block is not given" do
|
16
|
+
mock = MiniTest::Mock.new
|
17
|
+
mock.expect :create, nil #Sidekiq::RedisConnection, create
|
18
|
+
assert_raises(ArgumentError) {
|
19
|
+
Sidekiq.redis
|
20
|
+
}
|
21
|
+
assert_raises(MockExpectationError, "create should not be called") do
|
22
|
+
mock.verify
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
14
27
|
end
|
data/test/test_web.rb
CHANGED
@@ -32,7 +32,6 @@ class TestWeb < MiniTest::Unit::TestCase
|
|
32
32
|
get '/'
|
33
33
|
assert_equal 200, last_response.status
|
34
34
|
assert_match /status-idle/, last_response.body
|
35
|
-
refute_match /default/, last_response.body
|
36
35
|
end
|
37
36
|
|
38
37
|
it 'can display queues' do
|
@@ -200,17 +199,49 @@ class TestWeb < MiniTest::Unit::TestCase
|
|
200
199
|
assert_equal 200, last_response.status
|
201
200
|
end
|
202
201
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
202
|
+
describe 'stats' do
|
203
|
+
before do
|
204
|
+
Sidekiq.redis do |conn|
|
205
|
+
conn.set("stat:processed", 5)
|
206
|
+
conn.set("stat:failed", 2)
|
207
|
+
end
|
208
|
+
2.times { add_retry }
|
209
|
+
3.times { add_scheduled }
|
210
|
+
get '/dashboard/stats'
|
211
|
+
@response = Sidekiq.load_json(last_response.body)
|
207
212
|
end
|
208
|
-
2.times { add_retry }
|
209
|
-
3.times { add_scheduled }
|
210
213
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
+
it 'can refresh dashboard stats' do
|
215
|
+
assert_equal 200, last_response.status
|
216
|
+
end
|
217
|
+
|
218
|
+
describe "for sidekiq" do
|
219
|
+
it 'are namespaced' do
|
220
|
+
assert_includes @response.keys, "sidekiq"
|
221
|
+
end
|
222
|
+
|
223
|
+
it 'reports processed' do
|
224
|
+
assert_equal @response["sidekiq"]["processed"], 5
|
225
|
+
end
|
226
|
+
|
227
|
+
it 'reports failed' do
|
228
|
+
assert_equal @response["sidekiq"]["failed"], 2
|
229
|
+
end
|
230
|
+
|
231
|
+
it 'reports retries' do
|
232
|
+
assert_equal @response["sidekiq"]["retries"], 2
|
233
|
+
end
|
234
|
+
|
235
|
+
it 'reports scheduled' do
|
236
|
+
assert_equal @response["sidekiq"]["scheduled"], 3
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
describe "for redis" do
|
241
|
+
it 'are namespaced' do
|
242
|
+
assert_includes @response.keys, "redis"
|
243
|
+
end
|
244
|
+
end
|
214
245
|
end
|
215
246
|
|
216
247
|
def add_scheduled
|
@@ -16,6 +16,8 @@ var realtimeGraph = function(updatePath) {
|
|
16
16
|
width: 800,
|
17
17
|
height: 200,
|
18
18
|
renderer: 'line',
|
19
|
+
interpolation: 'linear',
|
20
|
+
|
19
21
|
series: new Rickshaw.Series.FixedDuration([{ name: 'failed', color: '#B1003E' }, { name: 'processed', color: '#006f68' }], undefined, {
|
20
22
|
timeInterval: timeInterval,
|
21
23
|
maxDataPoints: 100,
|
@@ -53,7 +55,8 @@ var realtimeGraph = function(updatePath) {
|
|
53
55
|
Sidekiq.processed = data.processed;
|
54
56
|
Sidekiq.failed = data.failed;
|
55
57
|
|
56
|
-
updateStatsSummary(data);
|
58
|
+
updateStatsSummary(data.sidekiq);
|
59
|
+
updateRedisStats(data.redis);
|
57
60
|
pulseBeacon();
|
58
61
|
});
|
59
62
|
i++;
|
@@ -69,6 +72,7 @@ var historyGraph = function() {
|
|
69
72
|
width: 800,
|
70
73
|
height: 200,
|
71
74
|
renderer: 'line',
|
75
|
+
interpolation: 'linear',
|
72
76
|
series: [
|
73
77
|
{
|
74
78
|
color: "#B1003E",
|
@@ -93,7 +97,7 @@ var historyGraph = function() {
|
|
93
97
|
|
94
98
|
var hoverDetail = new Rickshaw.Graph.HoverDetail({
|
95
99
|
graph: graph,
|
96
|
-
yFormatter: function(y) { return Math.floor(y) },
|
100
|
+
yFormatter: function(y) { return Math.floor(y).numberWithDelimiter() },
|
97
101
|
});
|
98
102
|
}
|
99
103
|
|
@@ -115,6 +119,14 @@ var updateStatsSummary = function(data) {
|
|
115
119
|
$('ul.summary li.enqueued span.count').html(data.enqueued.numberWithDelimiter())
|
116
120
|
}
|
117
121
|
|
122
|
+
var updateRedisStats = function(data) {
|
123
|
+
$('.stat h3.redis_version').html(data.redis_version)
|
124
|
+
$('.stat h3.uptime_in_days').html(data.uptime_in_days)
|
125
|
+
$('.stat h3.connected_clients').html(data.connected_clients)
|
126
|
+
$('.stat h3.used_memory_human').html(data.used_memory_human)
|
127
|
+
$('.stat h3.used_memory_peak_human').html(data.used_memory_peak_human)
|
128
|
+
}
|
129
|
+
|
118
130
|
var pulseBeacon = function(){
|
119
131
|
$beacon = $('.beacon')
|
120
132
|
$beacon.find('.dot').addClass('pulse').delay(1000).queue(function(){
|
data/web/views/_workers.slim
CHANGED
@@ -15,7 +15,7 @@ table class="workers table table-hover table-bordered table-striped table-white"
|
|
15
15
|
- if msg['payload']['args'].to_s.size > 100
|
16
16
|
= msg['payload']['args'].inspect[0..100] + "... "
|
17
17
|
button data-toggle="collapse" data-target="#worker_#{index}" class="btn btn-mini" Show All
|
18
|
-
.
|
18
|
+
.toggle[id="worker_#{index}" style="display: none;max-width: 750px;"]= msg['payload']['args']
|
19
19
|
- else
|
20
20
|
= msg['payload']['args']
|
21
21
|
td== relative_time(msg['run_at'].is_a?(Numeric) ? Time.at(msg['run_at']) : Time.parse(msg['run_at']))
|
data/web/views/dashboard.slim
CHANGED
@@ -11,6 +11,7 @@ h5 Real-time
|
|
11
11
|
|
12
12
|
h5
|
13
13
|
span.history-heading History
|
14
|
+
a href="#{{current_path}}?days=7" class="history-graph #{{"active" if params[:days] == "7"}}" 1 week
|
14
15
|
a href="#{{current_path}}" class="history-graph #{{"active" if params[:days].nil? || params[:days] == "30"}}" 1 month
|
15
16
|
a href="#{{current_path}}?days=90" class="history-graph #{{"active" if params[:days] == "90"}}" 3 month
|
16
17
|
a href="#{{current_path}}?days=180" class="history-graph #{{"active" if params[:days] == "180"}}" 6 month
|
@@ -21,25 +22,25 @@ h5 Redis
|
|
21
22
|
|
22
23
|
- if @redis_info.fetch("redis_version", nil)
|
23
24
|
.stat
|
24
|
-
h3= @redis_info.fetch("redis_version")
|
25
|
+
h3.redis_version= @redis_info.fetch("redis_version")
|
25
26
|
p Version
|
26
27
|
|
27
28
|
- if @redis_info.fetch("uptime_in_days", nil)
|
28
29
|
.stat
|
29
|
-
h3= @redis_info.fetch("uptime_in_days")
|
30
|
+
h3.uptime_in_days= @redis_info.fetch("uptime_in_days")
|
30
31
|
p Uptime (days)
|
31
32
|
|
32
33
|
- if @redis_info.fetch("connected_clients", nil)
|
33
34
|
.stat
|
34
|
-
h3= @redis_info.fetch("connected_clients")
|
35
|
+
h3.connected_clients= @redis_info.fetch("connected_clients")
|
35
36
|
p Connections
|
36
37
|
|
37
38
|
- if @redis_info.fetch("used_memory_human", nil)
|
38
39
|
.stat
|
39
|
-
h3= @redis_info.fetch("used_memory_human")
|
40
|
+
h3.used_memory_human= @redis_info.fetch("used_memory_human")
|
40
41
|
p Memory Usage
|
41
42
|
|
42
43
|
- if @redis_info.fetch("used_memory_peak_human", nil)
|
43
44
|
.stat
|
44
|
-
h3= @redis_info.fetch("used_memory_peak_human")
|
45
|
+
h3.used_memory_peak_human= @redis_info.fetch("used_memory_peak_human")
|
45
46
|
p Peak Memory Usage
|
data/web/views/layout.slim
CHANGED
data/web/views/queue.slim
CHANGED
@@ -18,7 +18,7 @@ table class="queue table table-hover table-bordered table-striped"
|
|
18
18
|
- if msg['args'] and msg['args'].to_s.size > 100
|
19
19
|
= msg['args'].inspect[0..100] + "... "
|
20
20
|
button data-toggle="collapse" data-target="#worker_#{index}" class="btn btn-mini" Show All
|
21
|
-
.
|
21
|
+
.toggle[id="worker_#{index}" style="display: none;"]= msg['args']
|
22
22
|
- else
|
23
23
|
= msg['args']
|
24
24
|
td
|
metadata
CHANGED
@@ -1,15 +1,42 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sidekiq
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.7.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Mike Perham
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
|
-
cert_chain:
|
12
|
-
|
11
|
+
cert_chain:
|
12
|
+
- !binary |-
|
13
|
+
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURNRENDQWhpZ0F3SUJB
|
14
|
+
Z0lCQURBTkJna3Foa2lHOXcwQkFRVUZBREErTVJBd0RnWURWUVFEREFkdGNH
|
15
|
+
VnkKYUdGdE1SVXdFd1lLQ1pJbWlaUHlMR1FCR1JZRloyMWhhV3d4RXpBUkJn
|
16
|
+
b0praWFKay9Jc1pBRVpGZ05qYjIwdwpIaGNOTVRNd01UTXdNVGt5T0RVM1do
|
17
|
+
Y05NVFF3TVRNd01Ua3lPRFUzV2pBK01SQXdEZ1lEVlFRRERBZHRjR1Z5CmFH
|
18
|
+
RnRNUlV3RXdZS0NaSW1pWlB5TEdRQkdSWUZaMjFoYVd3eEV6QVJCZ29Ka2lh
|
19
|
+
SmsvSXNaQUVaRmdOamIyMHcKZ2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJ
|
20
|
+
QkR3QXdnZ0VLQW9JQkFRQy9ydlV3THBPUUVzUGZpMVQvUXRSagpkYzcrMERF
|
21
|
+
OGxqSUxKcUorc1VrWjg4MVV4aXQ2TSs4WlpvcU5rd2EyZTJSQ1dSQmROeDYy
|
22
|
+
NVJRaDJiWDR1dHBZCmtsb1RXUTZQQmJyRERWSFZSQWt1d0RiYUg0d0U4cnR3
|
23
|
+
WERjS3V0bzR4YUhqTitFWVdmMnJIQk5DNCtxTVgrZXYKQ0QzTVJCRzd4T1VS
|
24
|
+
dGhEcFJUS0JYVG5EQTZxUGxGSCs0Qk9OTHlVT1BnejJqMGh6VlFiQS83OTVL
|
25
|
+
SlhwSWloOQpnb0VpYVd6dnZxczh1cHNkRkdRb1Z2YUZVS0UvWnI3OVptMGtO
|
26
|
+
QzdkRHRHMHRvSGxsMFhNRlVML0pqSlQyUmgyCmNBTER3SXh3VmRMN3I2bDJP
|
27
|
+
NHFldVhMN0hLU0M1WnlOcXgzSm9Wd3J4ZlhrMkkyRE9HQnFyR1NKSkZXVXEz
|
28
|
+
aTEKQWdNQkFBR2pPVEEzTUFrR0ExVWRFd1FDTUFBd0hRWURWUjBPQkJZRUZO
|
29
|
+
R0FuUm1yTExjNE5GZlRTTDJQanBBeApHSm5mTUFzR0ExVWREd1FFQXdJRXNE
|
30
|
+
QU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFmOXZxSzJmcm1uS2N5REU3CmR0
|
31
|
+
OWVMdGhZVXhaOEhsY3RMU1hEczR0amxFS0tmd2tEMVlhbHU0UE56aGpySHFY
|
32
|
+
YThoWVR4cUhQZldtVjc3MXEKcVQvT0xWdkw0b2ZqclhtQUcraHF3emNUN2dy
|
33
|
+
U2JZREFLMTRJVFk4TThEcEMyanZ1R1IzTW55Q2hpOWVwMHBMYQpFOUp5MzVs
|
34
|
+
eGEzVUZCanIwbmVJOVF4b3dNaWxtalVIblBEelZIYnptV0FReFBvYzE4dWlV
|
35
|
+
OVBYZDBoK0pzeDJGCnk4SXgreloxTElPV2s5TzlXbk1kTE9UalVGbkEvenV0
|
36
|
+
TTNOenY4ek5CblVKakg1L0E1aWdDSUFMKzZ2VTcrc3UKc0xGK0pDRlBiQmd2
|
37
|
+
UnFMNWhYMDNDS3V5T1VObVVWVDVBbkNEbmZJRFVWL2tKaFg3V2ZyNklxYVVI
|
38
|
+
bVVjeS9qbgpleTZobHc9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
|
39
|
+
date: 2013-02-03 00:00:00.000000000 Z
|
13
40
|
dependencies:
|
14
41
|
- !ruby/object:Gem::Dependency
|
15
42
|
name: redis
|
@@ -197,7 +224,7 @@ extensions: []
|
|
197
224
|
extra_rdoc_files: []
|
198
225
|
files:
|
199
226
|
- .gitignore
|
200
|
-
- .
|
227
|
+
- .public_cert.pem
|
201
228
|
- .travis.yml
|
202
229
|
- COMM-LICENSE
|
203
230
|
- Changes.md
|
@@ -218,9 +245,13 @@ files:
|
|
218
245
|
- examples/config.yml
|
219
246
|
- examples/monitrc.conf
|
220
247
|
- examples/por.rb
|
248
|
+
- examples/runit/README.md
|
249
|
+
- examples/runit/log/run
|
250
|
+
- examples/runit/run
|
221
251
|
- examples/scheduling.rb
|
222
252
|
- examples/sidekiq
|
223
253
|
- examples/sinkiq.rb
|
254
|
+
- examples/upstart.conf
|
224
255
|
- examples/web-ui.png
|
225
256
|
- lib/sidekiq.rb
|
226
257
|
- lib/sidekiq/api.rb
|
@@ -255,6 +286,7 @@ files:
|
|
255
286
|
- lib/sidekiq/yaml_patch.rb
|
256
287
|
- sidekiq.gemspec
|
257
288
|
- test/config.yml
|
289
|
+
- test/env_based_config.yml
|
258
290
|
- test/fake_env.rb
|
259
291
|
- test/helper.rb
|
260
292
|
- test/test_api.rb
|
@@ -317,12 +349,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
317
349
|
version: '0'
|
318
350
|
requirements: []
|
319
351
|
rubyforge_project:
|
320
|
-
rubygems_version: 1.8.
|
352
|
+
rubygems_version: 1.8.25
|
321
353
|
signing_key:
|
322
354
|
specification_version: 3
|
323
355
|
summary: Simple, efficient message processing for Ruby
|
324
356
|
test_files:
|
325
357
|
- test/config.yml
|
358
|
+
- test/env_based_config.yml
|
326
359
|
- test/fake_env.rb
|
327
360
|
- test/helper.rb
|
328
361
|
- test/test_api.rb
|
metadata.gz.sig
ADDED
Binary file
|
data/.rvmrc
DELETED