sidekiq_current_model_middleware 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/sidekiq_current_model_middleware.rb +188 -0
- metadata +162 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 21bd7e76952cdd1ae2dbc3fceb860acd135affef33a8eab7ef4d3671fba60eae
|
4
|
+
data.tar.gz: 28d837555a7ddedd10ce018caf93067e7aa9938524f7d7534aca4119b527b99f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2504b2be2e663161fdc48326a92b275ea1315866345f1e239450a3d214065d1157906efad362e9e96197c6874eb520b20667a0b689008ca0ca8dc97226cd2bdc
|
7
|
+
data.tar.gz: 5d23431c6469736a28387dbac509efad43c861ce2a5c97fb1890c87fb05f47a8b49852b3207bb9e9abf7f50f448b47072b436b918287d00315896250dc430df9
|
@@ -0,0 +1,188 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# SidekiqCurrentModelMiddleware
|
4
|
+
#
|
5
|
+
# This gem provides middleware for Sidekiq to persist ActiveSupport::CurrentAttributes
|
6
|
+
# across job boundaries, including support for ActiveRecord models.
|
7
|
+
#
|
8
|
+
# It extends the functionality of Sidekiq's built-in CurrentAttributes middleware
|
9
|
+
# by adding serialization and deserialization of ActiveRecord models using GlobalID.
|
10
|
+
#
|
11
|
+
# Key features:
|
12
|
+
# - Persists CurrentAttributes from Rails actions into associated Sidekiq jobs
|
13
|
+
# - Supports multiple CurrentAttributes classes
|
14
|
+
# - Handles serialization of ActiveRecord models using GlobalID
|
15
|
+
# - Provides both client-side and server-side middleware
|
16
|
+
#
|
17
|
+
# Usage:
|
18
|
+
# SidekiqCurrentModelMiddleware.persist("MyApp::Current")
|
19
|
+
# # or for multiple current attributes:
|
20
|
+
# SidekiqCurrentModelMiddleware.persist(["MyApp::Current", "MyApp::OtherCurrent"])
|
21
|
+
#
|
22
|
+
# This file was modified from https://github.com/sidekiq/sidekiq/blob/main/lib/sidekiq/middleware/current_attributes.rb
|
23
|
+
# It extends the original implementation to handle serialization and deserialization of ActiveRecord models.
|
24
|
+
|
25
|
+
require 'active_support/current_attributes'
|
26
|
+
require 'active_record'
|
27
|
+
require 'global_id'
|
28
|
+
require 'sidekiq/client'
|
29
|
+
require 'sidekiq'
|
30
|
+
|
31
|
+
##
|
32
|
+
# Automatically save and load any current attributes in the execution context
|
33
|
+
# so context attributes "flow" from Rails actions into any associated jobs.
|
34
|
+
# This can be useful for multi-tenancy, i18n locale, timezone, any implicit
|
35
|
+
# per-request attribute. See +ActiveSupport::CurrentAttributes+.
|
36
|
+
#
|
37
|
+
# For multiple current attributes, pass an array of current attributes.
|
38
|
+
#
|
39
|
+
# @example
|
40
|
+
#
|
41
|
+
# # in your initializer
|
42
|
+
# require "sidekiq_current_model_middleware"
|
43
|
+
# SidekiqCurrentModelMiddleware.persist("Myapp::Current")
|
44
|
+
# # or multiple current attributes
|
45
|
+
# SidekiqCurrentModelMiddleware.persist(["Myapp::Current", "Myapp::OtherCurrent"])
|
46
|
+
#
|
47
|
+
# SidekiqCurrentModelMiddleware module
|
48
|
+
#
|
49
|
+
# This module provides middleware for Sidekiq to persist ActiveSupport::CurrentAttributes
|
50
|
+
# across job boundaries, including support for ActiveRecord models.
|
51
|
+
#
|
52
|
+
# It extends the functionality of Sidekiq's built-in CurrentAttributes middleware
|
53
|
+
# by adding serialization and deserialization of ActiveRecord models using GlobalID.
|
54
|
+
module SidekiqCurrentModelMiddleware
|
55
|
+
# Save class
|
56
|
+
#
|
57
|
+
# Client middleware that saves CurrentAttributes to the Sidekiq job payload.
|
58
|
+
# It handles serialization of ActiveRecord models using GlobalID.
|
59
|
+
class Save
|
60
|
+
include Sidekiq::ClientMiddleware
|
61
|
+
|
62
|
+
# Initialize the Save middleware
|
63
|
+
#
|
64
|
+
# @param cattrs [Hash] A hash of CurrentAttributes classes to persist
|
65
|
+
def initialize(cattrs)
|
66
|
+
@cattrs = cattrs
|
67
|
+
end
|
68
|
+
|
69
|
+
def call(_, job, _, _)
|
70
|
+
@cattrs.each do |(key, strklass)|
|
71
|
+
next if job.key?(key)
|
72
|
+
|
73
|
+
# Add the global id if the attribute is an ActiveRecord model
|
74
|
+
attrs = strklass.constantize.attributes.transform_values do |attr|
|
75
|
+
attr.class <= ActiveRecord::Base ? attr.to_global_id : attr
|
76
|
+
end
|
77
|
+
# Retries can push the job N times, we don't
|
78
|
+
# want retries to reset cattr. #5692, #5090 (from orig Sidekiq repo)
|
79
|
+
job[key] = attrs if attrs.any?
|
80
|
+
end
|
81
|
+
yield
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Load class
|
86
|
+
#
|
87
|
+
# Server middleware that loads CurrentAttributes from the Sidekiq job payload.
|
88
|
+
# It handles deserialization of ActiveRecord models using GlobalID.
|
89
|
+
class Load
|
90
|
+
include Sidekiq::ServerMiddleware
|
91
|
+
|
92
|
+
# Initialize the Load middleware
|
93
|
+
#
|
94
|
+
# @param cattrs [Hash] A hash of CurrentAttributes classes to load
|
95
|
+
def initialize(cattrs)
|
96
|
+
@cattrs = cattrs
|
97
|
+
end
|
98
|
+
|
99
|
+
def call(_, job, _, &block)
|
100
|
+
klass_attrs = {}
|
101
|
+
|
102
|
+
@cattrs.each do |(key, strklass)|
|
103
|
+
next unless job.key?(key)
|
104
|
+
|
105
|
+
klass_attrs[strklass.constantize] = job[key]
|
106
|
+
end
|
107
|
+
|
108
|
+
wrap(klass_attrs.to_a, &block)
|
109
|
+
end
|
110
|
+
|
111
|
+
private
|
112
|
+
|
113
|
+
def wrap(klass_attrs, &block)
|
114
|
+
klass, attrs = klass_attrs.shift
|
115
|
+
return block.call unless klass
|
116
|
+
|
117
|
+
retried = false
|
118
|
+
|
119
|
+
begin
|
120
|
+
klass.set(current_attributes(attrs)) do
|
121
|
+
wrap(klass_attrs, &block)
|
122
|
+
end
|
123
|
+
rescue NoMethodError
|
124
|
+
raise if retried
|
125
|
+
|
126
|
+
# It is possible that the `CurrentAttributes` definition
|
127
|
+
# was changed before the job started processing.
|
128
|
+
attrs = attrs.select { |attr| klass.respond_to?(attr) }
|
129
|
+
retried = true
|
130
|
+
retry
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def current_attributes(attrs)
|
135
|
+
attrs.transform_values do |attr|
|
136
|
+
GlobalID::Locator.locate(attr) || attr
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
class << self
|
142
|
+
# Persist CurrentAttributes across Sidekiq job boundaries
|
143
|
+
#
|
144
|
+
# @param klass_or_array [String, Array<String>] The CurrentAttributes class(es) to persist
|
145
|
+
# @param config [Sidekiq::Config] The Sidekiq configuration to use (default: Sidekiq.default_configuration)
|
146
|
+
#
|
147
|
+
# @example
|
148
|
+
# SidekiqCurrentModelMiddleware.persist("MyApp::Current")
|
149
|
+
# # or for multiple current attributes:
|
150
|
+
# SidekiqCurrentModelMiddleware.persist(["MyApp::Current", "MyApp::OtherCurrent"])
|
151
|
+
def persist(klass_or_array)
|
152
|
+
cattrs = build_cattrs_hash(klass_or_array)
|
153
|
+
|
154
|
+
Sidekiq.configure_server do |config|
|
155
|
+
config.server_middleware do |chain|
|
156
|
+
chain.add Sidekiq::Middleware::MultiTenant::Server
|
157
|
+
end
|
158
|
+
config.client_middleware do |chain|
|
159
|
+
chain.add Sidekiq::Middleware::MultiTenant::Client
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
Sidekiq.configure_client do |config|
|
164
|
+
config.client_middleware do |chain|
|
165
|
+
chain.add Sidekiq::Middleware::MultiTenant::Client
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
private
|
171
|
+
|
172
|
+
def build_cattrs_hash(klass_or_array)
|
173
|
+
if klass_or_array.is_a?(Array)
|
174
|
+
{}.tap do |hash|
|
175
|
+
klass_or_array.each_with_index do |klass, index|
|
176
|
+
hash[key_at(index)] = klass.to_s
|
177
|
+
end
|
178
|
+
end
|
179
|
+
else
|
180
|
+
{ key_at(0) => klass_or_array.to_s }
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def key_at(index)
|
185
|
+
index.zero? ? 'cattr' : "cattr_#{index}"
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
metadata
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sidekiq_current_model_middleware
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Zavier Miller
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-08-01 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '7'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sidekiq
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '6.3'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '6.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: codecov
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pg
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '3.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec-rails
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rubocop
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
description: This gem provides Sidekiq middleware that extends the functionality of
|
126
|
+
Sidekiq's built-in CurrentAttributes to persist and restore ActiveSupport::CurrentAttributes
|
127
|
+
across Sidekiq jobs, with added support for ActiveRecord models. It uses GlobalID
|
128
|
+
for serialization and deserialization of ActiveRecord objects, allowing seamless
|
129
|
+
integration with Rails applications to maintain context between web requests and
|
130
|
+
background jobs. The middleware supports multiple CurrentAttributes classes and
|
131
|
+
handles both client-side and server-side persistence.
|
132
|
+
email: zavierjmiller@gmail.com
|
133
|
+
executables: []
|
134
|
+
extensions: []
|
135
|
+
extra_rdoc_files: []
|
136
|
+
files:
|
137
|
+
- lib/sidekiq_current_model_middleware.rb
|
138
|
+
homepage: https://rubygems.org/gems/sidekiq_current_model_middleware
|
139
|
+
licenses:
|
140
|
+
- LGPLv3
|
141
|
+
metadata: {}
|
142
|
+
post_install_message:
|
143
|
+
rdoc_options: []
|
144
|
+
require_paths:
|
145
|
+
- lib
|
146
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
147
|
+
requirements:
|
148
|
+
- - ">="
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: 3.2.0
|
151
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
152
|
+
requirements:
|
153
|
+
- - ">="
|
154
|
+
- !ruby/object:Gem::Version
|
155
|
+
version: '0'
|
156
|
+
requirements: []
|
157
|
+
rubygems_version: 3.5.16
|
158
|
+
signing_key:
|
159
|
+
specification_version: 4
|
160
|
+
summary: Sidekiq Middleware for persisting ActiveSupport::CurrentAttributes with ActiveRecord
|
161
|
+
model support
|
162
|
+
test_files: []
|