sidekiq 1.1.2 → 1.1.3

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/Changes.md CHANGED
@@ -1,3 +1,12 @@
1
+ 1.1.3
2
+ -----------
3
+
4
+ - Better network error handling when fetching jobs from Redis.
5
+ Sidekiq will retry once per second until it can re-establish
6
+ a connection. (ryanlecompte)
7
+ - capistrano recipe now uses `bundle_cmd` if set [#147]
8
+ - handle multi\_json API changes (sferik)
9
+
1
10
  1.1.2
2
11
  -----------
3
12
 
@@ -82,4 +82,22 @@ module Sidekiq
82
82
  @server_chain
83
83
  end
84
84
 
85
+ def self.load_json(string)
86
+ # Can't reliably detect whether MultiJson responds to load, since it's
87
+ # a reserved word. Use adapter as a proxy for new features.
88
+ if MultiJson.respond_to?(:adapter)
89
+ MultiJson.load(string)
90
+ else
91
+ MultiJson.decode(string)
92
+ end
93
+ end
94
+
95
+ def self.dump_json(object)
96
+ if MultiJson.respond_to?(:dump)
97
+ MultiJson.dump(object)
98
+ else
99
+ MultiJson.encode(object)
100
+ end
101
+ end
102
+
85
103
  end
@@ -11,18 +11,18 @@ Capistrano::Configuration.instance.load do
11
11
 
12
12
  desc "Quiet sidekiq (stop accepting new work)"
13
13
  task :quiet, :roles => lambda { fetch(:sidekiq_role) } do
14
- run "cd #{current_path} && if [ -f #{current_path}/tmp/pids/sidekiq.pid ]; then bundle exec sidekiqctl quiet #{current_path}/tmp/pids/sidekiq.pid ; fi"
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
15
  end
16
16
 
17
17
  desc "Stop sidekiq"
18
18
  task :stop, :roles => lambda { fetch(:sidekiq_role) } do
19
- run "cd #{current_path} && if [ -f #{current_path}/tmp/pids/sidekiq.pid ]; then bundle exec sidekiqctl stop #{current_path}/tmp/pids/sidekiq.pid #{fetch :sidekiq_timeout} ; fi"
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
20
  end
21
21
 
22
22
  desc "Start sidekiq"
23
23
  task :start, :roles => lambda { fetch(:sidekiq_role) } do
24
24
  rails_env = fetch(:rails_env, "production")
25
- run "cd #{current_path} ; nohup 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
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
26
  end
27
27
 
28
28
  desc "Restart sidekiq"
@@ -19,26 +19,33 @@ module Sidekiq
19
19
  Sidekiq.redis { |x| x.smembers('queues') }
20
20
  end
21
21
 
22
- # DEPRECATED
23
- def self.queue_mappings
24
- @queue_mappings ||= {}
25
- end
26
-
27
- # Example usage:
28
- # Sidekiq::Client.push('queue' => 'my_queue', 'class' => MyWorker, 'args' => ['foo', 1, :bat => 'bar'])
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
+ #
30
+ # All options must be strings, not symbols. NB: because we are serializing to JSON, all
31
+ # symbols in 'args' will be converted to strings.
32
+ #
33
+ # Example:
34
+ # Sidekiq::Client.push('queue' => 'my_queue', 'class' => MyWorker, 'args' => ['foo', 1, :bat => 'bar'])
35
+ #
29
36
  def self.push(item)
30
37
  raise(ArgumentError, "Message must be a Hash of the form: { 'class' => SomeWorker, 'args' => ['bob', 1, :foo => 'bar'] }") unless item.is_a?(Hash)
31
38
  raise(ArgumentError, "Message must include a class and set of arguments: #{item.inspect}") if !item['class'] || !item['args']
32
39
  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')
33
40
 
34
41
  item['retry'] = !!item['class'].get_sidekiq_options['retry']
35
- queue = item['queue'] || item['class'].get_sidekiq_options['queue'] || queue_mappings[item['class'].to_s] || 'default'
42
+ queue = item['queue'] || item['class'].get_sidekiq_options['queue'] || 'default'
36
43
  worker_class = item['class']
37
44
  item['class'] = item['class'].to_s
38
45
 
39
46
  pushed = false
40
47
  Sidekiq.client_middleware.invoke(worker_class, item, queue) do
41
- payload = MultiJson.encode(item)
48
+ payload = Sidekiq.dump_json(item)
42
49
  Sidekiq.redis do |conn|
43
50
  _, pushed = conn.multi do
44
51
  conn.sadd('queues', queue)
@@ -10,7 +10,6 @@ module Sidekiq
10
10
  include Celluloid
11
11
  include Sidekiq::Util
12
12
 
13
- # Timeout for Redis#blpop.
14
13
  TIMEOUT = 1
15
14
 
16
15
  def initialize(mgr, queues)
@@ -29,13 +28,20 @@ module Sidekiq
29
28
  # a new fetch if the current fetch turned up nothing.
30
29
  def fetch
31
30
  watchdog('Fetcher#fetch died') do
32
- queue = nil
33
- msg = nil
34
- Sidekiq.redis { |conn| queue, msg = conn.blpop(*queues_cmd) }
31
+ begin
32
+ queue = nil
33
+ msg = nil
34
+ Sidekiq.redis { |conn| queue, msg = conn.blpop(*queues_cmd) }
35
35
 
36
- if msg
37
- @mgr.assign!(msg, queue.gsub(/.*queue:/, ''))
38
- else
36
+ if msg
37
+ @mgr.assign!(msg, queue.gsub(/.*queue:/, ''))
38
+ else
39
+ after(0) { fetch }
40
+ end
41
+ rescue => ex
42
+ logger.error("Error fetching message: #{ex}")
43
+ logger.error(ex.backtrace.first)
44
+ sleep(TIMEOUT)
39
45
  after(0) { fetch }
40
46
  end
41
47
  end
@@ -19,7 +19,7 @@ module Sidekiq
19
19
  trap_exit :processor_died
20
20
 
21
21
  def initialize(options={})
22
- logger.info "Booting sidekiq #{Sidekiq::VERSION} with Redis at #{redis {|x| x.client.location}}"
22
+ logger.info "Booting sidekiq #{Sidekiq::VERSION} with Redis at #{redis {|x| x.client.id}}"
23
23
  logger.info "Running in #{RUBY_DESCRIPTION}"
24
24
  logger.debug { options.inspect }
25
25
  @count = options[:concurrency] || 25
@@ -110,7 +110,7 @@ module Sidekiq
110
110
  processor = @ready.pop
111
111
  @in_progress[processor.object_id] = [msg, queue]
112
112
  @busy << processor
113
- processor.process!(MultiJson.decode(msg), queue)
113
+ processor.process!(Sidekiq.load_json(msg), queue)
114
114
  end
115
115
  end
116
116
  end
@@ -1,5 +1,5 @@
1
- require 'multi_json'
2
1
  require 'digest'
2
+ require 'multi_json'
3
3
 
4
4
  module Sidekiq
5
5
  module Middleware
@@ -10,7 +10,7 @@ module Sidekiq
10
10
  def call(worker_class, item, queue)
11
11
  enabled = worker_class.get_sidekiq_options['unique']
12
12
  if enabled
13
- payload_hash = Digest::MD5.hexdigest(MultiJson.encode(item))
13
+ payload_hash = Digest::MD5.hexdigest(Sidekiq.dump_json(item))
14
14
  unique = false
15
15
 
16
16
  Sidekiq.redis do |conn|
@@ -1,3 +1,5 @@
1
+ require 'multi_json'
2
+
1
3
  module Sidekiq
2
4
  module Middleware
3
5
  module Server
@@ -14,8 +16,7 @@ module Sidekiq
14
16
  :worker => args[1]['class'],
15
17
  :queue => args[2]
16
18
  }
17
-
18
- Sidekiq.redis {|conn| conn.rpush(:failed, MultiJson.encode(data)) }
19
+ Sidekiq.redis {|conn| conn.rpush(:failed, Sidekiq.dump_json(data)) }
19
20
  raise
20
21
  end
21
22
  end
@@ -1,3 +1,5 @@
1
+ require 'multi_json'
2
+
1
3
  require 'sidekiq/retry'
2
4
 
3
5
  module Sidekiq
@@ -44,7 +46,7 @@ module Sidekiq
44
46
  delay = DELAY.call(count)
45
47
  logger.debug { "Failure! Retry #{count} in #{delay} seconds" }
46
48
  retry_at = Time.now.to_f + delay
47
- payload = MultiJson.encode(msg)
49
+ payload = Sidekiq.dump_json(msg)
48
50
  Sidekiq.redis do |conn|
49
51
  conn.zadd('retry', retry_at.to_s, payload)
50
52
  end
@@ -1,3 +1,5 @@
1
+ require 'multi_json'
2
+
1
3
  module Sidekiq
2
4
  module Middleware
3
5
  module Server
@@ -5,7 +7,7 @@ module Sidekiq
5
7
  def call(*args)
6
8
  yield
7
9
  ensure
8
- json = MultiJson.encode(args[1])
10
+ json = Sidekiq.dump_json(args[1])
9
11
  hash = Digest::MD5.hexdigest(json)
10
12
  Sidekiq.redis {|conn| conn.del(hash) }
11
13
  end
@@ -1,4 +1,5 @@
1
1
  require 'celluloid'
2
+ require 'multi_json'
2
3
  require 'sidekiq/util'
3
4
 
4
5
  require 'sidekiq/middleware/server/active_record'
@@ -53,8 +54,8 @@ module Sidekiq
53
54
  redis do |conn|
54
55
  conn.multi do
55
56
  conn.set("worker:#{self}:started", Time.now.to_s)
56
- conn.set("worker:#{self}", MultiJson.encode(:queue => queue, :payload => msg,
57
- :run_at => Time.now.strftime("%Y/%m/%d %H:%M:%S %Z")))
57
+ hash = {:queue => queue, :payload => msg, :run_at => Time.now.strftime("%Y/%m/%d %H:%M:%S %Z")}
58
+ conn.set("worker:#{self}", Sidekiq.dump_json(hash))
58
59
  end
59
60
  end
60
61
 
@@ -46,7 +46,7 @@ module Sidekiq
46
46
 
47
47
  messages.each do |message|
48
48
  logger.debug { "Retrying #{message}" }
49
- msg = MultiJson.decode(message)
49
+ msg = Sidekiq.load_json(message)
50
50
  conn.rpush("queue:#{msg['queue']}", message)
51
51
  end
52
52
  end
@@ -1,3 +1,3 @@
1
1
  module Sidekiq
2
- VERSION = "1.1.2"
2
+ VERSION = "1.1.3"
3
3
  end
@@ -52,7 +52,7 @@ module Sidekiq
52
52
  Sidekiq.redis do |conn|
53
53
  conn.smembers('workers').map do |w|
54
54
  msg = conn.get("worker:#{w}")
55
- msg = MultiJson.decode(msg) if msg
55
+ msg = Sidekiq.load_json(msg) if msg
56
56
  [w, msg]
57
57
  end.sort { |x| x[1] ? -1 : 1 }
58
58
  end
@@ -74,7 +74,7 @@ module Sidekiq
74
74
  def retries
75
75
  Sidekiq.redis do |conn|
76
76
  results = conn.zrange('retry', 0, 25, :withscores => true)
77
- results.each_slice(2).map { |msg, score| [MultiJson.decode(msg), Float(score)] }
77
+ results.each_slice(2).map { |msg, score| [Sidekiq.load_json(msg), Float(score)] }
78
78
  end
79
79
  end
80
80
 
@@ -89,7 +89,7 @@ module Sidekiq
89
89
  def retries_with_score(score)
90
90
  Sidekiq.redis do |conn|
91
91
  results = conn.zrangebyscore('retry', score, score)
92
- results.map { |msg| MultiJson.decode(msg) }
92
+ results.map { |msg| Sidekiq.load_json(msg) }
93
93
  end
94
94
  end
95
95
 
@@ -124,7 +124,7 @@ module Sidekiq
124
124
  get "/queues/:name" do
125
125
  halt 404 unless params[:name]
126
126
  @name = params[:name]
127
- @messages = Sidekiq.redis {|conn| conn.lrange("queue:#{@name}", 0, 10) }.map { |str| MultiJson.decode(str) }
127
+ @messages = Sidekiq.redis {|conn| conn.lrange("queue:#{@name}", 0, 10) }.map { |str| Sidekiq.load_json(str) }
128
128
  slim :queue
129
129
  end
130
130
 
@@ -142,7 +142,7 @@ module Sidekiq
142
142
  results = conn.zrangebyscore('retry', score, score)
143
143
  conn.zremrangebyscore('retry', score, score)
144
144
  results.map do |message|
145
- msg = MultiJson.decode(message)
145
+ msg = Sidekiq.load_json(message)
146
146
  conn.rpush("queue:#{msg['queue']}", message)
147
147
  end
148
148
  end
@@ -29,11 +29,6 @@ module Sidekiq
29
29
  Sidekiq::Client.push('class' => self, 'args' => args)
30
30
  end
31
31
 
32
- def queue(name)
33
- puts "DEPRECATED: `queue :name` is now `sidekiq_options :queue => :name`"
34
- Sidekiq::Client.queue_mappings[self.name] = name.to_s
35
- end
36
-
37
32
  ##
38
33
  # Allows customization for this type of Worker.
39
34
  # Legal options:
@@ -46,7 +41,7 @@ module Sidekiq
46
41
  end
47
42
 
48
43
  def get_sidekiq_options # :nodoc:
49
- @sidekiq_options || { 'unique' => true, 'retry' => true, 'queue' => 'default' }
44
+ defined?(@sidekiq_options) ? @sidekiq_options : { 'unique' => true, 'retry' => true, 'queue' => 'default' }
50
45
  end
51
46
 
52
47
  def stringify_keys(hash) # :nodoc:
@@ -17,7 +17,7 @@ Gem::Specification.new do |gem|
17
17
  gem.add_dependency 'redis-namespace'
18
18
  gem.add_dependency 'connection_pool', '~> 0.9.0'
19
19
  gem.add_dependency 'celluloid', '~> 0.10.0'
20
- gem.add_dependency 'multi_json', '~> 1'
20
+ gem.add_dependency 'multi_json', '~> 1.0'
21
21
  gem.add_development_dependency 'minitest'
22
22
  gem.add_development_dependency 'sinatra'
23
23
  gem.add_development_dependency 'slim'
@@ -1,4 +1,5 @@
1
1
  require 'helper'
2
+ require 'multi_json'
2
3
  require 'sidekiq/retry'
3
4
  require 'sidekiq/middleware/server/retry_jobs'
4
5
 
@@ -81,7 +82,7 @@ class TestRetry < MiniTest::Unit::TestCase
81
82
  end
82
83
 
83
84
  it 'should poll like a bad mother...SHUT YO MOUTH' do
84
- fake_msg = MultiJson.encode({ 'class' => 'Bob', 'args' => [1,2], 'queue' => 'someq' })
85
+ fake_msg = Sidekiq.dump_json({ 'class' => 'Bob', 'args' => [1,2], 'queue' => 'someq' })
85
86
  @redis.expect :multi, [[fake_msg], 1], []
86
87
  @redis.expect :rpush, 1, ['queue:someq', fake_msg]
87
88
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sidekiq
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.1.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-18 00:00:00.000000000 Z
12
+ date: 2012-04-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: redis
16
- requirement: &70246171142400 !ruby/object:Gem::Requirement
16
+ requirement: &70116788678440 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70246171142400
24
+ version_requirements: *70116788678440
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: redis-namespace
27
- requirement: &70246171141920 !ruby/object:Gem::Requirement
27
+ requirement: &70116788677560 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70246171141920
35
+ version_requirements: *70116788677560
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: connection_pool
38
- requirement: &70246171141340 !ruby/object:Gem::Requirement
38
+ requirement: &70116788676520 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 0.9.0
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70246171141340
46
+ version_requirements: *70116788676520
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: celluloid
49
- requirement: &70246171140740 !ruby/object:Gem::Requirement
49
+ requirement: &70116788675940 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,21 +54,21 @@ dependencies:
54
54
  version: 0.10.0
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70246171140740
57
+ version_requirements: *70116788675940
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: multi_json
60
- requirement: &70246171140040 !ruby/object:Gem::Requirement
60
+ requirement: &70116788675040 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
64
64
  - !ruby/object:Gem::Version
65
- version: '1'
65
+ version: '1.0'
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *70246171140040
68
+ version_requirements: *70116788675040
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: minitest
71
- requirement: &70246171138540 !ruby/object:Gem::Requirement
71
+ requirement: &70116788674260 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70246171138540
79
+ version_requirements: *70116788674260
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: sinatra
82
- requirement: &70246171138080 !ruby/object:Gem::Requirement
82
+ requirement: &70116788673760 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: '0'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *70246171138080
90
+ version_requirements: *70116788673760
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: slim
93
- requirement: &70246171137580 !ruby/object:Gem::Requirement
93
+ requirement: &70116788689600 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ! '>='
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: '0'
99
99
  type: :development
100
100
  prerelease: false
101
- version_requirements: *70246171137580
101
+ version_requirements: *70116788689600
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: rake
104
- requirement: &70246171136620 !ruby/object:Gem::Requirement
104
+ requirement: &70116788689140 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ! '>='
@@ -109,10 +109,10 @@ dependencies:
109
109
  version: '0'
110
110
  type: :development
111
111
  prerelease: false
112
- version_requirements: *70246171136620
112
+ version_requirements: *70116788689140
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: actionmailer
115
- requirement: &70246171135460 !ruby/object:Gem::Requirement
115
+ requirement: &70116788688560 !ruby/object:Gem::Requirement
116
116
  none: false
117
117
  requirements:
118
118
  - - ~>
@@ -120,10 +120,10 @@ dependencies:
120
120
  version: '3'
121
121
  type: :development
122
122
  prerelease: false
123
- version_requirements: *70246171135460
123
+ version_requirements: *70116788688560
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: activerecord
126
- requirement: &70246171134380 !ruby/object:Gem::Requirement
126
+ requirement: &70116788688060 !ruby/object:Gem::Requirement
127
127
  none: false
128
128
  requirements:
129
129
  - - ~>
@@ -131,7 +131,7 @@ dependencies:
131
131
  version: '3'
132
132
  type: :development
133
133
  prerelease: false
134
- version_requirements: *70246171134380
134
+ version_requirements: *70116788688060
135
135
  description: Simple, efficient message processing for Ruby
136
136
  email:
137
137
  - mperham@gmail.com
@@ -194,7 +194,6 @@ files:
194
194
  - myapp/.gitignore
195
195
  - myapp/Capfile
196
196
  - myapp/Gemfile
197
- - myapp/Gemfile.lock
198
197
  - myapp/Rakefile
199
198
  - myapp/app/controllers/application_controller.rb
200
199
  - myapp/app/controllers/work_controller.rb
@@ -308,4 +307,3 @@ test_files:
308
307
  - test/test_stats.rb
309
308
  - test/test_testing.rb
310
309
  - test/test_web.rb
311
- has_rdoc: