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.

Binary file
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
+ .rvmrc
1
2
  tags
2
3
  Gemfile.lock
3
4
  *.swp
@@ -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
@@ -12,4 +12,5 @@ end
12
12
  group :development do
13
13
  gem 'pry', :platform => :mri
14
14
  gem 'shotgun'
15
+ gem 'rack', '~> 1.4.0'
15
16
  end
@@ -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
@@ -0,0 +1,2 @@
1
+ #!/bin/sh
2
+ exec svlogd -tt /var/log/sidekiq
@@ -0,0 +1,4 @@
1
+ #!/bin/sh
2
+ cd /path/to/sidekiq
3
+ exec 2>&1
4
+ exec chpst -usidekiq bundle exec sidekiq -e production -P /var/run/sidekiq/sidekiq.pid
@@ -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
@@ -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
@@ -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
@@ -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
- after "deploy:restart", "sidekiq:restart"
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} ; nohup #{fetch(:sidekiq_cmd)} -e #{rails_env} -C #{current_path}/config/sidekiq.yml -i #{idx} -P #{pid_file} >> #{current_path}/log/sidekiq.log 2>&1 &", :pty => false
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
 
@@ -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
- cli = parse_options(args)
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
- logger.info 'Starting processing, hit Ctrl-C to stop'
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 options
118
- Sidekiq.options
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 detected_environment
122
- options[:environment] ||= ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
183
+ def options
184
+ Sidekiq.options
123
185
  end
124
186
 
125
187
  def boot_system
126
- ENV['RACK_ENV'] = ENV['RAILS_ENV'] = detected_environment
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 "-q", "--queue QUEUE[,WEIGHT]...", "Queues to process with optional weights" do |arg|
171
- queues_and_weights = arg.scan(/([\w\.-]+),?(\d*)/)
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 "-v", "--verbose", "Print more verbose output" do |arg|
176
- opts[:verbose] = arg
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 '-c', '--concurrency INT', "processor threads to use" do |arg|
200
- opts[:concurrency] = Integer(arg)
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 '-P', '--pidfile PATH', "path to pidfile" do |arg|
204
- opts[:pidfile] = arg
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(cli)
314
+ def parse_config(cfile)
246
315
  opts = {}
247
- if cli[:config_file] && File.exist?(cli[:config_file])
248
- opts = YAML.load(ERB.new(IO.read(cli[:config_file])).result)
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, options[:namespace], driver)
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.wrap(payload).each do |hash|
32
+ Array(payload).each do |hash|
33
33
  normed['class'].constantize.new.perform(*Sidekiq.load_json(hash)['args'])
34
34
  end
35
35
 
@@ -1,3 +1,3 @@
1
1
  module Sidekiq
2
- VERSION = "2.6.5"
2
+ VERSION = "2.7.0"
3
3
  end
@@ -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
- stats = Sidekiq::Stats.new
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
- processed: stats.processed,
211
- failed: stats.failed,
212
- enqueued: stats.enqueued,
213
- scheduled: stats.scheduled_size,
214
- retries: stats.retry_size,
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
 
@@ -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'
@@ -0,0 +1,11 @@
1
+ ---
2
+ :pidfile: /tmp/sidekiq-config-test.pid
3
+ :concurrency: 50
4
+ staging:
5
+ :verbose: false
6
+ :require: ./test/fake_env.rb
7
+ :logfile: /tmp/sidekiq.log
8
+ :concurrency: 5
9
+ :queues:
10
+ - [<%="very_"%>often, 2]
11
+ - [seldom, 1]
@@ -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|
@@ -112,7 +112,7 @@ class TestCli < MiniTest::Unit::TestCase
112
112
 
113
113
  Sidekiq.logger.info('test message')
114
114
 
115
- assert_match /test message/, File.read(@tmp_log_path), "didn't include the log message"
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 /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"
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|
@@ -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
@@ -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
- it 'can refresh dashboard stats' do
204
- Sidekiq.redis do |conn|
205
- conn.set("stat:processed", 5)
206
- conn.set("stat:failed", 2)
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
- get '/dashboard/stats'
212
- assert_equal 200, last_response.status
213
- assert_equal "{\"processed\":5,\"failed\":2,\"enqueued\":0,\"scheduled\":3,\"retries\":2}", last_response.body
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
@@ -37,4 +37,8 @@ $(function() {
37
37
  $(document).on("click", "[data-confirm]", function() {
38
38
  return confirm($(this).attr('data-confirm'));
39
39
  });
40
+
41
+ $(document).on("click", "[data-toggle]", function() {
42
+ $($(this).attr('data-target')).toggle();
43
+ });
40
44
  });
@@ -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(){
@@ -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
- .collapse[id="worker_#{index}" style="max-width: 750px;"]= msg['payload']['args']
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']))
@@ -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
@@ -24,6 +24,9 @@ html
24
24
  p.navbar-text Redis: #{location}
25
25
  li
26
26
  p.navbar-text Time: #{Time.now.utc.strftime('%H:%M:%S UTC')}
27
+ - if namespace
28
+ li
29
+ p.navbar-text Namespace: #{namespace}
27
30
 
28
31
  #page
29
32
  .container
@@ -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
- .collapse[id="worker_#{index}"]= msg['args']
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.6.5
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
- date: 2013-01-18 00:00:00.000000000 Z
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
- - .rvmrc
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.24
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
Binary file
data/.rvmrc DELETED
@@ -1,3 +0,0 @@
1
- export RUBYOPT="-Ilib:test"
2
- rvm use 1.9.3-p327@sidekiq --create
3
- #rvm use jruby@sidekiq --create