2012-02-08 20:04:19 -05:00
|
|
|
module Sidekiq
|
|
|
|
# Middleware is code configured to run before/after
|
|
|
|
# a message is processed. It is patterned after Rack
|
|
|
|
# middleware. Middleware exists for the client side
|
2012-02-09 23:32:59 -05:00
|
|
|
# (pushing jobs onto the queue) as well as the server
|
|
|
|
# side (when jobs are actually processed).
|
2012-02-08 20:04:19 -05:00
|
|
|
#
|
2012-02-18 15:12:05 -05:00
|
|
|
# To add middleware for the client:
|
2012-02-08 20:04:19 -05:00
|
|
|
#
|
2012-07-17 14:06:10 -04:00
|
|
|
# Sidekiq.configure_client do |config|
|
|
|
|
# config.client_middleware do |chain|
|
|
|
|
# chain.add MyClientHook
|
|
|
|
# end
|
2012-02-08 20:04:19 -05:00
|
|
|
# end
|
|
|
|
#
|
2012-02-18 15:12:05 -05:00
|
|
|
# To modify middleware for the server, just call
|
|
|
|
# with another block:
|
2012-02-08 20:04:19 -05:00
|
|
|
#
|
2012-07-17 14:06:10 -04:00
|
|
|
# Sidekiq.configure_server do |config|
|
|
|
|
# config.server_middleware do |chain|
|
|
|
|
# chain.add MyServerHook
|
|
|
|
# chain.remove ActiveRecord
|
|
|
|
# end
|
2012-02-08 20:04:19 -05:00
|
|
|
# end
|
|
|
|
#
|
2012-12-19 00:42:23 -05:00
|
|
|
# To insert immediately preceding another entry:
|
|
|
|
#
|
|
|
|
# Sidekiq.configure_client do |config|
|
|
|
|
# config.client_middleware do |chain|
|
2012-12-19 11:40:36 -05:00
|
|
|
# chain.insert_before ActiveRecord, MyClientHook
|
2012-12-19 00:42:23 -05:00
|
|
|
# end
|
|
|
|
# end
|
|
|
|
#
|
|
|
|
# To insert immediately after another entry:
|
|
|
|
#
|
|
|
|
# Sidekiq.configure_client do |config|
|
|
|
|
# config.client_middleware do |chain|
|
2012-12-19 11:40:36 -05:00
|
|
|
# chain.insert_after ActiveRecord, MyClientHook
|
2012-12-19 00:42:23 -05:00
|
|
|
# end
|
|
|
|
# end
|
|
|
|
#
|
2012-02-18 16:08:53 -05:00
|
|
|
# This is an example of a minimal server middleware:
|
2012-02-08 20:04:19 -05:00
|
|
|
#
|
2012-02-18 15:12:05 -05:00
|
|
|
# class MyServerHook
|
2012-07-17 14:06:10 -04:00
|
|
|
# def call(worker_instance, msg, queue)
|
2012-02-08 20:04:19 -05:00
|
|
|
# puts "Before work"
|
|
|
|
# yield
|
|
|
|
# puts "After work"
|
|
|
|
# end
|
|
|
|
# end
|
|
|
|
#
|
2013-11-14 23:30:11 -05:00
|
|
|
# This is an example of a minimal client middleware, note
|
|
|
|
# the method must return the result or the job will not push
|
|
|
|
# to Redis:
|
2012-02-18 16:08:53 -05:00
|
|
|
#
|
|
|
|
# class MyClientHook
|
2012-07-17 14:06:10 -04:00
|
|
|
# def call(worker_class, msg, queue)
|
2012-02-18 16:08:53 -05:00
|
|
|
# puts "Before push"
|
2013-11-14 23:30:11 -05:00
|
|
|
# result = yield
|
2012-02-18 16:08:53 -05:00
|
|
|
# puts "After push"
|
2013-11-14 23:30:11 -05:00
|
|
|
# result
|
2012-02-18 16:08:53 -05:00
|
|
|
# end
|
|
|
|
# end
|
|
|
|
#
|
2012-02-08 20:04:19 -05:00
|
|
|
module Middleware
|
|
|
|
class Chain
|
2013-07-27 19:14:07 -04:00
|
|
|
include Enumerable
|
2012-02-08 20:04:19 -05:00
|
|
|
attr_reader :entries
|
|
|
|
|
2013-10-26 00:07:54 -04:00
|
|
|
def initialize_copy(copy)
|
|
|
|
copy.instance_variable_set(:@entries, entries.dup)
|
|
|
|
end
|
|
|
|
|
2013-07-27 19:14:07 -04:00
|
|
|
def each(&block)
|
|
|
|
entries.each(&block)
|
|
|
|
end
|
|
|
|
|
2012-02-08 20:04:19 -05:00
|
|
|
def initialize
|
|
|
|
@entries = []
|
2012-02-19 16:02:32 -05:00
|
|
|
yield self if block_given?
|
2012-02-08 20:04:19 -05:00
|
|
|
end
|
|
|
|
|
2012-02-18 15:12:05 -05:00
|
|
|
def remove(klass)
|
2012-02-08 20:04:19 -05:00
|
|
|
entries.delete_if { |entry| entry.klass == klass }
|
|
|
|
end
|
|
|
|
|
2012-02-18 15:12:05 -05:00
|
|
|
def add(klass, *args)
|
2013-08-01 14:54:30 -04:00
|
|
|
remove(klass) if exists?(klass)
|
|
|
|
entries << Entry.new(klass, *args)
|
2012-02-10 23:20:01 -05:00
|
|
|
end
|
|
|
|
|
2012-12-19 11:40:36 -05:00
|
|
|
def insert_before(oldklass, newklass, *args)
|
2012-12-25 02:15:23 -05:00
|
|
|
i = entries.index { |entry| entry.klass == newklass }
|
|
|
|
new_entry = i.nil? ? Entry.new(newklass, *args) : entries.delete_at(i)
|
2013-09-12 17:14:17 -04:00
|
|
|
i = entries.index { |entry| entry.klass == oldklass } || 0
|
2012-12-19 12:18:28 -05:00
|
|
|
entries.insert(i, new_entry)
|
2012-12-19 00:42:23 -05:00
|
|
|
end
|
|
|
|
|
2012-12-19 11:40:36 -05:00
|
|
|
def insert_after(oldklass, newklass, *args)
|
2012-12-25 02:15:23 -05:00
|
|
|
i = entries.index { |entry| entry.klass == newklass }
|
|
|
|
new_entry = i.nil? ? Entry.new(newklass, *args) : entries.delete_at(i)
|
2013-09-12 17:14:17 -04:00
|
|
|
i = entries.index { |entry| entry.klass == oldklass } || entries.count - 1
|
2012-12-19 12:18:28 -05:00
|
|
|
entries.insert(i+1, new_entry)
|
2012-12-19 00:42:23 -05:00
|
|
|
end
|
|
|
|
|
2012-02-10 23:20:01 -05:00
|
|
|
def exists?(klass)
|
2013-09-12 17:14:17 -04:00
|
|
|
any? { |entry| entry.klass == klass }
|
2012-02-08 20:04:19 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def retrieve
|
2013-09-12 17:14:17 -04:00
|
|
|
map(&:make_new)
|
2012-02-08 20:04:19 -05:00
|
|
|
end
|
|
|
|
|
2012-03-17 20:59:18 -04:00
|
|
|
def clear
|
|
|
|
entries.clear
|
|
|
|
end
|
|
|
|
|
2012-02-08 20:04:19 -05:00
|
|
|
def invoke(*args, &final_action)
|
|
|
|
chain = retrieve.dup
|
|
|
|
traverse_chain = lambda do
|
|
|
|
if chain.empty?
|
|
|
|
final_action.call
|
|
|
|
else
|
|
|
|
chain.shift.call(*args, &traverse_chain)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
traverse_chain.call
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class Entry
|
|
|
|
attr_reader :klass
|
2013-08-01 14:54:30 -04:00
|
|
|
|
2012-02-08 20:04:19 -05:00
|
|
|
def initialize(klass, *args)
|
|
|
|
@klass = klass
|
|
|
|
@args = args
|
|
|
|
end
|
|
|
|
|
|
|
|
def make_new
|
|
|
|
@klass.new(*@args)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|