mirror of
https://github.com/mperham/sidekiq.git
synced 2022-11-09 13:52:34 -05:00
Clone arguments before calling workers to avoid mutation [#265]
This commit is contained in:
parent
c1da2f0034
commit
8357fa3e4b
3 changed files with 23 additions and 1 deletions
|
@ -3,6 +3,7 @@ HEAD
|
||||||
|
|
||||||
- Handle networking errors causing the scheduler thread to die [#309]
|
- Handle networking errors causing the scheduler thread to die [#309]
|
||||||
- Rework exception handling to log all Processor and actor death (#325, subelsky)
|
- Rework exception handling to log all Processor and actor death (#325, subelsky)
|
||||||
|
- Clone arguments when calling worker so modifications are discarded. (hakanensari)
|
||||||
|
|
||||||
2.1.0
|
2.1.0
|
||||||
-----------
|
-----------
|
||||||
|
|
|
@ -37,7 +37,7 @@ module Sidekiq
|
||||||
|
|
||||||
stats(worker, msg, queue) do
|
stats(worker, msg, queue) do
|
||||||
Sidekiq.server_middleware.invoke(worker, msg, queue) do
|
Sidekiq.server_middleware.invoke(worker, msg, queue) do
|
||||||
worker.perform(*msg['args'])
|
worker.perform(*cloned(msg['args']))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@boss.processor_done!(current_actor)
|
@boss.processor_done!(current_actor)
|
||||||
|
@ -57,6 +57,9 @@ module Sidekiq
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
# Singleton classes are not clonable.
|
||||||
|
SINGLETON_CLASSES = [ NilClass, TrueClass, FalseClass, Numeric, Symbol ].freeze
|
||||||
|
|
||||||
def stats(worker, msg, queue)
|
def stats(worker, msg, queue)
|
||||||
redis do |conn|
|
redis do |conn|
|
||||||
conn.multi do
|
conn.multi do
|
||||||
|
@ -88,7 +91,15 @@ module Sidekiq
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Clone the arguments passed to the worker so that if
|
||||||
|
# the message fails, what is pushed back onto Redis hasn't
|
||||||
|
# been mutated by the worker.
|
||||||
|
def cloned(ary)
|
||||||
|
ary.map do |val|
|
||||||
|
SINGLETON_CLASSES.include?(val.class) ? val : val.clone
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def hostname
|
def hostname
|
||||||
|
|
|
@ -18,6 +18,7 @@ class TestProcessor < MiniTest::Unit::TestCase
|
||||||
include Sidekiq::Worker
|
include Sidekiq::Worker
|
||||||
def perform(args)
|
def perform(args)
|
||||||
raise TEST_EXCEPTION if args == 'boom'
|
raise TEST_EXCEPTION if args == 'boom'
|
||||||
|
args.pop if args.is_a? Array
|
||||||
$invokes += 1
|
$invokes += 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -53,5 +54,14 @@ class TestProcessor < MiniTest::Unit::TestCase
|
||||||
|
|
||||||
assert re_raise, "does not re-raise exceptions after handling"
|
assert re_raise, "does not re-raise exceptions after handling"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'does not modify original arguments' do
|
||||||
|
msg = { 'class' => MockWorker.to_s, 'args' => [['myarg']] }
|
||||||
|
msgstr = Sidekiq.dump_json(msg)
|
||||||
|
processor = ::Sidekiq::Processor.new(@boss)
|
||||||
|
@boss.expect(:processor_done!, nil, [processor])
|
||||||
|
processor.process(msgstr, 'default')
|
||||||
|
assert_equal [['myarg']], msg['args']
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Reference in a new issue