sidekiq 4.2.4 → 6.4.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sidekiq might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/Changes.md +523 -0
- data/LICENSE +3 -3
- data/README.md +23 -36
- data/bin/sidekiq +26 -2
- data/bin/sidekiqload +28 -38
- data/bin/sidekiqmon +8 -0
- data/lib/generators/sidekiq/job_generator.rb +57 -0
- data/lib/generators/sidekiq/templates/{worker.rb.erb → job.rb.erb} +2 -2
- data/lib/generators/sidekiq/templates/job_spec.rb.erb +6 -0
- data/lib/generators/sidekiq/templates/job_test.rb.erb +8 -0
- data/lib/sidekiq/api.rb +403 -243
- data/lib/sidekiq/cli.rb +230 -211
- data/lib/sidekiq/client.rb +53 -64
- data/lib/sidekiq/delay.rb +43 -0
- data/lib/sidekiq/exception_handler.rb +12 -16
- data/lib/sidekiq/extensions/action_mailer.rb +15 -24
- data/lib/sidekiq/extensions/active_record.rb +15 -12
- data/lib/sidekiq/extensions/class_methods.rb +16 -13
- data/lib/sidekiq/extensions/generic_proxy.rb +14 -6
- data/lib/sidekiq/fetch.rb +39 -31
- data/lib/sidekiq/job.rb +13 -0
- data/lib/sidekiq/job_logger.rb +63 -0
- data/lib/sidekiq/job_retry.rb +261 -0
- data/lib/sidekiq/job_util.rb +65 -0
- data/lib/sidekiq/launcher.rb +170 -71
- data/lib/sidekiq/logger.rb +166 -0
- data/lib/sidekiq/manager.rb +21 -26
- data/lib/sidekiq/middleware/chain.rb +20 -8
- data/lib/sidekiq/middleware/current_attributes.rb +57 -0
- data/lib/sidekiq/middleware/i18n.rb +5 -7
- data/lib/sidekiq/monitor.rb +133 -0
- data/lib/sidekiq/paginator.rb +18 -14
- data/lib/sidekiq/processor.rb +161 -70
- data/lib/sidekiq/rails.rb +41 -73
- data/lib/sidekiq/redis_connection.rb +65 -20
- data/lib/sidekiq/scheduled.rb +95 -34
- data/lib/sidekiq/sd_notify.rb +149 -0
- data/lib/sidekiq/systemd.rb +24 -0
- data/lib/sidekiq/testing/inline.rb +2 -1
- data/lib/sidekiq/testing.rb +52 -26
- data/lib/sidekiq/util.rb +60 -14
- data/lib/sidekiq/version.rb +2 -1
- data/lib/sidekiq/web/action.rb +15 -15
- data/lib/sidekiq/web/application.rb +115 -89
- data/lib/sidekiq/web/csrf_protection.rb +180 -0
- data/lib/sidekiq/web/helpers.rb +151 -83
- data/lib/sidekiq/web/router.rb +27 -19
- data/lib/sidekiq/web.rb +65 -109
- data/lib/sidekiq/worker.rb +284 -41
- data/lib/sidekiq.rb +93 -60
- data/sidekiq.gemspec +24 -22
- data/web/assets/images/apple-touch-icon.png +0 -0
- data/web/assets/javascripts/application.js +83 -64
- data/web/assets/javascripts/dashboard.js +81 -85
- data/web/assets/stylesheets/application-dark.css +143 -0
- data/web/assets/stylesheets/application-rtl.css +242 -0
- data/web/assets/stylesheets/application.css +319 -143
- data/web/assets/stylesheets/bootstrap-rtl.min.css +9 -0
- data/web/assets/stylesheets/bootstrap.css +2 -2
- data/web/locales/ar.yml +87 -0
- data/web/locales/de.yml +14 -2
- data/web/locales/en.yml +8 -1
- data/web/locales/es.yml +22 -5
- data/web/locales/fa.yml +80 -0
- data/web/locales/fr.yml +10 -3
- data/web/locales/he.yml +79 -0
- data/web/locales/ja.yml +12 -4
- data/web/locales/lt.yml +83 -0
- data/web/locales/pl.yml +4 -4
- data/web/locales/ru.yml +4 -0
- data/web/locales/ur.yml +80 -0
- data/web/locales/vi.yml +83 -0
- data/web/views/_footer.erb +5 -2
- data/web/views/_job_info.erb +4 -3
- data/web/views/_nav.erb +4 -18
- data/web/views/_paging.erb +1 -1
- data/web/views/_poll_link.erb +2 -5
- data/web/views/_summary.erb +7 -7
- data/web/views/busy.erb +60 -22
- data/web/views/dashboard.erb +23 -15
- data/web/views/dead.erb +3 -3
- data/web/views/layout.erb +14 -3
- data/web/views/morgue.erb +19 -12
- data/web/views/queue.erb +24 -14
- data/web/views/queues.erb +14 -4
- data/web/views/retries.erb +22 -13
- data/web/views/retry.erb +4 -4
- data/web/views/scheduled.erb +7 -4
- metadata +49 -198
- data/.github/contributing.md +0 -32
- data/.github/issue_template.md +0 -4
- data/.gitignore +0 -12
- data/.travis.yml +0 -12
- data/3.0-Upgrade.md +0 -70
- data/4.0-Upgrade.md +0 -53
- data/COMM-LICENSE +0 -95
- data/Ent-Changes.md +0 -146
- data/Gemfile +0 -29
- data/Pro-2.0-Upgrade.md +0 -138
- data/Pro-3.0-Upgrade.md +0 -44
- data/Pro-Changes.md +0 -585
- data/Rakefile +0 -9
- data/bin/sidekiqctl +0 -99
- data/code_of_conduct.md +0 -50
- data/lib/generators/sidekiq/templates/worker_spec.rb.erb +0 -6
- data/lib/generators/sidekiq/templates/worker_test.rb.erb +0 -8
- data/lib/generators/sidekiq/worker_generator.rb +0 -49
- data/lib/sidekiq/core_ext.rb +0 -106
- data/lib/sidekiq/logging.rb +0 -106
- data/lib/sidekiq/middleware/server/active_record.rb +0 -13
- data/lib/sidekiq/middleware/server/logging.rb +0 -40
- data/lib/sidekiq/middleware/server/retry_jobs.rb +0 -205
- data/test/config.yml +0 -9
- data/test/env_based_config.yml +0 -11
- data/test/fake_env.rb +0 -1
- data/test/fixtures/en.yml +0 -2
- data/test/helper.rb +0 -75
- data/test/test_actors.rb +0 -138
- data/test/test_api.rb +0 -528
- data/test/test_cli.rb +0 -418
- data/test/test_client.rb +0 -266
- data/test/test_exception_handler.rb +0 -56
- data/test/test_extensions.rb +0 -127
- data/test/test_fetch.rb +0 -50
- data/test/test_launcher.rb +0 -95
- data/test/test_logging.rb +0 -35
- data/test/test_manager.rb +0 -50
- data/test/test_middleware.rb +0 -158
- data/test/test_processor.rb +0 -235
- data/test/test_rails.rb +0 -22
- data/test/test_redis_connection.rb +0 -132
- data/test/test_retry.rb +0 -326
- data/test/test_retry_exhausted.rb +0 -149
- data/test/test_scheduled.rb +0 -115
- data/test/test_scheduling.rb +0 -58
- data/test/test_sidekiq.rb +0 -107
- data/test/test_testing.rb +0 -143
- data/test/test_testing_fake.rb +0 -357
- data/test/test_testing_inline.rb +0 -94
- data/test/test_util.rb +0 -13
- data/test/test_web.rb +0 -726
- data/test/test_web_helpers.rb +0 -54
data/lib/sidekiq/testing.rb
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require 'securerandom'
|
3
|
-
require 'sidekiq'
|
4
2
|
|
5
|
-
|
3
|
+
require "securerandom"
|
4
|
+
require "sidekiq"
|
6
5
|
|
6
|
+
module Sidekiq
|
7
7
|
class Testing
|
8
8
|
class << self
|
9
9
|
attr_accessor :__test_mode
|
10
10
|
|
11
11
|
def __set_test_mode(mode)
|
12
12
|
if block_given?
|
13
|
-
current_mode =
|
13
|
+
current_mode = __test_mode
|
14
14
|
begin
|
15
15
|
self.__test_mode = mode
|
16
16
|
yield
|
@@ -35,19 +35,19 @@ module Sidekiq
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def enabled?
|
38
|
-
|
38
|
+
__test_mode != :disable
|
39
39
|
end
|
40
40
|
|
41
41
|
def disabled?
|
42
|
-
|
42
|
+
__test_mode == :disable
|
43
43
|
end
|
44
44
|
|
45
45
|
def fake?
|
46
|
-
|
46
|
+
__test_mode == :fake
|
47
47
|
end
|
48
48
|
|
49
49
|
def inline?
|
50
|
-
|
50
|
+
__test_mode == :inline
|
51
51
|
end
|
52
52
|
|
53
53
|
def server_middleware
|
@@ -55,6 +55,15 @@ module Sidekiq
|
|
55
55
|
yield @server_chain if block_given?
|
56
56
|
@server_chain
|
57
57
|
end
|
58
|
+
|
59
|
+
def constantize(str)
|
60
|
+
names = str.split("::")
|
61
|
+
names.shift if names.empty? || names.first.empty?
|
62
|
+
|
63
|
+
names.inject(Object) do |constant, name|
|
64
|
+
constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
|
65
|
+
end
|
66
|
+
end
|
58
67
|
end
|
59
68
|
end
|
60
69
|
|
@@ -63,29 +72,31 @@ module Sidekiq
|
|
63
72
|
|
64
73
|
class EmptyQueueError < RuntimeError; end
|
65
74
|
|
66
|
-
|
67
|
-
alias_method :raw_push_real, :raw_push
|
68
|
-
|
75
|
+
module TestingClient
|
69
76
|
def raw_push(payloads)
|
70
77
|
if Sidekiq::Testing.fake?
|
71
78
|
payloads.each do |job|
|
72
|
-
|
79
|
+
job = Sidekiq.load_json(Sidekiq.dump_json(job))
|
80
|
+
job["enqueued_at"] = Time.now.to_f unless job["at"]
|
81
|
+
Queues.push(job["queue"], job["class"], job)
|
73
82
|
end
|
74
83
|
true
|
75
84
|
elsif Sidekiq::Testing.inline?
|
76
85
|
payloads.each do |job|
|
77
|
-
klass = job[
|
78
|
-
job[
|
86
|
+
klass = Sidekiq::Testing.constantize(job["class"])
|
87
|
+
job["id"] ||= SecureRandom.hex(12)
|
79
88
|
job_hash = Sidekiq.load_json(Sidekiq.dump_json(job))
|
80
89
|
klass.process_job(job_hash)
|
81
90
|
end
|
82
91
|
true
|
83
92
|
else
|
84
|
-
|
93
|
+
super
|
85
94
|
end
|
86
95
|
end
|
87
96
|
end
|
88
97
|
|
98
|
+
Sidekiq::Client.prepend TestingClient
|
99
|
+
|
89
100
|
module Queues
|
90
101
|
##
|
91
102
|
# The Queues class is only for testing the fake queue implementation.
|
@@ -244,27 +255,26 @@ module Sidekiq
|
|
244
255
|
# Then I should receive a welcome email to "foo@example.com"
|
245
256
|
#
|
246
257
|
module ClassMethods
|
247
|
-
|
248
258
|
# Queue for this worker
|
249
259
|
def queue
|
250
|
-
|
260
|
+
get_sidekiq_options["queue"]
|
251
261
|
end
|
252
262
|
|
253
263
|
# Jobs queued for this worker
|
254
264
|
def jobs
|
255
|
-
Queues.jobs_by_worker[
|
265
|
+
Queues.jobs_by_worker[to_s]
|
256
266
|
end
|
257
267
|
|
258
268
|
# Clear all jobs for this worker
|
259
269
|
def clear
|
260
|
-
Queues.clear_for(queue,
|
270
|
+
Queues.clear_for(queue, to_s)
|
261
271
|
end
|
262
272
|
|
263
273
|
# Drain and run all jobs for this worker
|
264
274
|
def drain
|
265
275
|
while jobs.any?
|
266
276
|
next_job = jobs.first
|
267
|
-
Queues.delete_for(next_job["jid"], next_job["queue"],
|
277
|
+
Queues.delete_for(next_job["jid"], next_job["queue"], to_s)
|
268
278
|
process_job(next_job)
|
269
279
|
end
|
270
280
|
end
|
@@ -273,16 +283,16 @@ module Sidekiq
|
|
273
283
|
def perform_one
|
274
284
|
raise(EmptyQueueError, "perform_one called with empty job queue") if jobs.empty?
|
275
285
|
next_job = jobs.first
|
276
|
-
Queues.delete_for(next_job["jid"], queue,
|
286
|
+
Queues.delete_for(next_job["jid"], queue, to_s)
|
277
287
|
process_job(next_job)
|
278
288
|
end
|
279
289
|
|
280
290
|
def process_job(job)
|
281
291
|
worker = new
|
282
|
-
worker.jid = job[
|
283
|
-
worker.bid = job[
|
284
|
-
Sidekiq::Testing.server_middleware.invoke(worker, job, job[
|
285
|
-
execute_job(worker, job[
|
292
|
+
worker.jid = job["jid"]
|
293
|
+
worker.bid = job["bid"] if worker.respond_to?(:bid=)
|
294
|
+
Sidekiq::Testing.server_middleware.invoke(worker, job, job["queue"]) do
|
295
|
+
execute_job(worker, job["args"])
|
286
296
|
end
|
287
297
|
end
|
288
298
|
|
@@ -307,10 +317,26 @@ module Sidekiq
|
|
307
317
|
worker_classes = jobs.map { |job| job["class"] }.uniq
|
308
318
|
|
309
319
|
worker_classes.each do |worker_class|
|
310
|
-
|
320
|
+
Sidekiq::Testing.constantize(worker_class).drain
|
311
321
|
end
|
312
322
|
end
|
313
323
|
end
|
314
324
|
end
|
315
325
|
end
|
326
|
+
|
327
|
+
module TestingExtensions
|
328
|
+
def jobs_for(klass)
|
329
|
+
jobs.select do |job|
|
330
|
+
marshalled = job["args"][0]
|
331
|
+
marshalled.index(klass.to_s) && YAML.load(marshalled)[0] == klass
|
332
|
+
end
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
Sidekiq::Extensions::DelayedMailer.extend(TestingExtensions) if defined?(Sidekiq::Extensions::DelayedMailer)
|
337
|
+
Sidekiq::Extensions::DelayedModel.extend(TestingExtensions) if defined?(Sidekiq::Extensions::DelayedModel)
|
338
|
+
end
|
339
|
+
|
340
|
+
if defined?(::Rails) && Rails.respond_to?(:env) && !Rails.env.test? && !$TESTING
|
341
|
+
warn("⛔️ WARNING: Sidekiq testing API enabled, but this is not the test environment. Your jobs will not go to Redis.", uplevel: 1)
|
316
342
|
end
|
data/lib/sidekiq/util.rb
CHANGED
@@ -1,27 +1,67 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
2
|
+
|
3
|
+
require "forwardable"
|
4
|
+
require "socket"
|
5
|
+
require "securerandom"
|
6
|
+
require "sidekiq/exception_handler"
|
6
7
|
|
7
8
|
module Sidekiq
|
8
9
|
##
|
9
10
|
# This module is part of Sidekiq core and not intended for extensions.
|
10
11
|
#
|
12
|
+
|
13
|
+
class RingBuffer
|
14
|
+
include Enumerable
|
15
|
+
extend Forwardable
|
16
|
+
def_delegators :@buf, :[], :each, :size
|
17
|
+
|
18
|
+
def initialize(size, default = 0)
|
19
|
+
@size = size
|
20
|
+
@buf = Array.new(size, default)
|
21
|
+
@index = 0
|
22
|
+
end
|
23
|
+
|
24
|
+
def <<(element)
|
25
|
+
@buf[@index % @size] = element
|
26
|
+
@index += 1
|
27
|
+
element
|
28
|
+
end
|
29
|
+
|
30
|
+
def buffer
|
31
|
+
@buf
|
32
|
+
end
|
33
|
+
|
34
|
+
def reset(default = 0)
|
35
|
+
@buf.fill(default)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
11
39
|
module Util
|
12
40
|
include ExceptionHandler
|
13
41
|
|
14
|
-
|
42
|
+
# hack for quicker development / testing environment #2774
|
43
|
+
PAUSE_TIME = $stdout.tty? ? 0.1 : 0.5
|
44
|
+
|
45
|
+
# Wait for the orblock to be true or the deadline passed.
|
46
|
+
def wait_for(deadline, &condblock)
|
47
|
+
remaining = deadline - ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
48
|
+
while remaining > PAUSE_TIME
|
49
|
+
return if condblock.call
|
50
|
+
sleep PAUSE_TIME
|
51
|
+
remaining = deadline - ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
52
|
+
end
|
53
|
+
end
|
15
54
|
|
16
55
|
def watchdog(last_words)
|
17
56
|
yield
|
18
57
|
rescue Exception => ex
|
19
|
-
handle_exception(ex, {
|
58
|
+
handle_exception(ex, {context: last_words})
|
20
59
|
raise ex
|
21
60
|
end
|
22
61
|
|
23
62
|
def safe_thread(name, &block)
|
24
63
|
Thread.new do
|
64
|
+
Thread.current.name = name
|
25
65
|
watchdog(name, &block)
|
26
66
|
end
|
27
67
|
end
|
@@ -34,8 +74,12 @@ module Sidekiq
|
|
34
74
|
Sidekiq.redis(&block)
|
35
75
|
end
|
36
76
|
|
77
|
+
def tid
|
78
|
+
Thread.current["sidekiq_tid"] ||= (Thread.current.object_id ^ ::Process.pid).to_s(36)
|
79
|
+
end
|
80
|
+
|
37
81
|
def hostname
|
38
|
-
ENV[
|
82
|
+
ENV["DYNO"] || Socket.gethostname
|
39
83
|
end
|
40
84
|
|
41
85
|
def process_nonce
|
@@ -43,18 +87,20 @@ module Sidekiq
|
|
43
87
|
end
|
44
88
|
|
45
89
|
def identity
|
46
|
-
@@identity ||= "#{hostname}:#{
|
90
|
+
@@identity ||= "#{hostname}:#{::Process.pid}:#{process_nonce}"
|
47
91
|
end
|
48
92
|
|
49
|
-
def fire_event(event,
|
93
|
+
def fire_event(event, options = {})
|
94
|
+
reverse = options[:reverse]
|
95
|
+
reraise = options[:reraise]
|
96
|
+
|
50
97
|
arr = Sidekiq.options[:lifecycle_events][event]
|
51
98
|
arr.reverse! if reverse
|
52
99
|
arr.each do |block|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
end
|
100
|
+
block.call
|
101
|
+
rescue => ex
|
102
|
+
handle_exception(ex, {context: "Exception during Sidekiq lifecycle event.", event: event})
|
103
|
+
raise ex if reraise
|
58
104
|
end
|
59
105
|
arr.clear
|
60
106
|
end
|
data/lib/sidekiq/version.rb
CHANGED
data/lib/sidekiq/web/action.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Sidekiq
|
4
4
|
class WebAction
|
5
|
-
RACK_SESSION =
|
5
|
+
RACK_SESSION = "rack.session"
|
6
6
|
|
7
7
|
attr_accessor :env, :block, :type
|
8
8
|
|
@@ -15,18 +15,18 @@ module Sidekiq
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def halt(res)
|
18
|
-
throw :halt, res
|
18
|
+
throw :halt, [res, {"Content-Type" => "text/plain"}, [res.to_s]]
|
19
19
|
end
|
20
20
|
|
21
21
|
def redirect(location)
|
22
|
-
throw :halt, [302, {
|
22
|
+
throw :halt, [302, {"Location" => "#{request.base_url}#{location}"}, []]
|
23
23
|
end
|
24
24
|
|
25
25
|
def params
|
26
|
-
indifferent_hash = Hash.new {|hash,key| hash[key.to_s] if Symbol === key }
|
26
|
+
indifferent_hash = Hash.new { |hash, key| hash[key.to_s] if Symbol === key }
|
27
27
|
|
28
28
|
indifferent_hash.merge! request.params
|
29
|
-
route_params.each {|k,v| indifferent_hash[k.to_s] = v }
|
29
|
+
route_params.each { |k, v| indifferent_hash[k.to_s] = v }
|
30
30
|
|
31
31
|
indifferent_hash
|
32
32
|
end
|
@@ -39,15 +39,15 @@ module Sidekiq
|
|
39
39
|
env[RACK_SESSION]
|
40
40
|
end
|
41
41
|
|
42
|
-
def content_type(type)
|
43
|
-
@type = type
|
44
|
-
end
|
45
|
-
|
46
42
|
def erb(content, options = {})
|
47
|
-
if content.
|
43
|
+
if content.is_a? Symbol
|
48
44
|
unless respond_to?(:"_erb_#{content}")
|
49
45
|
src = ERB.new(File.read("#{Web.settings.views}/#{content}.erb")).src
|
50
|
-
WebAction.class_eval
|
46
|
+
WebAction.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
47
|
+
def _erb_#{content}
|
48
|
+
#{src}
|
49
|
+
end
|
50
|
+
RUBY
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
@@ -68,22 +68,22 @@ module Sidekiq
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def json(payload)
|
71
|
-
[200, {
|
71
|
+
[200, {"Content-Type" => "application/json", "Cache-Control" => "private, no-store"}, [Sidekiq.dump_json(payload)]]
|
72
72
|
end
|
73
73
|
|
74
74
|
def initialize(env, block)
|
75
75
|
@_erb = false
|
76
76
|
@env = env
|
77
77
|
@block = block
|
78
|
-
|
78
|
+
@files ||= {}
|
79
79
|
end
|
80
80
|
|
81
81
|
private
|
82
82
|
|
83
83
|
def _erb(file, locals)
|
84
|
-
locals
|
84
|
+
locals&.each { |k, v| define_singleton_method(k) { v } unless singleton_methods.include? k }
|
85
85
|
|
86
|
-
if file.
|
86
|
+
if file.is_a?(String)
|
87
87
|
ERB.new(file).result(binding)
|
88
88
|
else
|
89
89
|
send(:"_erb_#{file}")
|