sidekiq 2.15.1 → 4.2.10
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 +7 -0
- data/.github/contributing.md +32 -0
- data/.github/issue_template.md +9 -0
- data/.gitignore +1 -0
- data/.travis.yml +16 -17
- data/3.0-Upgrade.md +70 -0
- data/4.0-Upgrade.md +53 -0
- data/COMM-LICENSE +56 -44
- data/Changes.md +644 -1
- data/Ent-Changes.md +173 -0
- data/Gemfile +27 -0
- data/LICENSE +1 -1
- data/Pro-2.0-Upgrade.md +138 -0
- data/Pro-3.0-Upgrade.md +44 -0
- data/Pro-Changes.md +457 -3
- data/README.md +46 -29
- data/Rakefile +6 -3
- data/bin/sidekiq +4 -0
- data/bin/sidekiqctl +41 -20
- data/bin/sidekiqload +154 -0
- data/code_of_conduct.md +50 -0
- data/lib/generators/sidekiq/templates/worker.rb.erb +9 -0
- data/lib/generators/sidekiq/templates/worker_spec.rb.erb +6 -0
- data/lib/generators/sidekiq/templates/worker_test.rb.erb +8 -0
- data/lib/generators/sidekiq/worker_generator.rb +49 -0
- data/lib/sidekiq.rb +141 -29
- data/lib/sidekiq/api.rb +540 -106
- data/lib/sidekiq/cli.rb +131 -71
- data/lib/sidekiq/client.rb +168 -96
- data/lib/sidekiq/core_ext.rb +36 -8
- data/lib/sidekiq/exception_handler.rb +20 -28
- data/lib/sidekiq/extensions/action_mailer.rb +25 -5
- data/lib/sidekiq/extensions/active_record.rb +8 -4
- data/lib/sidekiq/extensions/class_methods.rb +9 -5
- data/lib/sidekiq/extensions/generic_proxy.rb +1 -0
- data/lib/sidekiq/fetch.rb +45 -101
- data/lib/sidekiq/launcher.rb +144 -30
- data/lib/sidekiq/logging.rb +69 -12
- data/lib/sidekiq/manager.rb +90 -140
- data/lib/sidekiq/middleware/chain.rb +18 -5
- data/lib/sidekiq/middleware/i18n.rb +9 -2
- data/lib/sidekiq/middleware/server/active_record.rb +1 -1
- data/lib/sidekiq/middleware/server/logging.rb +11 -11
- data/lib/sidekiq/middleware/server/retry_jobs.rb +98 -44
- data/lib/sidekiq/paginator.rb +20 -8
- data/lib/sidekiq/processor.rb +157 -96
- data/lib/sidekiq/rails.rb +109 -5
- data/lib/sidekiq/redis_connection.rb +70 -24
- data/lib/sidekiq/scheduled.rb +122 -50
- data/lib/sidekiq/testing.rb +171 -31
- data/lib/sidekiq/testing/inline.rb +1 -0
- data/lib/sidekiq/util.rb +31 -5
- data/lib/sidekiq/version.rb +2 -1
- data/lib/sidekiq/web.rb +136 -263
- data/lib/sidekiq/web/action.rb +93 -0
- data/lib/sidekiq/web/application.rb +336 -0
- data/lib/sidekiq/web/helpers.rb +278 -0
- data/lib/sidekiq/web/router.rb +100 -0
- data/lib/sidekiq/worker.rb +40 -7
- data/sidekiq.gemspec +18 -14
- data/web/assets/images/favicon.ico +0 -0
- data/web/assets/images/{status-sd8051fd480.png → status.png} +0 -0
- data/web/assets/javascripts/application.js +67 -19
- data/web/assets/javascripts/dashboard.js +138 -29
- data/web/assets/stylesheets/application.css +267 -406
- data/web/assets/stylesheets/bootstrap.css +4 -8
- data/web/locales/cs.yml +78 -0
- data/web/locales/da.yml +9 -1
- data/web/locales/de.yml +18 -9
- data/web/locales/el.yml +68 -0
- data/web/locales/en.yml +19 -4
- data/web/locales/es.yml +10 -1
- data/web/locales/fa.yml +79 -0
- data/web/locales/fr.yml +50 -32
- data/web/locales/hi.yml +75 -0
- data/web/locales/it.yml +27 -18
- data/web/locales/ja.yml +27 -12
- data/web/locales/ko.yml +8 -3
- data/web/locales/{no.yml → nb.yml} +19 -5
- data/web/locales/nl.yml +8 -3
- data/web/locales/pl.yml +0 -1
- data/web/locales/pt-br.yml +11 -4
- data/web/locales/pt.yml +8 -1
- data/web/locales/ru.yml +39 -21
- data/web/locales/sv.yml +68 -0
- data/web/locales/ta.yml +75 -0
- data/web/locales/uk.yml +76 -0
- data/web/locales/zh-cn.yml +68 -0
- data/web/locales/zh-tw.yml +68 -0
- data/web/views/_footer.erb +17 -0
- data/web/views/_job_info.erb +72 -60
- data/web/views/_nav.erb +58 -25
- data/web/views/_paging.erb +5 -5
- data/web/views/_poll_link.erb +7 -0
- data/web/views/_summary.erb +20 -14
- data/web/views/busy.erb +94 -0
- data/web/views/dashboard.erb +34 -21
- data/web/views/dead.erb +34 -0
- data/web/views/layout.erb +8 -30
- data/web/views/morgue.erb +75 -0
- data/web/views/queue.erb +37 -30
- data/web/views/queues.erb +26 -20
- data/web/views/retries.erb +60 -47
- data/web/views/retry.erb +23 -19
- data/web/views/scheduled.erb +39 -35
- data/web/views/scheduled_job_info.erb +2 -1
- metadata +152 -195
- data/Contributing.md +0 -29
- data/config.ru +0 -18
- data/lib/sidekiq/actor.rb +0 -7
- data/lib/sidekiq/capistrano.rb +0 -54
- data/lib/sidekiq/yaml_patch.rb +0 -21
- data/test/config.yml +0 -11
- data/test/env_based_config.yml +0 -11
- data/test/fake_env.rb +0 -0
- data/test/helper.rb +0 -42
- data/test/test_api.rb +0 -341
- data/test/test_cli.rb +0 -326
- data/test/test_client.rb +0 -211
- data/test/test_exception_handler.rb +0 -124
- data/test/test_extensions.rb +0 -105
- data/test/test_fetch.rb +0 -44
- data/test/test_manager.rb +0 -83
- data/test/test_middleware.rb +0 -135
- data/test/test_processor.rb +0 -160
- data/test/test_redis_connection.rb +0 -97
- data/test/test_retry.rb +0 -306
- data/test/test_scheduled.rb +0 -86
- data/test/test_scheduling.rb +0 -47
- data/test/test_sidekiq.rb +0 -37
- data/test/test_testing.rb +0 -82
- data/test/test_testing_fake.rb +0 -265
- data/test/test_testing_inline.rb +0 -92
- data/test/test_util.rb +0 -18
- data/test/test_web.rb +0 -372
- data/web/assets/images/bootstrap/glyphicons-halflings-white.png +0 -0
- data/web/assets/images/bootstrap/glyphicons-halflings.png +0 -0
- data/web/assets/images/status/active.png +0 -0
- data/web/assets/images/status/idle.png +0 -0
- data/web/assets/javascripts/locales/README.md +0 -27
- data/web/assets/javascripts/locales/jquery.timeago.ar.js +0 -96
- data/web/assets/javascripts/locales/jquery.timeago.bg.js +0 -18
- data/web/assets/javascripts/locales/jquery.timeago.bs.js +0 -49
- data/web/assets/javascripts/locales/jquery.timeago.ca.js +0 -18
- data/web/assets/javascripts/locales/jquery.timeago.cy.js +0 -20
- data/web/assets/javascripts/locales/jquery.timeago.cz.js +0 -18
- data/web/assets/javascripts/locales/jquery.timeago.da.js +0 -18
- data/web/assets/javascripts/locales/jquery.timeago.de.js +0 -18
- data/web/assets/javascripts/locales/jquery.timeago.el.js +0 -18
- data/web/assets/javascripts/locales/jquery.timeago.en-short.js +0 -20
- data/web/assets/javascripts/locales/jquery.timeago.en.js +0 -20
- data/web/assets/javascripts/locales/jquery.timeago.es.js +0 -18
- data/web/assets/javascripts/locales/jquery.timeago.et.js +0 -18
- data/web/assets/javascripts/locales/jquery.timeago.fa.js +0 -22
- data/web/assets/javascripts/locales/jquery.timeago.fi.js +0 -28
- data/web/assets/javascripts/locales/jquery.timeago.fr-short.js +0 -16
- data/web/assets/javascripts/locales/jquery.timeago.fr.js +0 -17
- data/web/assets/javascripts/locales/jquery.timeago.he.js +0 -18
- data/web/assets/javascripts/locales/jquery.timeago.hr.js +0 -49
- data/web/assets/javascripts/locales/jquery.timeago.hu.js +0 -18
- data/web/assets/javascripts/locales/jquery.timeago.hy.js +0 -18
- data/web/assets/javascripts/locales/jquery.timeago.id.js +0 -18
- data/web/assets/javascripts/locales/jquery.timeago.it.js +0 -16
- data/web/assets/javascripts/locales/jquery.timeago.ja.js +0 -19
- data/web/assets/javascripts/locales/jquery.timeago.ko.js +0 -17
- data/web/assets/javascripts/locales/jquery.timeago.lt.js +0 -20
- data/web/assets/javascripts/locales/jquery.timeago.mk.js +0 -20
- data/web/assets/javascripts/locales/jquery.timeago.nl.js +0 -20
- data/web/assets/javascripts/locales/jquery.timeago.no.js +0 -18
- data/web/assets/javascripts/locales/jquery.timeago.pl.js +0 -31
- data/web/assets/javascripts/locales/jquery.timeago.pt-br.js +0 -16
- data/web/assets/javascripts/locales/jquery.timeago.pt.js +0 -16
- data/web/assets/javascripts/locales/jquery.timeago.ro.js +0 -18
- data/web/assets/javascripts/locales/jquery.timeago.rs.js +0 -49
- data/web/assets/javascripts/locales/jquery.timeago.ru.js +0 -34
- data/web/assets/javascripts/locales/jquery.timeago.sk.js +0 -18
- data/web/assets/javascripts/locales/jquery.timeago.sl.js +0 -44
- data/web/assets/javascripts/locales/jquery.timeago.sv.js +0 -18
- data/web/assets/javascripts/locales/jquery.timeago.th.js +0 -20
- data/web/assets/javascripts/locales/jquery.timeago.tr.js +0 -16
- data/web/assets/javascripts/locales/jquery.timeago.uk.js +0 -34
- data/web/assets/javascripts/locales/jquery.timeago.uz.js +0 -19
- data/web/assets/javascripts/locales/jquery.timeago.zh-CN.js +0 -20
- data/web/assets/javascripts/locales/jquery.timeago.zh-TW.js +0 -20
- data/web/views/_poll.erb +0 -14
- data/web/views/_workers.erb +0 -29
- data/web/views/index.erb +0 -16
data/lib/sidekiq/core_ext.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
begin
|
2
3
|
require 'active_support/core_ext/class/attribute'
|
3
4
|
rescue LoadError
|
@@ -6,7 +7,6 @@ rescue LoadError
|
|
6
7
|
# Class#class_attribute helper.
|
7
8
|
class Class
|
8
9
|
def class_attribute(*attrs)
|
9
|
-
instance_reader = true
|
10
10
|
instance_writer = true
|
11
11
|
|
12
12
|
attrs.each do |name|
|
@@ -29,14 +29,12 @@ rescue LoadError
|
|
29
29
|
val
|
30
30
|
end
|
31
31
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
32
|
+
def #{name}
|
33
|
+
defined?(@#{name}) ? @#{name} : self.class.#{name}
|
34
|
+
end
|
36
35
|
|
37
|
-
|
38
|
-
|
39
|
-
end
|
36
|
+
def #{name}?
|
37
|
+
!!#{name}
|
40
38
|
end
|
41
39
|
RUBY
|
42
40
|
|
@@ -53,6 +51,7 @@ end
|
|
53
51
|
|
54
52
|
begin
|
55
53
|
require 'active_support/core_ext/hash/keys'
|
54
|
+
require 'active_support/core_ext/hash/deep_merge'
|
56
55
|
rescue LoadError
|
57
56
|
class Hash
|
58
57
|
def stringify_keys
|
@@ -68,6 +67,22 @@ rescue LoadError
|
|
68
67
|
end
|
69
68
|
self
|
70
69
|
end if !{}.respond_to?(:symbolize_keys)
|
70
|
+
|
71
|
+
def deep_merge(other_hash, &block)
|
72
|
+
dup.deep_merge!(other_hash, &block)
|
73
|
+
end if !{}.respond_to?(:deep_merge)
|
74
|
+
|
75
|
+
def deep_merge!(other_hash, &block)
|
76
|
+
other_hash.each_pair do |k,v|
|
77
|
+
tv = self[k]
|
78
|
+
if tv.is_a?(Hash) && v.is_a?(Hash)
|
79
|
+
self[k] = tv.deep_merge(v, &block)
|
80
|
+
else
|
81
|
+
self[k] = block && tv ? block.call(k, tv, v) : v
|
82
|
+
end
|
83
|
+
end
|
84
|
+
self
|
85
|
+
end if !{}.respond_to?(:deep_merge!)
|
71
86
|
end
|
72
87
|
end
|
73
88
|
|
@@ -89,3 +104,16 @@ rescue LoadError
|
|
89
104
|
end
|
90
105
|
|
91
106
|
|
107
|
+
begin
|
108
|
+
require 'active_support/core_ext/kernel/reporting'
|
109
|
+
rescue LoadError
|
110
|
+
module Kernel
|
111
|
+
module_function
|
112
|
+
def silence_warnings
|
113
|
+
old_verbose, $VERBOSE = $VERBOSE, nil
|
114
|
+
yield
|
115
|
+
ensure
|
116
|
+
$VERBOSE = old_verbose
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -1,39 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'sidekiq'
|
3
|
+
|
1
4
|
module Sidekiq
|
2
5
|
module ExceptionHandler
|
3
6
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
# middleware like BugSnag does:
|
11
|
-
# https://github.com/bugsnag/bugsnag-ruby/blob/master/lib/bugsnag/sidekiq.rb
|
12
|
-
send_to_airbrake(ctxHash, ex) if defined?(::Airbrake)
|
13
|
-
send_to_honeybadger(ctxHash, ex) if defined?(::Honeybadger)
|
14
|
-
send_to_exceptional(ctxHash, ex) if defined?(::Exceptional)
|
15
|
-
send_to_exception_notifier(ctxHash, ex) if defined?(::ExceptionNotifier)
|
16
|
-
end
|
17
|
-
|
18
|
-
private
|
19
|
-
|
20
|
-
def send_to_airbrake(hash, ex)
|
21
|
-
::Airbrake.notify_or_ignore(ex, :parameters => hash)
|
22
|
-
end
|
7
|
+
class Logger
|
8
|
+
def call(ex, ctxHash)
|
9
|
+
Sidekiq.logger.warn(Sidekiq.dump_json(ctxHash)) if !ctxHash.empty?
|
10
|
+
Sidekiq.logger.warn "#{ex.class.name}: #{ex.message}"
|
11
|
+
Sidekiq.logger.warn ex.backtrace.join("\n") unless ex.backtrace.nil?
|
12
|
+
end
|
23
13
|
|
24
|
-
|
25
|
-
|
14
|
+
# Set up default handler which just logs the error
|
15
|
+
Sidekiq.error_handlers << Sidekiq::ExceptionHandler::Logger.new
|
26
16
|
end
|
27
17
|
|
28
|
-
def
|
29
|
-
|
30
|
-
|
31
|
-
|
18
|
+
def handle_exception(ex, ctxHash={})
|
19
|
+
Sidekiq.error_handlers.each do |handler|
|
20
|
+
begin
|
21
|
+
handler.call(ex, ctxHash)
|
22
|
+
rescue => ex
|
23
|
+
Sidekiq.logger.error "!!! ERROR HANDLER THREW AN ERROR !!!"
|
24
|
+
Sidekiq.logger.error ex
|
25
|
+
Sidekiq.logger.error ex.backtrace.join("\n") unless ex.backtrace.nil?
|
26
|
+
end
|
32
27
|
end
|
33
28
|
end
|
34
29
|
|
35
|
-
def send_to_exception_notifier(hash, ex)
|
36
|
-
::ExceptionNotifier.notify_exception(ex, :data => {:message => hash})
|
37
|
-
end
|
38
30
|
end
|
39
31
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'sidekiq/extensions/generic_proxy'
|
2
3
|
|
3
4
|
module Sidekiq
|
@@ -14,23 +15,42 @@ module Sidekiq
|
|
14
15
|
|
15
16
|
def perform(yml)
|
16
17
|
(target, method_name, args) = YAML.load(yml)
|
17
|
-
msg = target.
|
18
|
+
msg = target.public_send(method_name, *args)
|
18
19
|
# The email method can return nil, which causes ActionMailer to return
|
19
20
|
# an undeliverable empty message.
|
20
|
-
|
21
|
+
if msg
|
22
|
+
deliver(msg)
|
23
|
+
else
|
24
|
+
raise "#{target.name}##{method_name} returned an undeliverable mail object"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def deliver(msg)
|
31
|
+
if msg.respond_to?(:deliver_now)
|
32
|
+
# Rails 4.2/5.0
|
33
|
+
msg.deliver_now
|
34
|
+
else
|
35
|
+
# Rails 3.2/4.0/4.1
|
36
|
+
msg.deliver
|
37
|
+
end
|
21
38
|
end
|
22
39
|
end
|
23
40
|
|
24
41
|
module ActionMailer
|
25
|
-
def
|
42
|
+
def sidekiq_delay(options={})
|
26
43
|
Proxy.new(DelayedMailer, self, options)
|
27
44
|
end
|
28
|
-
def
|
45
|
+
def sidekiq_delay_for(interval, options={})
|
29
46
|
Proxy.new(DelayedMailer, self, options.merge('at' => Time.now.to_f + interval.to_f))
|
30
47
|
end
|
31
|
-
def
|
48
|
+
def sidekiq_delay_until(timestamp, options={})
|
32
49
|
Proxy.new(DelayedMailer, self, options.merge('at' => timestamp.to_f))
|
33
50
|
end
|
51
|
+
alias_method :delay, :sidekiq_delay
|
52
|
+
alias_method :delay_for, :sidekiq_delay_for
|
53
|
+
alias_method :delay_until, :sidekiq_delay_until
|
34
54
|
end
|
35
55
|
|
36
56
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'sidekiq/extensions/generic_proxy'
|
2
3
|
|
3
4
|
module Sidekiq
|
@@ -16,20 +17,23 @@ module Sidekiq
|
|
16
17
|
|
17
18
|
def perform(yml)
|
18
19
|
(target, method_name, args) = YAML.load(yml)
|
19
|
-
target.
|
20
|
+
target.__send__(method_name, *args)
|
20
21
|
end
|
21
22
|
end
|
22
23
|
|
23
24
|
module ActiveRecord
|
24
|
-
def
|
25
|
+
def sidekiq_delay(options={})
|
25
26
|
Proxy.new(DelayedModel, self, options)
|
26
27
|
end
|
27
|
-
def
|
28
|
+
def sidekiq_delay_for(interval, options={})
|
28
29
|
Proxy.new(DelayedModel, self, options.merge('at' => Time.now.to_f + interval.to_f))
|
29
30
|
end
|
30
|
-
def
|
31
|
+
def sidekiq_delay_until(timestamp, options={})
|
31
32
|
Proxy.new(DelayedModel, self, options.merge('at' => timestamp.to_f))
|
32
33
|
end
|
34
|
+
alias_method :delay, :sidekiq_delay
|
35
|
+
alias_method :delay_for, :sidekiq_delay_for
|
36
|
+
alias_method :delay_until, :sidekiq_delay_until
|
33
37
|
end
|
34
38
|
|
35
39
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'sidekiq/extensions/generic_proxy'
|
2
3
|
|
3
4
|
module Sidekiq
|
@@ -14,23 +15,26 @@ module Sidekiq
|
|
14
15
|
|
15
16
|
def perform(yml)
|
16
17
|
(target, method_name, args) = YAML.load(yml)
|
17
|
-
target.
|
18
|
+
target.__send__(method_name, *args)
|
18
19
|
end
|
19
20
|
end
|
20
21
|
|
21
22
|
module Klass
|
22
|
-
def
|
23
|
+
def sidekiq_delay(options={})
|
23
24
|
Proxy.new(DelayedClass, self, options)
|
24
25
|
end
|
25
|
-
def
|
26
|
+
def sidekiq_delay_for(interval, options={})
|
26
27
|
Proxy.new(DelayedClass, self, options.merge('at' => Time.now.to_f + interval.to_f))
|
27
28
|
end
|
28
|
-
def
|
29
|
+
def sidekiq_delay_until(timestamp, options={})
|
29
30
|
Proxy.new(DelayedClass, self, options.merge('at' => timestamp.to_f))
|
30
31
|
end
|
32
|
+
alias_method :delay, :sidekiq_delay
|
33
|
+
alias_method :delay_for, :sidekiq_delay_for
|
34
|
+
alias_method :delay_until, :sidekiq_delay_until
|
31
35
|
end
|
32
36
|
|
33
37
|
end
|
34
38
|
end
|
35
39
|
|
36
|
-
Module.
|
40
|
+
Module.__send__(:include, Sidekiq::Extensions::Klass) unless defined?(::Rails)
|
data/lib/sidekiq/fetch.rb
CHANGED
@@ -1,88 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'sidekiq'
|
2
|
-
require 'sidekiq/actor'
|
3
3
|
|
4
4
|
module Sidekiq
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
class Fetcher
|
10
|
-
include Util
|
11
|
-
include Actor
|
12
|
-
|
13
|
-
TIMEOUT = 1
|
14
|
-
|
15
|
-
def initialize(mgr, options)
|
16
|
-
@down = nil
|
17
|
-
@mgr = mgr
|
18
|
-
@strategy = Fetcher.strategy.new(options)
|
19
|
-
end
|
20
|
-
|
21
|
-
# Fetching is straightforward: the Manager makes a fetch
|
22
|
-
# request for each idle processor when Sidekiq starts and
|
23
|
-
# then issues a new fetch request every time a Processor
|
24
|
-
# finishes a message.
|
25
|
-
#
|
26
|
-
# Because we have to shut down cleanly, we can't block
|
27
|
-
# forever and we can't loop forever. Instead we reschedule
|
28
|
-
# a new fetch if the current fetch turned up nothing.
|
29
|
-
def fetch
|
30
|
-
watchdog('Fetcher#fetch died') do
|
31
|
-
return if Sidekiq::Fetcher.done?
|
32
|
-
|
33
|
-
begin
|
34
|
-
work = @strategy.retrieve_work
|
35
|
-
::Sidekiq.logger.info("Redis is online, #{Time.now.to_f - @down.to_f} sec downtime") if @down
|
36
|
-
@down = nil
|
5
|
+
class BasicFetch
|
6
|
+
# We want the fetch operation to timeout every few seconds so the thread
|
7
|
+
# can check if the process is shutting down.
|
8
|
+
TIMEOUT = 2
|
37
9
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
end
|
43
|
-
rescue => ex
|
44
|
-
handle_exception(ex)
|
45
|
-
end
|
10
|
+
UnitOfWork = Struct.new(:queue, :job) do
|
11
|
+
def acknowledge
|
12
|
+
# nothing to do
|
13
|
+
end
|
46
14
|
|
15
|
+
def queue_name
|
16
|
+
queue.sub(/.*queue:/, ''.freeze)
|
47
17
|
end
|
48
|
-
end
|
49
18
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
ex.backtrace.each do |bt|
|
54
|
-
logger.error(bt)
|
19
|
+
def requeue
|
20
|
+
Sidekiq.redis do |conn|
|
21
|
+
conn.rpush("queue:#{queue_name}", job)
|
55
22
|
end
|
56
23
|
end
|
57
|
-
@down ||= Time.now
|
58
|
-
sleep(TIMEOUT)
|
59
|
-
after(0) { fetch }
|
60
|
-
rescue Task::TerminatedError
|
61
|
-
# If redis is down when we try to shut down, all the fetch backlog
|
62
|
-
# raises these errors. Haven't been able to figure out what I'm doing wrong.
|
63
|
-
end
|
64
|
-
|
65
|
-
# Ugh. Say hello to a bloody hack.
|
66
|
-
# Can't find a clean way to get the fetcher to just stop processing
|
67
|
-
# its mailbox when shutdown starts.
|
68
|
-
def self.done!
|
69
|
-
@done = true
|
70
|
-
end
|
71
|
-
|
72
|
-
def self.done?
|
73
|
-
@done
|
74
24
|
end
|
75
25
|
|
76
|
-
def self.strategy
|
77
|
-
Sidekiq.options[:fetch] || BasicFetch
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
class BasicFetch
|
82
26
|
def initialize(options)
|
83
27
|
@strictly_ordered_queues = !!options[:strict]
|
84
28
|
@queues = options[:queues].map { |q| "queue:#{q}" }
|
85
|
-
|
29
|
+
if @strictly_ordered_queues
|
30
|
+
@queues = @queues.uniq
|
31
|
+
@queues << TIMEOUT
|
32
|
+
end
|
86
33
|
end
|
87
34
|
|
88
35
|
def retrieve_work
|
@@ -90,48 +37,45 @@ module Sidekiq
|
|
90
37
|
UnitOfWork.new(*work) if work
|
91
38
|
end
|
92
39
|
|
93
|
-
|
40
|
+
# Creating the Redis#brpop command takes into account any
|
41
|
+
# configured queue weights. By default Redis#brpop returns
|
42
|
+
# data from the first queue that has pending elements. We
|
43
|
+
# recreate the queue command each time we invoke Redis#brpop
|
44
|
+
# to honor weights and avoid queue starvation.
|
45
|
+
def queues_cmd
|
46
|
+
if @strictly_ordered_queues
|
47
|
+
@queues
|
48
|
+
else
|
49
|
+
queues = @queues.shuffle.uniq
|
50
|
+
queues << TIMEOUT
|
51
|
+
queues
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
# By leaving this as a class method, it can be pluggable and used by the Manager actor. Making it
|
57
|
+
# an instance method will make it async to the Fetcher actor
|
58
|
+
def self.bulk_requeue(inprogress, options)
|
59
|
+
return if inprogress.empty?
|
60
|
+
|
94
61
|
Sidekiq.logger.debug { "Re-queueing terminated jobs" }
|
95
62
|
jobs_to_requeue = {}
|
96
63
|
inprogress.each do |unit_of_work|
|
97
64
|
jobs_to_requeue[unit_of_work.queue_name] ||= []
|
98
|
-
jobs_to_requeue[unit_of_work.queue_name] << unit_of_work.
|
65
|
+
jobs_to_requeue[unit_of_work.queue_name] << unit_of_work.job
|
99
66
|
end
|
100
67
|
|
101
68
|
Sidekiq.redis do |conn|
|
102
|
-
|
103
|
-
|
69
|
+
conn.pipelined do
|
70
|
+
jobs_to_requeue.each do |queue, jobs|
|
71
|
+
conn.rpush("queue:#{queue}", jobs)
|
72
|
+
end
|
104
73
|
end
|
105
74
|
end
|
106
|
-
Sidekiq.logger.info("Pushed #{inprogress.size}
|
75
|
+
Sidekiq.logger.info("Pushed #{inprogress.size} jobs back to Redis")
|
107
76
|
rescue => ex
|
108
77
|
Sidekiq.logger.warn("Failed to requeue #{inprogress.size} jobs: #{ex.message}")
|
109
78
|
end
|
110
79
|
|
111
|
-
UnitOfWork = Struct.new(:queue, :message) do
|
112
|
-
def acknowledge
|
113
|
-
# nothing to do
|
114
|
-
end
|
115
|
-
|
116
|
-
def queue_name
|
117
|
-
queue.gsub(/.*queue:/, '')
|
118
|
-
end
|
119
|
-
|
120
|
-
def requeue
|
121
|
-
Sidekiq.redis do |conn|
|
122
|
-
conn.rpush("queue:#{queue_name}", message)
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
# Creating the Redis#blpop command takes into account any
|
128
|
-
# configured queue weights. By default Redis#blpop returns
|
129
|
-
# data from the first queue that has pending elements. We
|
130
|
-
# recreate the queue command each time we invoke Redis#blpop
|
131
|
-
# to honor weights and avoid queue starvation.
|
132
|
-
def queues_cmd
|
133
|
-
queues = @strictly_ordered_queues ? @unique_queues.dup : @queues.shuffle.uniq
|
134
|
-
queues << Sidekiq::Fetcher::TIMEOUT
|
135
|
-
end
|
136
80
|
end
|
137
81
|
end
|