sidekiq 6.2.2 → 8.1.5
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 +4 -4
- data/Changes.md +726 -11
- data/LICENSE.txt +9 -0
- data/README.md +70 -39
- data/bin/kiq +17 -0
- data/bin/lint-herb +13 -0
- data/bin/multi_queue_bench +271 -0
- data/bin/sidekiq +4 -9
- data/bin/sidekiqload +214 -115
- data/bin/sidekiqmon +4 -1
- data/bin/webload +69 -0
- data/lib/active_job/queue_adapters/sidekiq_adapter.rb +124 -0
- data/lib/generators/sidekiq/job_generator.rb +71 -0
- data/lib/generators/sidekiq/templates/{worker.rb.erb → job.rb.erb} +3 -3
- data/lib/generators/sidekiq/templates/{worker_spec.rb.erb → job_spec.rb.erb} +1 -1
- data/lib/generators/sidekiq/templates/{worker_test.rb.erb → job_test.rb.erb} +1 -1
- data/lib/sidekiq/api.rb +729 -264
- data/lib/sidekiq/capsule.rb +135 -0
- data/lib/sidekiq/cli.rb +124 -100
- data/lib/sidekiq/client.rb +153 -106
- data/lib/sidekiq/component.rb +132 -0
- data/lib/sidekiq/config.rb +320 -0
- data/lib/sidekiq/deploy.rb +64 -0
- data/lib/sidekiq/embedded.rb +64 -0
- data/lib/sidekiq/fetch.rb +27 -26
- data/lib/sidekiq/iterable_job.rb +56 -0
- data/lib/sidekiq/job/interrupt_handler.rb +24 -0
- data/lib/sidekiq/job/iterable/active_record_enumerator.rb +53 -0
- data/lib/sidekiq/job/iterable/csv_enumerator.rb +47 -0
- data/lib/sidekiq/job/iterable/enumerators.rb +135 -0
- data/lib/sidekiq/job/iterable.rb +322 -0
- data/lib/sidekiq/job.rb +397 -5
- data/lib/sidekiq/job_logger.rb +23 -32
- data/lib/sidekiq/job_retry.rb +141 -68
- data/lib/sidekiq/job_util.rb +113 -0
- data/lib/sidekiq/launcher.rb +122 -98
- data/lib/sidekiq/loader.rb +57 -0
- data/lib/sidekiq/logger.rb +27 -106
- data/lib/sidekiq/manager.rb +41 -43
- data/lib/sidekiq/metrics/query.rb +184 -0
- data/lib/sidekiq/metrics/shared.rb +109 -0
- data/lib/sidekiq/metrics/tracking.rb +153 -0
- data/lib/sidekiq/middleware/chain.rb +96 -51
- data/lib/sidekiq/middleware/current_attributes.rb +120 -0
- data/lib/sidekiq/middleware/i18n.rb +8 -4
- data/lib/sidekiq/middleware/modules.rb +23 -0
- data/lib/sidekiq/monitor.rb +16 -6
- data/lib/sidekiq/paginator.rb +37 -10
- data/lib/sidekiq/processor.rb +105 -87
- data/lib/sidekiq/profiler.rb +73 -0
- data/lib/sidekiq/rails.rb +49 -36
- data/lib/sidekiq/redis_client_adapter.rb +117 -0
- data/lib/sidekiq/redis_connection.rb +55 -86
- data/lib/sidekiq/ring_buffer.rb +32 -0
- data/lib/sidekiq/scheduled.rb +106 -50
- data/lib/sidekiq/systemd.rb +2 -0
- data/lib/sidekiq/test_api.rb +331 -0
- data/lib/sidekiq/testing/inline.rb +2 -30
- data/lib/sidekiq/testing.rb +2 -342
- data/lib/sidekiq/transaction_aware_client.rb +59 -0
- data/lib/sidekiq/tui/controls.rb +53 -0
- data/lib/sidekiq/tui/filtering.rb +53 -0
- data/lib/sidekiq/tui/tabs/base_tab.rb +204 -0
- data/lib/sidekiq/tui/tabs/busy.rb +118 -0
- data/lib/sidekiq/tui/tabs/dead.rb +19 -0
- data/lib/sidekiq/tui/tabs/home.rb +144 -0
- data/lib/sidekiq/tui/tabs/metrics.rb +131 -0
- data/lib/sidekiq/tui/tabs/queues.rb +95 -0
- data/lib/sidekiq/tui/tabs/retries.rb +19 -0
- data/lib/sidekiq/tui/tabs/scheduled.rb +19 -0
- data/lib/sidekiq/tui/tabs/set_tab.rb +96 -0
- data/lib/sidekiq/tui/tabs.rb +15 -0
- data/lib/sidekiq/tui.rb +382 -0
- data/lib/sidekiq/version.rb +6 -1
- data/lib/sidekiq/web/action.rb +149 -64
- data/lib/sidekiq/web/application.rb +376 -268
- data/lib/sidekiq/web/config.rb +117 -0
- data/lib/sidekiq/web/helpers.rb +213 -87
- data/lib/sidekiq/web/router.rb +61 -74
- data/lib/sidekiq/web.rb +71 -100
- data/lib/sidekiq/worker_compatibility_alias.rb +13 -0
- data/lib/sidekiq.rb +95 -196
- data/sidekiq.gemspec +14 -11
- data/web/assets/images/logo.png +0 -0
- data/web/assets/images/status.png +0 -0
- data/web/assets/javascripts/application.js +171 -57
- data/web/assets/javascripts/base-charts.js +120 -0
- data/web/assets/javascripts/chart.min.js +13 -0
- data/web/assets/javascripts/chartjs-adapter-date-fns.min.js +7 -0
- data/web/assets/javascripts/chartjs-plugin-annotation.min.js +7 -0
- data/web/assets/javascripts/dashboard-charts.js +194 -0
- data/web/assets/javascripts/dashboard.js +41 -274
- data/web/assets/javascripts/metrics.js +280 -0
- data/web/assets/stylesheets/style.css +776 -0
- data/web/locales/ar.yml +72 -70
- data/web/locales/cs.yml +64 -62
- data/web/locales/da.yml +62 -53
- data/web/locales/de.yml +67 -65
- data/web/locales/el.yml +45 -24
- data/web/locales/en.yml +93 -69
- data/web/locales/es.yml +91 -68
- data/web/locales/fa.yml +67 -65
- data/web/locales/fr.yml +82 -67
- data/web/locales/gd.yml +110 -0
- data/web/locales/he.yml +67 -64
- data/web/locales/hi.yml +61 -59
- data/web/locales/it.yml +94 -54
- data/web/locales/ja.yml +74 -68
- data/web/locales/ko.yml +54 -52
- data/web/locales/lt.yml +68 -66
- data/web/locales/nb.yml +63 -61
- data/web/locales/nl.yml +54 -52
- data/web/locales/pl.yml +47 -45
- data/web/locales/{pt-br.yml → pt-BR.yml} +85 -56
- data/web/locales/pt.yml +53 -51
- data/web/locales/ru.yml +69 -66
- data/web/locales/sv.yml +55 -53
- data/web/locales/ta.yml +62 -60
- data/web/locales/tr.yml +102 -0
- data/web/locales/uk.yml +87 -61
- data/web/locales/ur.yml +66 -64
- data/web/locales/vi.yml +69 -67
- data/web/locales/zh-CN.yml +107 -0
- data/web/locales/{zh-tw.yml → zh-TW.yml} +44 -9
- data/web/views/_footer.html.erb +32 -0
- data/web/views/_job_info.html.erb +115 -0
- data/web/views/_metrics_period_select.html.erb +15 -0
- data/web/views/_nav.html.erb +45 -0
- data/web/views/_paging.html.erb +26 -0
- data/web/views/_poll_link.html.erb +4 -0
- data/web/views/_summary.html.erb +40 -0
- data/web/views/busy.html.erb +151 -0
- data/web/views/dashboard.html.erb +104 -0
- data/web/views/dead.html.erb +38 -0
- data/web/views/filtering.html.erb +6 -0
- data/web/views/layout.html.erb +26 -0
- data/web/views/metrics.html.erb +85 -0
- data/web/views/metrics_for_job.html.erb +58 -0
- data/web/views/morgue.html.erb +69 -0
- data/web/views/profiles.html.erb +43 -0
- data/web/views/queue.html.erb +57 -0
- data/web/views/queues.html.erb +46 -0
- data/web/views/retries.html.erb +77 -0
- data/web/views/retry.html.erb +39 -0
- data/web/views/scheduled.html.erb +64 -0
- data/web/views/{scheduled_job_info.erb → scheduled_job_info.html.erb} +3 -3
- metadata +130 -61
- data/LICENSE +0 -9
- data/lib/generators/sidekiq/worker_generator.rb +0 -57
- data/lib/sidekiq/delay.rb +0 -41
- data/lib/sidekiq/exception_handler.rb +0 -27
- data/lib/sidekiq/extensions/action_mailer.rb +0 -48
- data/lib/sidekiq/extensions/active_record.rb +0 -43
- data/lib/sidekiq/extensions/class_methods.rb +0 -43
- data/lib/sidekiq/extensions/generic_proxy.rb +0 -33
- data/lib/sidekiq/util.rb +0 -95
- data/lib/sidekiq/web/csrf_protection.rb +0 -180
- data/lib/sidekiq/worker.rb +0 -244
- data/web/assets/stylesheets/application-dark.css +0 -147
- data/web/assets/stylesheets/application-rtl.css +0 -246
- data/web/assets/stylesheets/application.css +0 -1053
- data/web/assets/stylesheets/bootstrap-rtl.min.css +0 -9
- data/web/assets/stylesheets/bootstrap.css +0 -5
- data/web/locales/zh-cn.yml +0 -68
- data/web/views/_footer.erb +0 -20
- data/web/views/_job_info.erb +0 -89
- data/web/views/_nav.erb +0 -52
- data/web/views/_paging.erb +0 -23
- data/web/views/_poll_link.erb +0 -7
- data/web/views/_status.erb +0 -4
- data/web/views/_summary.erb +0 -40
- data/web/views/busy.erb +0 -132
- data/web/views/dashboard.erb +0 -83
- data/web/views/dead.erb +0 -34
- data/web/views/layout.erb +0 -42
- data/web/views/morgue.erb +0 -78
- data/web/views/queue.erb +0 -55
- data/web/views/queues.erb +0 -38
- data/web/views/retries.erb +0 -83
- data/web/views/retry.erb +0 -34
- data/web/views/scheduled.erb +0 -57
|
@@ -1,82 +1,93 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "sidekiq/middleware/modules"
|
|
4
|
+
|
|
3
5
|
module Sidekiq
|
|
4
6
|
# Middleware is code configured to run before/after
|
|
5
|
-
# a
|
|
7
|
+
# a job is processed. It is patterned after Rack
|
|
6
8
|
# middleware. Middleware exists for the client side
|
|
7
9
|
# (pushing jobs onto the queue) as well as the server
|
|
8
10
|
# side (when jobs are actually processed).
|
|
9
11
|
#
|
|
12
|
+
# Callers will register middleware Classes and Sidekiq will
|
|
13
|
+
# create new instances of the middleware for every job. This
|
|
14
|
+
# is important so that instance state is not shared accidentally
|
|
15
|
+
# between job executions.
|
|
16
|
+
#
|
|
10
17
|
# To add middleware for the client:
|
|
11
18
|
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
19
|
+
# Sidekiq.configure_client do |config|
|
|
20
|
+
# config.client_middleware do |chain|
|
|
21
|
+
# chain.add MyClientHook
|
|
22
|
+
# end
|
|
15
23
|
# end
|
|
16
|
-
# end
|
|
17
24
|
#
|
|
18
25
|
# To modify middleware for the server, just call
|
|
19
26
|
# with another block:
|
|
20
27
|
#
|
|
21
|
-
#
|
|
22
|
-
#
|
|
23
|
-
#
|
|
24
|
-
#
|
|
28
|
+
# Sidekiq.configure_server do |config|
|
|
29
|
+
# config.server_middleware do |chain|
|
|
30
|
+
# chain.add MyServerHook
|
|
31
|
+
# chain.remove ActiveRecord
|
|
32
|
+
# end
|
|
25
33
|
# end
|
|
26
|
-
# end
|
|
27
34
|
#
|
|
28
35
|
# To insert immediately preceding another entry:
|
|
29
36
|
#
|
|
30
|
-
#
|
|
31
|
-
#
|
|
32
|
-
#
|
|
37
|
+
# Sidekiq.configure_client do |config|
|
|
38
|
+
# config.client_middleware do |chain|
|
|
39
|
+
# chain.insert_before ActiveRecord, MyClientHook
|
|
40
|
+
# end
|
|
33
41
|
# end
|
|
34
|
-
# end
|
|
35
42
|
#
|
|
36
43
|
# To insert immediately after another entry:
|
|
37
44
|
#
|
|
38
|
-
#
|
|
39
|
-
#
|
|
40
|
-
#
|
|
45
|
+
# Sidekiq.configure_client do |config|
|
|
46
|
+
# config.client_middleware do |chain|
|
|
47
|
+
# chain.insert_after ActiveRecord, MyClientHook
|
|
48
|
+
# end
|
|
41
49
|
# end
|
|
42
|
-
# end
|
|
43
50
|
#
|
|
44
51
|
# This is an example of a minimal server middleware:
|
|
45
52
|
#
|
|
46
|
-
#
|
|
47
|
-
#
|
|
48
|
-
#
|
|
49
|
-
#
|
|
50
|
-
#
|
|
53
|
+
# class MyServerHook
|
|
54
|
+
# include Sidekiq::ServerMiddleware
|
|
55
|
+
#
|
|
56
|
+
# def call(job_instance, msg, queue)
|
|
57
|
+
# logger.info "Before job"
|
|
58
|
+
# redis {|conn| conn.get("foo") } # do something in Redis
|
|
59
|
+
# yield
|
|
60
|
+
# logger.info "After job"
|
|
61
|
+
# end
|
|
51
62
|
# end
|
|
52
|
-
# end
|
|
53
63
|
#
|
|
54
64
|
# This is an example of a minimal client middleware, note
|
|
55
65
|
# the method must return the result or the job will not push
|
|
56
66
|
# to Redis:
|
|
57
67
|
#
|
|
58
|
-
#
|
|
59
|
-
#
|
|
60
|
-
#
|
|
61
|
-
#
|
|
62
|
-
#
|
|
63
|
-
#
|
|
68
|
+
# class MyClientHook
|
|
69
|
+
# include Sidekiq::ClientMiddleware
|
|
70
|
+
#
|
|
71
|
+
# def call(job_class, msg, queue, redis_pool)
|
|
72
|
+
# logger.info "Before push"
|
|
73
|
+
# result = yield
|
|
74
|
+
# logger.info "After push"
|
|
75
|
+
# result
|
|
76
|
+
# end
|
|
64
77
|
# end
|
|
65
|
-
# end
|
|
66
78
|
#
|
|
67
79
|
module Middleware
|
|
68
80
|
class Chain
|
|
69
81
|
include Enumerable
|
|
70
82
|
|
|
71
|
-
|
|
72
|
-
copy.instance_variable_set(:@entries, entries.dup)
|
|
73
|
-
end
|
|
74
|
-
|
|
83
|
+
# Iterate through each middleware in the chain
|
|
75
84
|
def each(&block)
|
|
76
85
|
entries.each(&block)
|
|
77
86
|
end
|
|
78
87
|
|
|
79
|
-
|
|
88
|
+
# @api private
|
|
89
|
+
def initialize(config = nil) # :nodoc:
|
|
90
|
+
@config = config
|
|
80
91
|
@entries = nil
|
|
81
92
|
yield self if block_given?
|
|
82
93
|
end
|
|
@@ -85,38 +96,62 @@ module Sidekiq
|
|
|
85
96
|
@entries ||= []
|
|
86
97
|
end
|
|
87
98
|
|
|
99
|
+
def copy_for(capsule)
|
|
100
|
+
chain = Sidekiq::Middleware::Chain.new(capsule)
|
|
101
|
+
chain.instance_variable_set(:@entries, entries.dup)
|
|
102
|
+
chain
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Remove all middleware matching the given Class
|
|
106
|
+
# @param klass [Class]
|
|
88
107
|
def remove(klass)
|
|
89
108
|
entries.delete_if { |entry| entry.klass == klass }
|
|
90
109
|
end
|
|
91
110
|
|
|
111
|
+
# Add the given middleware to the end of the chain.
|
|
112
|
+
# Sidekiq will call `klass.new(*args)` to create a clean
|
|
113
|
+
# copy of your middleware for every job executed.
|
|
114
|
+
#
|
|
115
|
+
# chain.add(Statsd::Metrics, { collector: "localhost:8125" })
|
|
116
|
+
#
|
|
117
|
+
# @param klass [Class] Your middleware class
|
|
118
|
+
# @param *args [Array<Object>] Set of arguments to pass to every instance of your middleware
|
|
92
119
|
def add(klass, *args)
|
|
93
120
|
remove(klass)
|
|
94
|
-
entries << Entry.new(klass, *args)
|
|
121
|
+
entries << Entry.new(@config, klass, *args)
|
|
95
122
|
end
|
|
96
123
|
|
|
124
|
+
# Identical to {#add} except the middleware is added to the front of the chain.
|
|
97
125
|
def prepend(klass, *args)
|
|
98
126
|
remove(klass)
|
|
99
|
-
entries.insert(0, Entry.new(klass, *args))
|
|
127
|
+
entries.insert(0, Entry.new(@config, klass, *args))
|
|
100
128
|
end
|
|
101
129
|
|
|
130
|
+
# Inserts +newklass+ before +oldklass+ in the chain.
|
|
131
|
+
# Useful if one middleware must run before another middleware.
|
|
102
132
|
def insert_before(oldklass, newklass, *args)
|
|
103
133
|
i = entries.index { |entry| entry.klass == newklass }
|
|
104
|
-
new_entry = i.nil? ? Entry.new(newklass, *args) : entries.delete_at(i)
|
|
134
|
+
new_entry = i.nil? ? Entry.new(@config, newklass, *args) : entries.delete_at(i)
|
|
105
135
|
i = entries.index { |entry| entry.klass == oldklass } || 0
|
|
106
136
|
entries.insert(i, new_entry)
|
|
107
137
|
end
|
|
108
138
|
|
|
139
|
+
# Inserts +newklass+ after +oldklass+ in the chain.
|
|
140
|
+
# Useful if one middleware must run after another middleware.
|
|
109
141
|
def insert_after(oldklass, newklass, *args)
|
|
110
142
|
i = entries.index { |entry| entry.klass == newklass }
|
|
111
|
-
new_entry = i.nil? ? Entry.new(newklass, *args) : entries.delete_at(i)
|
|
143
|
+
new_entry = i.nil? ? Entry.new(@config, newklass, *args) : entries.delete_at(i)
|
|
112
144
|
i = entries.index { |entry| entry.klass == oldklass } || entries.count - 1
|
|
113
145
|
entries.insert(i + 1, new_entry)
|
|
114
146
|
end
|
|
115
147
|
|
|
148
|
+
# @return [Boolean] if the given class is already in the chain
|
|
116
149
|
def exists?(klass)
|
|
117
150
|
any? { |entry| entry.klass == klass }
|
|
118
151
|
end
|
|
152
|
+
alias_method :include?, :exists?
|
|
119
153
|
|
|
154
|
+
# @return [Boolean] if the chain contains no middleware
|
|
120
155
|
def empty?
|
|
121
156
|
@entries.nil? || @entries.empty?
|
|
122
157
|
end
|
|
@@ -129,33 +164,43 @@ module Sidekiq
|
|
|
129
164
|
entries.clear
|
|
130
165
|
end
|
|
131
166
|
|
|
132
|
-
|
|
167
|
+
# Used by Sidekiq to execute the middleware at runtime
|
|
168
|
+
# @api private
|
|
169
|
+
def invoke(*args, &block)
|
|
133
170
|
return yield if empty?
|
|
134
171
|
|
|
135
172
|
chain = retrieve
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
173
|
+
traverse(chain, 0, args, &block)
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
private
|
|
177
|
+
|
|
178
|
+
def traverse(chain, index, args, &block)
|
|
179
|
+
if index >= chain.size
|
|
180
|
+
yield
|
|
181
|
+
else
|
|
182
|
+
chain[index].call(*args) do
|
|
183
|
+
traverse(chain, index + 1, args, &block)
|
|
141
184
|
end
|
|
142
185
|
end
|
|
143
|
-
traverse_chain.call
|
|
144
186
|
end
|
|
145
187
|
end
|
|
146
188
|
|
|
147
|
-
|
|
148
|
-
|
|
189
|
+
# Represents each link in the middleware chain
|
|
190
|
+
# @api private
|
|
149
191
|
class Entry
|
|
150
192
|
attr_reader :klass
|
|
151
193
|
|
|
152
|
-
def initialize(klass, *args)
|
|
194
|
+
def initialize(config, klass, *args)
|
|
195
|
+
@config = config
|
|
153
196
|
@klass = klass
|
|
154
197
|
@args = args
|
|
155
198
|
end
|
|
156
199
|
|
|
157
200
|
def make_new
|
|
158
|
-
@klass.new(*@args)
|
|
201
|
+
x = @klass.new(*@args)
|
|
202
|
+
x.config = @config if @config && x.respond_to?(:config=)
|
|
203
|
+
x
|
|
159
204
|
end
|
|
160
205
|
end
|
|
161
206
|
end
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_job/arguments"
|
|
4
|
+
require "active_support/current_attributes"
|
|
5
|
+
|
|
6
|
+
module Sidekiq
|
|
7
|
+
##
|
|
8
|
+
# Automatically save and load any current attributes in the execution context
|
|
9
|
+
# so context attributes "flow" from Rails actions into any associated jobs.
|
|
10
|
+
# This can be useful for multi-tenancy, i18n locale, timezone, any implicit
|
|
11
|
+
# per-request attribute. See +ActiveSupport::CurrentAttributes+.
|
|
12
|
+
#
|
|
13
|
+
# For multiple current attributes, pass an array of current attributes.
|
|
14
|
+
#
|
|
15
|
+
# @example
|
|
16
|
+
#
|
|
17
|
+
# # in your initializer
|
|
18
|
+
# require "sidekiq/middleware/current_attributes"
|
|
19
|
+
# Sidekiq::CurrentAttributes.persist("Myapp::Current")
|
|
20
|
+
# # or multiple current attributes
|
|
21
|
+
# Sidekiq::CurrentAttributes.persist(["Myapp::Current", "Myapp::OtherCurrent"])
|
|
22
|
+
#
|
|
23
|
+
module CurrentAttributes
|
|
24
|
+
Serializer = ::ActiveJob::Arguments
|
|
25
|
+
|
|
26
|
+
class Save
|
|
27
|
+
include Sidekiq::ClientMiddleware
|
|
28
|
+
|
|
29
|
+
def initialize(cattrs)
|
|
30
|
+
@cattrs = cattrs
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def call(_, job, _, _)
|
|
34
|
+
@cattrs.each do |(key, strklass)|
|
|
35
|
+
if !job.has_key?(key)
|
|
36
|
+
attrs = strklass.constantize.attributes
|
|
37
|
+
# Retries can push the job N times, we don't
|
|
38
|
+
# want retries to reset cattr. #5692, #5090
|
|
39
|
+
job[key] = Serializer.serialize(attrs) if attrs.any?
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
yield
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
class Load
|
|
47
|
+
include Sidekiq::ServerMiddleware
|
|
48
|
+
|
|
49
|
+
def initialize(cattrs)
|
|
50
|
+
@cattrs = cattrs
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def call(_, job, *, &block)
|
|
54
|
+
klass_attrs = {}
|
|
55
|
+
|
|
56
|
+
@cattrs.each do |(key, strklass)|
|
|
57
|
+
next unless job.has_key?(key)
|
|
58
|
+
|
|
59
|
+
klass_attrs[strklass.constantize] = Serializer.deserialize(job[key]).to_h
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
wrap(klass_attrs.to_a, &block)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
private
|
|
66
|
+
|
|
67
|
+
def wrap(klass_attrs, &block)
|
|
68
|
+
klass, attrs = klass_attrs.shift
|
|
69
|
+
return block.call unless klass
|
|
70
|
+
|
|
71
|
+
retried = false
|
|
72
|
+
|
|
73
|
+
begin
|
|
74
|
+
set_succeeded = false
|
|
75
|
+
klass.set(attrs) do
|
|
76
|
+
set_succeeded = true
|
|
77
|
+
wrap(klass_attrs, &block)
|
|
78
|
+
end
|
|
79
|
+
rescue NoMethodError
|
|
80
|
+
# Don't retry if the no method error didn't come from current attributes
|
|
81
|
+
raise if retried || set_succeeded
|
|
82
|
+
|
|
83
|
+
# It is possible that the `CurrentAttributes` definition
|
|
84
|
+
# was changed before the job started processing.
|
|
85
|
+
attrs = attrs.select { |attr| klass.respond_to?(attr) }
|
|
86
|
+
retried = true
|
|
87
|
+
retry
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
class << self
|
|
93
|
+
def persist(klass_or_array, config = Sidekiq.default_configuration)
|
|
94
|
+
cattrs = build_cattrs_hash(klass_or_array)
|
|
95
|
+
|
|
96
|
+
config.client_middleware.prepend Load, cattrs
|
|
97
|
+
config.client_middleware.add Save, cattrs
|
|
98
|
+
config.server_middleware.prepend Load, cattrs
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
private
|
|
102
|
+
|
|
103
|
+
def build_cattrs_hash(klass_or_array)
|
|
104
|
+
if klass_or_array.is_a?(Array)
|
|
105
|
+
{}.tap do |hash|
|
|
106
|
+
klass_or_array.each_with_index do |klass, index|
|
|
107
|
+
hash[key_at(index)] = klass.to_s
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
else
|
|
111
|
+
{key_at(0) => klass_or_array.to_s}
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def key_at(index)
|
|
116
|
+
(index == 0) ? "cattr" : "cattr_#{index}"
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
@@ -10,16 +10,20 @@ module Sidekiq::Middleware::I18n
|
|
|
10
10
|
# Get the current locale and store it in the message
|
|
11
11
|
# to be sent to Sidekiq.
|
|
12
12
|
class Client
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
include Sidekiq::ClientMiddleware
|
|
14
|
+
|
|
15
|
+
def call(_jobclass, job, _queue, _redis)
|
|
16
|
+
job["locale"] ||= I18n.locale
|
|
15
17
|
yield
|
|
16
18
|
end
|
|
17
19
|
end
|
|
18
20
|
|
|
19
21
|
# Pull the msg locale out and set the current thread to use it.
|
|
20
22
|
class Server
|
|
21
|
-
|
|
22
|
-
|
|
23
|
+
include Sidekiq::ServerMiddleware
|
|
24
|
+
|
|
25
|
+
def call(_jobclass, job, _queue, &block)
|
|
26
|
+
I18n.with_locale(job.fetch("locale", I18n.default_locale), &block)
|
|
23
27
|
end
|
|
24
28
|
end
|
|
25
29
|
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sidekiq
|
|
4
|
+
# Server-side middleware must import this Module in order
|
|
5
|
+
# to get access to server resources during `call`.
|
|
6
|
+
module ServerMiddleware
|
|
7
|
+
attr_accessor :config
|
|
8
|
+
def redis_pool
|
|
9
|
+
config.redis_pool
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def logger
|
|
13
|
+
config.logger
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def redis(&block)
|
|
17
|
+
config.redis(&block)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# no difference for now
|
|
22
|
+
ClientMiddleware = ServerMiddleware
|
|
23
|
+
end
|
data/lib/sidekiq/monitor.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
|
|
3
4
|
require "fileutils"
|
|
4
5
|
require "sidekiq/api"
|
|
@@ -16,8 +17,6 @@ class Sidekiq::Monitor
|
|
|
16
17
|
return
|
|
17
18
|
end
|
|
18
19
|
send(section)
|
|
19
|
-
rescue => e
|
|
20
|
-
puts "Couldn't get status: #{e}"
|
|
21
20
|
end
|
|
22
21
|
|
|
23
22
|
def all
|
|
@@ -49,10 +48,21 @@ class Sidekiq::Monitor
|
|
|
49
48
|
def processes
|
|
50
49
|
puts "---- Processes (#{process_set.size}) ----"
|
|
51
50
|
process_set.each_with_index do |process, index|
|
|
51
|
+
# Keep compatibility with legacy versions since we don't want to break sidekiqmon during rolling upgrades or downgrades.
|
|
52
|
+
queues =
|
|
53
|
+
if process["capsules"] # 8.0.6+
|
|
54
|
+
process["capsules"].values.map { |x| x["weights"].keys.join(", ") }
|
|
55
|
+
elsif process["weights"]
|
|
56
|
+
process["weights"].sort_by { |queue| queue[0] }.map { |capsule| capsule.map { |name, weight| (weight > 0) ? "#{name}: #{weight}" : name }.join(", ") }
|
|
57
|
+
else
|
|
58
|
+
process["queues"].sort
|
|
59
|
+
end
|
|
60
|
+
|
|
52
61
|
puts "#{process["identity"]} #{tags_for(process)}"
|
|
53
62
|
puts " Started: #{Time.at(process["started_at"])} (#{time_ago(process["started_at"])})"
|
|
54
63
|
puts " Threads: #{process["concurrency"]} (#{process["busy"]} busy)"
|
|
55
|
-
puts " Queues: #{split_multiline(
|
|
64
|
+
puts " Queues: #{split_multiline(queues, pad: 11)}"
|
|
65
|
+
puts " Version: #{process["version"] || "Unknown"}" if process["version"] != Sidekiq::VERSION
|
|
56
66
|
puts "" unless (index + 1) == process_set.size
|
|
57
67
|
end
|
|
58
68
|
end
|
|
@@ -85,13 +95,13 @@ class Sidekiq::Monitor
|
|
|
85
95
|
pad = opts[:pad] || 0
|
|
86
96
|
max_length = opts[:max_length] || (80 - pad)
|
|
87
97
|
out = []
|
|
88
|
-
line = ""
|
|
98
|
+
line = +""
|
|
89
99
|
values.each do |value|
|
|
90
100
|
if (line.length + value.length) > max_length
|
|
91
101
|
out << line
|
|
92
102
|
line = " " * pad
|
|
93
103
|
end
|
|
94
|
-
line << value + "
|
|
104
|
+
line << value + "; "
|
|
95
105
|
end
|
|
96
106
|
out << line[0..-3]
|
|
97
107
|
out.join("\n")
|
|
@@ -101,7 +111,7 @@ class Sidekiq::Monitor
|
|
|
101
111
|
tags = [
|
|
102
112
|
process["tag"],
|
|
103
113
|
process["labels"],
|
|
104
|
-
(process["quiet"] == "true" ? "quiet" : nil)
|
|
114
|
+
((process["quiet"] == "true") ? "quiet" : nil)
|
|
105
115
|
].flatten.compact
|
|
106
116
|
tags.any? ? "[#{tags.join("] [")}]" : nil
|
|
107
117
|
end
|
data/lib/sidekiq/paginator.rb
CHANGED
|
@@ -2,8 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
module Sidekiq
|
|
4
4
|
module Paginator
|
|
5
|
+
TYPE_CACHE = {
|
|
6
|
+
"dead" => "zset",
|
|
7
|
+
"retry" => "zset",
|
|
8
|
+
"schedule" => "zset"
|
|
9
|
+
}
|
|
10
|
+
|
|
5
11
|
def page(key, pageidx = 1, page_size = 25, opts = nil)
|
|
6
|
-
current_page = pageidx.to_i < 1 ? 1 : pageidx.to_i
|
|
12
|
+
current_page = (pageidx.to_i < 1) ? 1 : pageidx.to_i
|
|
7
13
|
pageidx = current_page - 1
|
|
8
14
|
total_size = 0
|
|
9
15
|
items = []
|
|
@@ -11,27 +17,35 @@ module Sidekiq
|
|
|
11
17
|
ending = starting + page_size - 1
|
|
12
18
|
|
|
13
19
|
Sidekiq.redis do |conn|
|
|
14
|
-
|
|
20
|
+
# horrible, think you can make this cleaner?
|
|
21
|
+
type = TYPE_CACHE[key]
|
|
22
|
+
if type
|
|
23
|
+
elsif key.start_with?("queue:")
|
|
24
|
+
type = TYPE_CACHE[key] = "list"
|
|
25
|
+
else
|
|
26
|
+
type = conn.type(key)
|
|
27
|
+
TYPE_CACHE[key] = type unless type == "none"
|
|
28
|
+
end
|
|
15
29
|
rev = opts && opts[:reverse]
|
|
16
30
|
|
|
17
31
|
case type
|
|
18
32
|
when "zset"
|
|
19
|
-
total_size, items = conn.multi {
|
|
20
|
-
|
|
33
|
+
total_size, items = conn.multi { |transaction|
|
|
34
|
+
transaction.zcard(key)
|
|
21
35
|
if rev
|
|
22
|
-
|
|
36
|
+
transaction.zrange(key, starting, ending, "REV", "withscores")
|
|
23
37
|
else
|
|
24
|
-
|
|
38
|
+
transaction.zrange(key, starting, ending, "withscores")
|
|
25
39
|
end
|
|
26
40
|
}
|
|
27
41
|
[current_page, total_size, items]
|
|
28
42
|
when "list"
|
|
29
|
-
total_size, items = conn.multi {
|
|
30
|
-
|
|
43
|
+
total_size, items = conn.multi { |transaction|
|
|
44
|
+
transaction.llen(key)
|
|
31
45
|
if rev
|
|
32
|
-
|
|
46
|
+
transaction.lrange(key, -ending - 1, -starting - 1)
|
|
33
47
|
else
|
|
34
|
-
|
|
48
|
+
transaction.lrange(key, starting, ending)
|
|
35
49
|
end
|
|
36
50
|
}
|
|
37
51
|
items.reverse! if rev
|
|
@@ -43,5 +57,18 @@ module Sidekiq
|
|
|
43
57
|
end
|
|
44
58
|
end
|
|
45
59
|
end
|
|
60
|
+
|
|
61
|
+
def page_items(items, pageidx = 1, page_size = 25)
|
|
62
|
+
current_page = (pageidx.to_i < 1) ? 1 : pageidx.to_i
|
|
63
|
+
pageidx = current_page - 1
|
|
64
|
+
starting = pageidx * page_size
|
|
65
|
+
items = items.to_a
|
|
66
|
+
total_size = items.size
|
|
67
|
+
if starting > total_size
|
|
68
|
+
starting = 0
|
|
69
|
+
current_page = 1
|
|
70
|
+
end
|
|
71
|
+
[current_page, total_size, items[starting, page_size]]
|
|
72
|
+
end
|
|
46
73
|
end
|
|
47
74
|
end
|