mirror of
https://github.com/mperham/sidekiq.git
synced 2022-11-09 13:52:34 -05:00
Helper middleware to preserve implicit context? (#4982)
* Add support for round-tripping AS::CurrentAttributes * Add tests
This commit is contained in:
parent
237c70fe37
commit
9c46df0a15
2 changed files with 99 additions and 0 deletions
48
lib/sidekiq/middleware/current_attributes.rb
Normal file
48
lib/sidekiq/middleware/current_attributes.rb
Normal file
|
@ -0,0 +1,48 @@
|
|||
require "active_support/current_attributes"
|
||||
|
||||
module Sidekiq
|
||||
##
|
||||
# Automatically save and load any current attributes in the execution context
|
||||
# so context attributes "flow" from Rails actions into any associated jobs.
|
||||
# This can be useful for multi-tenancy, i18n locale, timezone, any implicit
|
||||
# per-request attribute. See +ActiveSupport::CurrentAttributes+.
|
||||
#
|
||||
# @example
|
||||
#
|
||||
# # in your initializer
|
||||
# require "sidekiq/middleware/current_attributes"
|
||||
# Sidekiq::CurrentAttributes.persist(Myapp::Current)
|
||||
#
|
||||
module CurrentAttributes
|
||||
class Save
|
||||
def initialize(with:)
|
||||
@klass = with
|
||||
end
|
||||
|
||||
def call(_, job, _, _)
|
||||
job["ctx"] = @klass.attributes
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
||||
class Load
|
||||
def initialize(with:)
|
||||
@klass = with
|
||||
end
|
||||
|
||||
def call(_, job, _, &block)
|
||||
@klass.set(job["ctx"], &block)
|
||||
end
|
||||
end
|
||||
|
||||
def self.persist(klass)
|
||||
Sidekiq.configure_client do |config|
|
||||
config.client_middleware.add Save, with: klass
|
||||
end
|
||||
Sidekiq.configure_server do |config|
|
||||
config.client_middleware.add Save, with: klass
|
||||
config.server_middleware.add Load, with: klass
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
51
test/test_current_attributes.rb
Normal file
51
test/test_current_attributes.rb
Normal file
|
@ -0,0 +1,51 @@
|
|||
require_relative "./helper"
|
||||
require "sidekiq/middleware/current_attributes"
|
||||
|
||||
module Myapp
|
||||
class Current < ActiveSupport::CurrentAttributes
|
||||
attribute :user_id
|
||||
end
|
||||
end
|
||||
|
||||
class TestCurrentAttributes < Minitest::Test
|
||||
def test_save
|
||||
cm = Sidekiq::CurrentAttributes::Save.new(with: Myapp::Current)
|
||||
job = {}
|
||||
with_context(:user_id, 123) do
|
||||
cm.call(nil, job, nil, nil) do
|
||||
assert_equal 123, job["ctx"][:user_id]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_load
|
||||
cm = Sidekiq::CurrentAttributes::Load.new(with: Myapp::Current)
|
||||
|
||||
job = { "ctx" => { "user_id" => 123 } }
|
||||
assert_nil Myapp::Current.user_id
|
||||
cm.call(nil, job, nil) do
|
||||
assert_equal 123, Myapp::Current.user_id
|
||||
end
|
||||
# the Rails reloader is responsible for reseting Current after every unit of work
|
||||
end
|
||||
|
||||
def test_persist
|
||||
begin
|
||||
Sidekiq::CurrentAttributes.persist(Myapp::Current)
|
||||
ensure
|
||||
Sidekiq.client_middleware.clear
|
||||
Sidekiq.server_middleware.clear
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def with_context(attr, value)
|
||||
begin
|
||||
Myapp::Current.send("#{attr}=", value)
|
||||
yield
|
||||
ensure
|
||||
Myapp::Current.reset_all
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue