sidekiq 5.2.9 → 7.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (149) hide show
  1. checksums.yaml +4 -4
  2. data/Changes.md +547 -8
  3. data/LICENSE.txt +9 -0
  4. data/README.md +47 -50
  5. data/bin/sidekiq +22 -3
  6. data/bin/sidekiqload +213 -115
  7. data/bin/sidekiqmon +11 -0
  8. data/lib/generators/sidekiq/job_generator.rb +57 -0
  9. data/lib/generators/sidekiq/templates/{worker.rb.erb → job.rb.erb} +2 -2
  10. data/lib/generators/sidekiq/templates/{worker_spec.rb.erb → job_spec.rb.erb} +1 -1
  11. data/lib/generators/sidekiq/templates/{worker_test.rb.erb → job_test.rb.erb} +1 -1
  12. data/lib/sidekiq/api.rb +558 -353
  13. data/lib/sidekiq/capsule.rb +127 -0
  14. data/lib/sidekiq/cli.rb +204 -226
  15. data/lib/sidekiq/client.rb +124 -101
  16. data/lib/sidekiq/component.rb +68 -0
  17. data/lib/sidekiq/config.rb +278 -0
  18. data/lib/sidekiq/deploy.rb +62 -0
  19. data/lib/sidekiq/embedded.rb +61 -0
  20. data/lib/sidekiq/fetch.rb +49 -42
  21. data/lib/sidekiq/job.rb +374 -0
  22. data/lib/sidekiq/job_logger.rb +33 -7
  23. data/lib/sidekiq/job_retry.rb +145 -107
  24. data/lib/sidekiq/job_util.rb +107 -0
  25. data/lib/sidekiq/launcher.rb +203 -105
  26. data/lib/sidekiq/logger.rb +131 -0
  27. data/lib/sidekiq/manager.rb +43 -46
  28. data/lib/sidekiq/metrics/query.rb +153 -0
  29. data/lib/sidekiq/metrics/shared.rb +95 -0
  30. data/lib/sidekiq/metrics/tracking.rb +136 -0
  31. data/lib/sidekiq/middleware/chain.rb +113 -56
  32. data/lib/sidekiq/middleware/current_attributes.rb +95 -0
  33. data/lib/sidekiq/middleware/i18n.rb +7 -7
  34. data/lib/sidekiq/middleware/modules.rb +21 -0
  35. data/lib/sidekiq/monitor.rb +146 -0
  36. data/lib/sidekiq/paginator.rb +28 -16
  37. data/lib/sidekiq/processor.rb +122 -120
  38. data/lib/sidekiq/rails.rb +53 -38
  39. data/lib/sidekiq/redis_client_adapter.rb +96 -0
  40. data/lib/sidekiq/redis_connection.rb +38 -107
  41. data/lib/sidekiq/ring_buffer.rb +29 -0
  42. data/lib/sidekiq/scheduled.rb +111 -49
  43. data/lib/sidekiq/sd_notify.rb +149 -0
  44. data/lib/sidekiq/systemd.rb +24 -0
  45. data/lib/sidekiq/testing/inline.rb +6 -5
  46. data/lib/sidekiq/testing.rb +66 -84
  47. data/lib/sidekiq/transaction_aware_client.rb +44 -0
  48. data/lib/sidekiq/version.rb +3 -1
  49. data/lib/sidekiq/web/action.rb +15 -11
  50. data/lib/sidekiq/web/application.rb +123 -79
  51. data/lib/sidekiq/web/csrf_protection.rb +180 -0
  52. data/lib/sidekiq/web/helpers.rb +137 -106
  53. data/lib/sidekiq/web/router.rb +23 -19
  54. data/lib/sidekiq/web.rb +68 -107
  55. data/lib/sidekiq/worker_compatibility_alias.rb +13 -0
  56. data/lib/sidekiq.rb +92 -182
  57. data/sidekiq.gemspec +25 -16
  58. data/web/assets/images/apple-touch-icon.png +0 -0
  59. data/web/assets/javascripts/application.js +131 -61
  60. data/web/assets/javascripts/base-charts.js +106 -0
  61. data/web/assets/javascripts/chart.min.js +13 -0
  62. data/web/assets/javascripts/chartjs-plugin-annotation.min.js +7 -0
  63. data/web/assets/javascripts/dashboard-charts.js +168 -0
  64. data/web/assets/javascripts/dashboard.js +36 -292
  65. data/web/assets/javascripts/metrics.js +264 -0
  66. data/web/assets/stylesheets/application-dark.css +147 -0
  67. data/web/assets/stylesheets/application-rtl.css +2 -95
  68. data/web/assets/stylesheets/application.css +102 -522
  69. data/web/locales/ar.yml +71 -65
  70. data/web/locales/cs.yml +62 -62
  71. data/web/locales/da.yml +60 -53
  72. data/web/locales/de.yml +65 -53
  73. data/web/locales/el.yml +43 -24
  74. data/web/locales/en.yml +84 -66
  75. data/web/locales/es.yml +70 -54
  76. data/web/locales/fa.yml +65 -65
  77. data/web/locales/fr.yml +83 -62
  78. data/web/locales/gd.yml +99 -0
  79. data/web/locales/he.yml +65 -64
  80. data/web/locales/hi.yml +59 -59
  81. data/web/locales/it.yml +53 -53
  82. data/web/locales/ja.yml +75 -64
  83. data/web/locales/ko.yml +52 -52
  84. data/web/locales/lt.yml +83 -0
  85. data/web/locales/nb.yml +61 -61
  86. data/web/locales/nl.yml +52 -52
  87. data/web/locales/pl.yml +45 -45
  88. data/web/locales/pt-br.yml +83 -55
  89. data/web/locales/pt.yml +51 -51
  90. data/web/locales/ru.yml +68 -63
  91. data/web/locales/sv.yml +53 -53
  92. data/web/locales/ta.yml +60 -60
  93. data/web/locales/uk.yml +62 -61
  94. data/web/locales/ur.yml +64 -64
  95. data/web/locales/vi.yml +83 -0
  96. data/web/locales/zh-cn.yml +43 -16
  97. data/web/locales/zh-tw.yml +42 -8
  98. data/web/views/_footer.erb +6 -3
  99. data/web/views/_job_info.erb +21 -4
  100. data/web/views/_metrics_period_select.erb +12 -0
  101. data/web/views/_nav.erb +1 -1
  102. data/web/views/_paging.erb +2 -0
  103. data/web/views/_poll_link.erb +3 -6
  104. data/web/views/_summary.erb +7 -7
  105. data/web/views/busy.erb +75 -25
  106. data/web/views/dashboard.erb +58 -18
  107. data/web/views/dead.erb +3 -3
  108. data/web/views/layout.erb +3 -1
  109. data/web/views/metrics.erb +82 -0
  110. data/web/views/metrics_for_job.erb +68 -0
  111. data/web/views/morgue.erb +14 -15
  112. data/web/views/queue.erb +33 -24
  113. data/web/views/queues.erb +13 -3
  114. data/web/views/retries.erb +16 -17
  115. data/web/views/retry.erb +3 -3
  116. data/web/views/scheduled.erb +17 -15
  117. metadata +71 -72
  118. data/.circleci/config.yml +0 -61
  119. data/.github/contributing.md +0 -32
  120. data/.github/issue_template.md +0 -11
  121. data/.gitignore +0 -15
  122. data/.travis.yml +0 -11
  123. data/3.0-Upgrade.md +0 -70
  124. data/4.0-Upgrade.md +0 -53
  125. data/5.0-Upgrade.md +0 -56
  126. data/COMM-LICENSE +0 -97
  127. data/Ent-Changes.md +0 -238
  128. data/Gemfile +0 -23
  129. data/LICENSE +0 -9
  130. data/Pro-2.0-Upgrade.md +0 -138
  131. data/Pro-3.0-Upgrade.md +0 -44
  132. data/Pro-4.0-Upgrade.md +0 -35
  133. data/Pro-Changes.md +0 -759
  134. data/Rakefile +0 -9
  135. data/bin/sidekiqctl +0 -20
  136. data/code_of_conduct.md +0 -50
  137. data/lib/generators/sidekiq/worker_generator.rb +0 -49
  138. data/lib/sidekiq/core_ext.rb +0 -1
  139. data/lib/sidekiq/ctl.rb +0 -221
  140. data/lib/sidekiq/delay.rb +0 -42
  141. data/lib/sidekiq/exception_handler.rb +0 -29
  142. data/lib/sidekiq/extensions/action_mailer.rb +0 -57
  143. data/lib/sidekiq/extensions/active_record.rb +0 -40
  144. data/lib/sidekiq/extensions/class_methods.rb +0 -40
  145. data/lib/sidekiq/extensions/generic_proxy.rb +0 -31
  146. data/lib/sidekiq/logging.rb +0 -122
  147. data/lib/sidekiq/middleware/server/active_record.rb +0 -23
  148. data/lib/sidekiq/util.rb +0 -66
  149. data/lib/sidekiq/worker.rb +0 -220
data/lib/sidekiq/web.rb CHANGED
@@ -1,20 +1,20 @@
1
1
  # frozen_string_literal: true
2
- require 'erb'
3
2
 
4
- require 'sidekiq'
5
- require 'sidekiq/api'
6
- require 'sidekiq/paginator'
7
- require 'sidekiq/web/helpers'
3
+ require "erb"
8
4
 
9
- require 'sidekiq/web/router'
10
- require 'sidekiq/web/action'
11
- require 'sidekiq/web/application'
5
+ require "sidekiq"
6
+ require "sidekiq/api"
7
+ require "sidekiq/paginator"
8
+ require "sidekiq/web/helpers"
12
9
 
13
- require 'rack/protection'
10
+ require "sidekiq/web/router"
11
+ require "sidekiq/web/action"
12
+ require "sidekiq/web/application"
13
+ require "sidekiq/web/csrf_protection"
14
14
 
15
- require 'rack/builder'
16
- require 'rack/file'
17
- require 'rack/session/cookie'
15
+ require "rack/content_length"
16
+ require "rack/builder"
17
+ require "rack/static"
18
18
 
19
19
  module Sidekiq
20
20
  class Web
@@ -25,27 +25,32 @@ module Sidekiq
25
25
  ASSETS = "#{ROOT}/assets"
26
26
 
27
27
  DEFAULT_TABS = {
28
- "Dashboard" => '',
29
- "Busy" => 'busy',
30
- "Queues" => 'queues',
31
- "Retries" => 'retries',
32
- "Scheduled" => 'scheduled',
33
- "Dead" => 'morgue',
28
+ "Dashboard" => "",
29
+ "Busy" => "busy",
30
+ "Queues" => "queues",
31
+ "Retries" => "retries",
32
+ "Scheduled" => "scheduled",
33
+ "Dead" => "morgue",
34
+ "Metrics" => "metrics"
34
35
  }
35
36
 
37
+ if Gem::Version.new(Rack::RELEASE) < Gem::Version.new("3")
38
+ CONTENT_LANGUAGE = "Content-Language"
39
+ CONTENT_SECURITY_POLICY = "Content-Security-Policy"
40
+ LOCATION = "Location"
41
+ X_CASCADE = "X-Cascade"
42
+ else
43
+ CONTENT_LANGUAGE = "content-language"
44
+ CONTENT_SECURITY_POLICY = "content-security-policy"
45
+ LOCATION = "location"
46
+ X_CASCADE = "x-cascade"
47
+ end
48
+
36
49
  class << self
37
50
  def settings
38
51
  self
39
52
  end
40
53
 
41
- def middlewares
42
- @middlewares ||= []
43
- end
44
-
45
- def use(*middleware_args, &block)
46
- middlewares << [middleware_args, block]
47
- end
48
-
49
54
  def default_tabs
50
55
  DEFAULT_TABS
51
56
  end
@@ -55,6 +60,10 @@ module Sidekiq
55
60
  end
56
61
  alias_method :tabs, :custom_tabs
57
62
 
63
+ def custom_job_info_rows
64
+ @custom_job_info_rows ||= []
65
+ end
66
+
58
67
  def locales
59
68
  @locales ||= LOCALES
60
69
  end
@@ -64,39 +73,44 @@ module Sidekiq
64
73
  end
65
74
 
66
75
  def enable(*opts)
67
- opts.each {|key| set(key, true) }
76
+ opts.each { |key| set(key, true) }
68
77
  end
69
78
 
70
79
  def disable(*opts)
71
- opts.each {|key| set(key, false) }
80
+ opts.each { |key| set(key, false) }
81
+ end
82
+
83
+ def middlewares
84
+ @middlewares ||= []
85
+ end
86
+
87
+ def use(*args, &block)
88
+ middlewares << [args, block]
72
89
  end
73
90
 
74
- # Helper for the Sinatra syntax: Sidekiq::Web.set(:session_secret, Rails.application.secrets...)
75
91
  def set(attribute, value)
76
92
  send(:"#{attribute}=", value)
77
93
  end
78
94
 
79
- attr_accessor :app_url, :session_secret, :redis_pool, :sessions
95
+ attr_accessor :app_url, :redis_pool
80
96
  attr_writer :locales, :views
81
97
  end
82
98
 
83
99
  def self.inherited(child)
84
- child.app_url = self.app_url
85
- child.session_secret = self.session_secret
86
- child.redis_pool = self.redis_pool
87
- child.sessions = self.sessions
100
+ child.app_url = app_url
101
+ child.redis_pool = redis_pool
88
102
  end
89
103
 
90
104
  def settings
91
105
  self.class.settings
92
106
  end
93
107
 
94
- def use(*middleware_args, &block)
95
- middlewares << [middleware_args, block]
108
+ def middlewares
109
+ @middlewares ||= self.class.middlewares
96
110
  end
97
111
 
98
- def middlewares
99
- @middlewares ||= Web.middlewares.dup
112
+ def use(*args, &block)
113
+ middlewares << [args, block]
100
114
  end
101
115
 
102
116
  def call(env)
@@ -113,81 +127,37 @@ module Sidekiq
113
127
  end
114
128
 
115
129
  def enable(*opts)
116
- opts.each {|key| set(key, true) }
130
+ opts.each { |key| set(key, true) }
117
131
  end
118
132
 
119
133
  def disable(*opts)
120
- opts.each {|key| set(key, false) }
134
+ opts.each { |key| set(key, false) }
121
135
  end
122
136
 
123
137
  def set(attribute, value)
124
138
  send(:"#{attribute}=", value)
125
139
  end
126
140
 
127
- # Default values
128
- set :sessions, true
129
-
130
- attr_writer :sessions
131
-
132
- def sessions
133
- unless instance_variable_defined?("@sessions")
134
- @sessions = self.class.sessions
135
- @sessions = @sessions.to_hash.dup if @sessions.respond_to?(:to_hash)
136
- end
137
-
138
- @sessions
139
- end
140
-
141
141
  def self.register(extension)
142
142
  extension.registered(WebApplication)
143
143
  end
144
144
 
145
145
  private
146
146
 
147
- def using?(middleware)
148
- middlewares.any? do |(m,_)|
149
- m.kind_of?(Array) && (m[0] == middleware || m[0].kind_of?(middleware))
150
- end
151
- end
152
-
153
- def build_sessions
154
- middlewares = self.middlewares
155
-
156
- unless using?(::Rack::Protection) || ENV['RACK_ENV'] == 'test'
157
- middlewares.unshift [[::Rack::Protection, { use: :authenticity_token }], nil]
158
- end
159
-
160
- s = sessions
161
- return unless s
162
-
163
- unless using? ::Rack::Session::Cookie
164
- unless secret = Web.session_secret
165
- require 'securerandom'
166
- secret = SecureRandom.hex(64)
167
- end
168
-
169
- options = { secret: secret }
170
- options = options.merge(s.to_hash) if s.respond_to? :to_hash
171
-
172
- middlewares.unshift [[::Rack::Session::Cookie, options], nil]
173
- end
174
- end
175
-
176
147
  def build
177
- build_sessions
178
-
179
- middlewares = self.middlewares
180
148
  klass = self.class
149
+ m = middlewares
181
150
 
182
- ::Rack::Builder.new do
183
- %w(stylesheets javascripts images).each do |asset_dir|
184
- map "/#{asset_dir}" do
185
- run ::Rack::File.new("#{ASSETS}/#{asset_dir}", { 'Cache-Control' => 'public, max-age=86400' })
186
- end
187
- end
188
-
189
- middlewares.each {|middleware, block| use(*middleware, &block) }
151
+ rules = []
152
+ rules = [[:all, {Rack::CACHE_CONTROL => "private, max-age=86400"}]] unless ENV["SIDEKIQ_WEB_TESTING"]
190
153
 
154
+ ::Rack::Builder.new do
155
+ use Rack::Static, urls: ["/stylesheets", "/images", "/javascripts"],
156
+ root: ASSETS,
157
+ cascade: true,
158
+ header_rules: rules
159
+ m.each { |middleware, block| use(*middleware, &block) }
160
+ use Sidekiq::Web::CsrfProtection unless $TESTING
191
161
  run WebApplication.new(klass)
192
162
  end
193
163
  end
@@ -196,18 +166,9 @@ module Sidekiq
196
166
  Sidekiq::WebApplication.helpers WebHelpers
197
167
  Sidekiq::WebApplication.helpers Sidekiq::Paginator
198
168
 
199
- Sidekiq::WebAction.class_eval "def _render\n#{ERB.new(File.read(Web::LAYOUT)).src}\nend"
200
- end
201
-
202
- if defined?(::ActionDispatch::Request::Session) &&
203
- !::ActionDispatch::Request::Session.method_defined?(:each)
204
- # mperham/sidekiq#2460
205
- # Rack apps can't reuse the Rails session store without
206
- # this monkeypatch, fixed in Rails 5.
207
- class ActionDispatch::Request::Session
208
- def each(&block)
209
- hash = self.to_hash
210
- hash.each(&block)
169
+ Sidekiq::WebAction.class_eval <<-RUBY, __FILE__, __LINE__ + 1
170
+ def _render
171
+ #{ERB.new(File.read(Web::LAYOUT)).src}
211
172
  end
212
- end
173
+ RUBY
213
174
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sidekiq
4
+ # Sidekiq::Job is a new alias for Sidekiq::Worker as of Sidekiq 6.3.0.
5
+ # Use `include Sidekiq::Job` rather than `include Sidekiq::Worker`.
6
+ #
7
+ # The term "worker" is too generic and overly confusing, used in several
8
+ # different contexts meaning different things. Many people call a Sidekiq
9
+ # process a "worker". Some people call the thread that executes jobs a
10
+ # "worker". This change brings Sidekiq closer to ActiveJob where your job
11
+ # classes extend ApplicationJob.
12
+ Worker = Job
13
+ end
data/lib/sidekiq.rb CHANGED
@@ -1,237 +1,147 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'sidekiq/version'
4
- fail "Sidekiq #{Sidekiq::VERSION} does not support Ruby versions below 2.2.2." if RUBY_PLATFORM != 'java' && Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.2.2')
3
+ require "sidekiq/version"
4
+ fail "Sidekiq #{Sidekiq::VERSION} does not support Ruby versions below 2.7.0." if RUBY_PLATFORM != "java" && Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.7.0")
5
5
 
6
- require 'sidekiq/logging'
7
- require 'sidekiq/client'
8
- require 'sidekiq/worker'
9
- require 'sidekiq/redis_connection'
10
- require 'sidekiq/delay'
6
+ begin
7
+ require "sidekiq-ent/version"
8
+ fail <<~EOM if Gem::Version.new(Sidekiq::Enterprise::VERSION).segments[0] != Sidekiq::MAJOR
11
9
 
12
- require 'json'
10
+ Sidekiq Enterprise #{Sidekiq::Enterprise::VERSION} does not work with Sidekiq #{Sidekiq::VERSION}.
11
+ Starting with Sidekiq 7, major versions are synchronized so Sidekiq Enterprise 7 works with Sidekiq 7.
12
+ Use `bundle up sidekiq-ent` to upgrade.
13
13
 
14
- module Sidekiq
15
- NAME = 'Sidekiq'
16
- LICENSE = 'See LICENSE and the LGPL-3.0 for licensing details.'
17
-
18
- DEFAULTS = {
19
- queues: [],
20
- labels: [],
21
- concurrency: 10,
22
- require: '.',
23
- environment: nil,
24
- timeout: 8,
25
- poll_interval_average: nil,
26
- average_scheduled_poll_interval: 5,
27
- error_handlers: [],
28
- death_handlers: [],
29
- lifecycle_events: {
30
- startup: [],
31
- quiet: [],
32
- shutdown: [],
33
- heartbeat: [],
34
- },
35
- dead_max_jobs: 10_000,
36
- dead_timeout_in_seconds: 180 * 24 * 60 * 60, # 6 months
37
- reloader: proc { |&block| block.call },
38
- }
39
-
40
- DEFAULT_WORKER_OPTIONS = {
41
- 'retry' => true,
42
- 'queue' => 'default'
43
- }
44
-
45
- FAKE_INFO = {
46
- "redis_version" => "9.9.9",
47
- "uptime_in_days" => "9999",
48
- "connected_clients" => "9999",
49
- "used_memory_human" => "9P",
50
- "used_memory_peak_human" => "9P"
51
- }
14
+ EOM
15
+ rescue LoadError
16
+ end
52
17
 
53
- def self.❨╯°□°❩╯︵┻━┻
54
- puts "Calm down, yo."
55
- end
18
+ begin
19
+ require "sidekiq/pro/version"
20
+ fail <<~EOM if Gem::Version.new(Sidekiq::Pro::VERSION).segments[0] != Sidekiq::MAJOR
56
21
 
57
- def self.options
58
- @options ||= DEFAULTS.dup
59
- end
22
+ Sidekiq Pro #{Sidekiq::Pro::VERSION} does not work with Sidekiq #{Sidekiq::VERSION}.
23
+ Starting with Sidekiq 7, major versions are synchronized so Sidekiq Pro 7 works with Sidekiq 7.
24
+ Use `bundle up sidekiq-pro` to upgrade.
60
25
 
61
- def self.options=(opts)
62
- @options = opts
63
- end
26
+ EOM
27
+ rescue LoadError
28
+ end
64
29
 
65
- ##
66
- # Configuration for Sidekiq server, use like:
67
- #
68
- # Sidekiq.configure_server do |config|
69
- # config.redis = { :namespace => 'myapp', :size => 25, :url => 'redis://myhost:8877/0' }
70
- # config.server_middleware do |chain|
71
- # chain.add MyServerHook
72
- # end
73
- # end
74
- def self.configure_server
75
- yield self if server?
76
- end
30
+ require "sidekiq/config"
31
+ require "sidekiq/logger"
32
+ require "sidekiq/client"
33
+ require "sidekiq/transaction_aware_client"
34
+ require "sidekiq/job"
35
+ require "sidekiq/worker_compatibility_alias"
36
+ require "sidekiq/redis_client_adapter"
77
37
 
78
- ##
79
- # Configuration for Sidekiq client, use like:
80
- #
81
- # Sidekiq.configure_client do |config|
82
- # config.redis = { :namespace => 'myapp', :size => 1, :url => 'redis://myhost:8877/0' }
83
- # end
84
- def self.configure_client
85
- yield self unless server?
38
+ require "json"
39
+
40
+ module Sidekiq
41
+ NAME = "Sidekiq"
42
+ LICENSE = "See LICENSE and the LGPL-3.0 for licensing details."
43
+
44
+ def self.❨╯°□°❩╯︵┻━┻
45
+ puts "Take a deep breath and count to ten..."
86
46
  end
87
47
 
88
48
  def self.server?
89
49
  defined?(Sidekiq::CLI)
90
50
  end
91
51
 
92
- def self.redis
93
- raise ArgumentError, "requires a block" unless block_given?
94
- redis_pool.with do |conn|
95
- retryable = true
96
- begin
97
- yield conn
98
- rescue Redis::CommandError => ex
99
- #2550 Failover can cause the server to become a replica, need
100
- # to disconnect and reopen the socket to get back to the primary.
101
- (conn.disconnect!; retryable = false; retry) if retryable && ex.message =~ /READONLY/
102
- raise
103
- end
104
- end
105
- end
106
-
107
- def self.redis_info
108
- redis do |conn|
109
- begin
110
- # admin commands can't go through redis-namespace starting
111
- # in redis-namespace 2.0
112
- if conn.respond_to?(:namespace)
113
- conn.redis.info
114
- else
115
- conn.info
116
- end
117
- rescue Redis::CommandError => ex
118
- #2850 return fake version when INFO command has (probably) been renamed
119
- raise unless ex.message =~ /unknown command/
120
- FAKE_INFO
121
- end
122
- end
52
+ def self.load_json(string)
53
+ JSON.parse(string)
123
54
  end
124
55
 
125
- def self.redis_pool
126
- @redis ||= Sidekiq::RedisConnection.create
56
+ def self.dump_json(object)
57
+ JSON.generate(object)
127
58
  end
128
59
 
129
- def self.redis=(hash)
130
- @redis = if hash.is_a?(ConnectionPool)
131
- hash
132
- else
133
- Sidekiq::RedisConnection.create(hash)
134
- end
60
+ def self.pro?
61
+ defined?(Sidekiq::Pro)
135
62
  end
136
63
 
137
- def self.client_middleware
138
- @client_chain ||= Middleware::Chain.new
139
- yield @client_chain if block_given?
140
- @client_chain
64
+ def self.ent?
65
+ defined?(Sidekiq::Enterprise)
141
66
  end
142
67
 
143
- def self.server_middleware
144
- @server_chain ||= default_server_middleware
145
- yield @server_chain if block_given?
146
- @server_chain
68
+ def self.redis_pool
69
+ (Thread.current[:sidekiq_capsule] || default_configuration).redis_pool
147
70
  end
148
71
 
149
- def self.default_server_middleware
150
- Middleware::Chain.new
72
+ def self.redis(&block)
73
+ (Thread.current[:sidekiq_capsule] || default_configuration).redis(&block)
151
74
  end
152
75
 
153
- def self.default_worker_options=(hash)
154
- # stringify
155
- @default_worker_options = default_worker_options.merge(Hash[hash.map{|k, v| [k.to_s, v]}])
156
- end
157
- def self.default_worker_options
158
- defined?(@default_worker_options) ? @default_worker_options : DEFAULT_WORKER_OPTIONS
76
+ def self.strict_args!(mode = :raise)
77
+ Sidekiq::Config::DEFAULTS[:on_complex_arguments] = mode
159
78
  end
160
79
 
161
- def self.default_retries_exhausted=(prok)
162
- logger.info { "default_retries_exhausted is deprecated, please use `config.death_handlers << -> {|job, ex| }`" }
163
- return nil unless prok
164
- death_handlers << prok
80
+ def self.default_job_options=(hash)
81
+ @default_job_options = default_job_options.merge(hash.transform_keys(&:to_s))
165
82
  end
166
83
 
167
- ##
168
- # Death handlers are called when all retries for a job have been exhausted and
169
- # the job dies. It's the notification to your application
170
- # that this job will not succeed without manual intervention.
171
- #
172
- # Sidekiq.configure_server do |config|
173
- # config.death_handlers << ->(job, ex) do
174
- # end
175
- # end
176
- def self.death_handlers
177
- options[:death_handlers]
84
+ def self.default_job_options
85
+ @default_job_options ||= {"retry" => true, "queue" => "default"}
178
86
  end
179
87
 
180
- def self.load_json(string)
181
- JSON.parse(string)
182
- end
183
- def self.dump_json(object)
184
- JSON.generate(object)
88
+ def self.default_configuration
89
+ @config ||= Sidekiq::Config.new
185
90
  end
186
91
 
187
92
  def self.logger
188
- Sidekiq::Logging.logger
93
+ default_configuration.logger
189
94
  end
190
- def self.logger=(log)
191
- Sidekiq::Logging.logger = log
95
+
96
+ def self.configure_server(&block)
97
+ (@config_blocks ||= []) << block
98
+ yield default_configuration if server?
192
99
  end
193
100
 
194
- # How frequently Redis should be checked by a random Sidekiq process for
195
- # scheduled and retriable jobs. Each individual process will take turns by
196
- # waiting some multiple of this value.
197
- #
198
- # See sidekiq/scheduled.rb for an in-depth explanation of this value
199
- def self.average_scheduled_poll_interval=(interval)
200
- self.options[:average_scheduled_poll_interval] = interval
101
+ def self.freeze!
102
+ @frozen = true
103
+ @config_blocks = nil
201
104
  end
202
105
 
203
- # Register a proc to handle any error which occurs within the Sidekiq process.
106
+ # Creates a Sidekiq::Config instance that is more tuned for embedding
107
+ # within an arbitrary Ruby process. Notably it reduces concurrency by
108
+ # default so there is less contention for CPU time with other threads.
204
109
  #
205
- # Sidekiq.configure_server do |config|
206
- # config.error_handlers << proc {|ex,ctx_hash| MyErrorService.notify(ex, ctx_hash) }
110
+ # inst = Sidekiq.configure_embed do |config|
111
+ # config.queues = %w[critical default low]
207
112
  # end
113
+ # inst.run
114
+ # sleep 10
115
+ # inst.terminate
208
116
  #
209
- # The default error handler logs errors to Sidekiq.logger.
210
- def self.error_handlers
211
- self.options[:error_handlers]
117
+ # NB: it is really easy to overload a Ruby process with threads due to the GIL.
118
+ # I do not recommend setting concurrency higher than 2-3.
119
+ #
120
+ # NB: Sidekiq only supports one instance in memory. You will get undefined behavior
121
+ # if you try to embed Sidekiq twice in the same process.
122
+ def self.configure_embed(&block)
123
+ raise "Sidekiq global configuration is frozen, you must create all embedded instances BEFORE calling `run`" if @frozen
124
+
125
+ require "sidekiq/embedded"
126
+ cfg = default_configuration
127
+ cfg.concurrency = 2
128
+ @config_blocks&.each { |block| block.call(cfg) }
129
+ yield cfg
130
+
131
+ Sidekiq::Embedded.new(cfg)
212
132
  end
213
133
 
214
- # Register a block to run at a point in the Sidekiq lifecycle.
215
- # :startup, :quiet or :shutdown are valid events.
216
- #
217
- # Sidekiq.configure_server do |config|
218
- # config.on(:shutdown) do
219
- # puts "Goodbye cruel world!"
220
- # end
221
- # end
222
- def self.on(event, &block)
223
- raise ArgumentError, "Symbols only please: #{event}" unless event.is_a?(Symbol)
224
- raise ArgumentError, "Invalid event name: #{event}" unless options[:lifecycle_events].key?(event)
225
- options[:lifecycle_events][event] << block
134
+ def self.configure_client
135
+ yield default_configuration unless server?
226
136
  end
227
137
 
228
- # We are shutting down Sidekiq but what about workers that
138
+ # We are shutting down Sidekiq but what about threads that
229
139
  # are working on some long job? This error is
230
- # raised in workers that have not finished within the hard
140
+ # raised in jobs that have not finished within the hard
231
141
  # timeout limit. This is needed to rollback db transactions,
232
142
  # otherwise Ruby's Thread#kill will commit. See #377.
233
- # DO NOT RESCUE THIS ERROR IN YOUR WORKERS
143
+ # DO NOT RESCUE THIS ERROR IN YOUR JOBS
234
144
  class Shutdown < Interrupt; end
235
145
  end
236
146
 
237
- require 'sidekiq/rails' if defined?(::Rails::Engine)
147
+ require "sidekiq/rails" if defined?(::Rails::Engine)
data/sidekiq.gemspec CHANGED
@@ -1,21 +1,30 @@
1
- require_relative 'lib/sidekiq/version'
1
+ require_relative "lib/sidekiq/version"
2
2
 
3
3
  Gem::Specification.new do |gem|
4
- gem.authors = ["Mike Perham"]
5
- gem.email = ["mperham@gmail.com"]
6
- gem.summary = "Simple, efficient background processing for Ruby"
7
- gem.description = "Simple, efficient background processing for Ruby."
8
- gem.homepage = "http://sidekiq.org"
9
- gem.license = "LGPL-3.0"
4
+ gem.authors = ["Mike Perham"]
5
+ gem.email = ["info@contribsys.com"]
6
+ gem.summary = "Simple, efficient background processing for Ruby"
7
+ gem.description = "Simple, efficient background processing for Ruby."
8
+ gem.homepage = "https://sidekiq.org"
9
+ gem.license = "LGPL-3.0"
10
10
 
11
- gem.executables = ['sidekiq', 'sidekiqctl']
12
- gem.files = `git ls-files | grep -Ev '^(test|myapp|examples)'`.split("\n")
13
- gem.name = "sidekiq"
14
- gem.version = Sidekiq::VERSION
15
- gem.required_ruby_version = ">= 2.2.2"
11
+ gem.executables = ["sidekiq", "sidekiqmon"]
12
+ gem.files = %w[sidekiq.gemspec README.md Changes.md LICENSE.txt] + `git ls-files | grep -E '^(bin|lib|web)'`.split("\n")
13
+ gem.name = "sidekiq"
14
+ gem.version = Sidekiq::VERSION
15
+ gem.required_ruby_version = ">= 2.7.0"
16
16
 
17
- gem.add_dependency 'redis', '>= 3.3.5', '< 4.2'
18
- gem.add_dependency 'connection_pool', '~> 2.2', '>= 2.2.2'
19
- gem.add_dependency 'rack', '~> 2.0'
20
- gem.add_dependency 'rack-protection', '>= 1.5.0'
17
+ gem.metadata = {
18
+ "homepage_uri" => "https://sidekiq.org",
19
+ "bug_tracker_uri" => "https://github.com/sidekiq/sidekiq/issues",
20
+ "documentation_uri" => "https://github.com/sidekiq/sidekiq/wiki",
21
+ "changelog_uri" => "https://github.com/sidekiq/sidekiq/blob/main/Changes.md",
22
+ "source_code_uri" => "https://github.com/sidekiq/sidekiq",
23
+ "rubygems_mfa_required" => "true"
24
+ }
25
+
26
+ gem.add_dependency "redis-client", ">= 0.14.0"
27
+ gem.add_dependency "connection_pool", ">= 2.3.0"
28
+ gem.add_dependency "rack", ">= 2.2.4"
29
+ gem.add_dependency "concurrent-ruby", "< 2"
21
30
  end