sidekiq 4.2.4 → 5.2.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.

Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/.github/issue_template.md +8 -1
  3. data/.gitignore +1 -0
  4. data/.travis.yml +5 -3
  5. data/5.0-Upgrade.md +56 -0
  6. data/COMM-LICENSE +1 -1
  7. data/Changes.md +151 -0
  8. data/Ent-Changes.md +77 -2
  9. data/Gemfile +10 -25
  10. data/LICENSE +1 -1
  11. data/Pro-4.0-Upgrade.md +35 -0
  12. data/Pro-Changes.md +156 -2
  13. data/README.md +9 -6
  14. data/Rakefile +1 -2
  15. data/bin/sidekiqctl +1 -1
  16. data/bin/sidekiqload +15 -33
  17. data/lib/generators/sidekiq/templates/worker_spec.rb.erb +1 -1
  18. data/lib/generators/sidekiq/templates/worker_test.rb.erb +1 -1
  19. data/lib/sidekiq/api.rb +157 -67
  20. data/lib/sidekiq/cli.rb +71 -26
  21. data/lib/sidekiq/client.rb +25 -18
  22. data/lib/sidekiq/core_ext.rb +1 -106
  23. data/lib/sidekiq/delay.rb +42 -0
  24. data/lib/sidekiq/exception_handler.rb +2 -4
  25. data/lib/sidekiq/extensions/generic_proxy.rb +7 -1
  26. data/lib/sidekiq/fetch.rb +1 -1
  27. data/lib/sidekiq/job_logger.rb +25 -0
  28. data/lib/sidekiq/job_retry.rb +241 -0
  29. data/lib/sidekiq/launcher.rb +45 -37
  30. data/lib/sidekiq/logging.rb +18 -2
  31. data/lib/sidekiq/manager.rb +3 -4
  32. data/lib/sidekiq/middleware/server/active_record.rb +10 -0
  33. data/lib/sidekiq/processor.rb +91 -34
  34. data/lib/sidekiq/rails.rb +15 -51
  35. data/lib/sidekiq/redis_connection.rb +31 -5
  36. data/lib/sidekiq/scheduled.rb +35 -8
  37. data/lib/sidekiq/testing.rb +24 -7
  38. data/lib/sidekiq/util.rb +6 -2
  39. data/lib/sidekiq/version.rb +1 -1
  40. data/lib/sidekiq/web/action.rb +2 -6
  41. data/lib/sidekiq/web/application.rb +28 -21
  42. data/lib/sidekiq/web/helpers.rb +67 -23
  43. data/lib/sidekiq/web/router.rb +14 -10
  44. data/lib/sidekiq/web.rb +4 -4
  45. data/lib/sidekiq/worker.rb +97 -14
  46. data/lib/sidekiq.rb +23 -24
  47. data/sidekiq.gemspec +7 -10
  48. data/web/assets/javascripts/application.js +0 -0
  49. data/web/assets/javascripts/dashboard.js +18 -13
  50. data/web/assets/stylesheets/application-rtl.css +246 -0
  51. data/web/assets/stylesheets/application.css +336 -4
  52. data/web/assets/stylesheets/bootstrap-rtl.min.css +9 -0
  53. data/web/assets/stylesheets/bootstrap.css +2 -2
  54. data/web/locales/ar.yml +80 -0
  55. data/web/locales/en.yml +1 -0
  56. data/web/locales/es.yml +4 -3
  57. data/web/locales/fa.yml +80 -0
  58. data/web/locales/he.yml +79 -0
  59. data/web/locales/ja.yml +5 -3
  60. data/web/locales/ur.yml +80 -0
  61. data/web/views/_footer.erb +5 -2
  62. data/web/views/_job_info.erb +1 -1
  63. data/web/views/_nav.erb +1 -1
  64. data/web/views/_paging.erb +1 -1
  65. data/web/views/busy.erb +9 -5
  66. data/web/views/dashboard.erb +3 -3
  67. data/web/views/layout.erb +11 -2
  68. data/web/views/morgue.erb +14 -10
  69. data/web/views/queue.erb +10 -10
  70. data/web/views/queues.erb +4 -2
  71. data/web/views/retries.erb +13 -11
  72. data/web/views/retry.erb +1 -1
  73. data/web/views/scheduled.erb +2 -2
  74. metadata +26 -160
  75. data/lib/sidekiq/middleware/server/logging.rb +0 -40
  76. data/lib/sidekiq/middleware/server/retry_jobs.rb +0 -205
  77. data/test/config.yml +0 -9
  78. data/test/env_based_config.yml +0 -11
  79. data/test/fake_env.rb +0 -1
  80. data/test/fixtures/en.yml +0 -2
  81. data/test/helper.rb +0 -75
  82. data/test/test_actors.rb +0 -138
  83. data/test/test_api.rb +0 -528
  84. data/test/test_cli.rb +0 -418
  85. data/test/test_client.rb +0 -266
  86. data/test/test_exception_handler.rb +0 -56
  87. data/test/test_extensions.rb +0 -127
  88. data/test/test_fetch.rb +0 -50
  89. data/test/test_launcher.rb +0 -95
  90. data/test/test_logging.rb +0 -35
  91. data/test/test_manager.rb +0 -50
  92. data/test/test_middleware.rb +0 -158
  93. data/test/test_processor.rb +0 -235
  94. data/test/test_rails.rb +0 -22
  95. data/test/test_redis_connection.rb +0 -132
  96. data/test/test_retry.rb +0 -326
  97. data/test/test_retry_exhausted.rb +0 -149
  98. data/test/test_scheduled.rb +0 -115
  99. data/test/test_scheduling.rb +0 -58
  100. data/test/test_sidekiq.rb +0 -107
  101. data/test/test_testing.rb +0 -143
  102. data/test/test_testing_fake.rb +0 -357
  103. data/test/test_testing_inline.rb +0 -94
  104. data/test/test_util.rb +0 -13
  105. data/test/test_web.rb +0 -726
  106. data/test/test_web_helpers.rb +0 -54
data/lib/sidekiq/cli.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- # encoding: utf-8
3
2
  $stdout.sync = true
4
3
 
5
4
  require 'yaml'
@@ -17,7 +16,7 @@ module Sidekiq
17
16
  include Singleton unless $TESTING
18
17
 
19
18
  PROCTITLES = [
20
- proc { 'sidekiq'.freeze },
19
+ proc { 'sidekiq' },
21
20
  proc { Sidekiq::VERSION },
22
21
  proc { |me, data| data['tag'] },
23
22
  proc { |me, data| "[#{Processor::WORKER_STATE.size} of #{data['concurrency']} busy]" },
@@ -43,6 +42,10 @@ module Sidekiq
43
42
  write_pid
44
43
  end
45
44
 
45
+ def jruby?
46
+ defined?(::JRUBY_VERSION)
47
+ end
48
+
46
49
  # Code within this method is not tested because it alters
47
50
  # global process state irreversibly. PRs which improve the
48
51
  # test coverage of Sidekiq::CLI are welcomed.
@@ -51,11 +54,17 @@ module Sidekiq
51
54
  print_banner
52
55
 
53
56
  self_read, self_write = IO.pipe
57
+ sigs = %w(INT TERM TTIN TSTP)
58
+ # USR1 and USR2 don't work on the JVM
59
+ if !jruby?
60
+ sigs << 'USR1'
61
+ sigs << 'USR2'
62
+ end
54
63
 
55
- %w(INT TERM USR1 USR2 TTIN).each do |sig|
64
+ sigs.each do |sig|
56
65
  begin
57
66
  trap sig do
58
- self_write.puts(sig)
67
+ self_write.write("#{sig}\n")
59
68
  end
60
69
  rescue ArgumentError
61
70
  puts "Signal #{sig} not supported"
@@ -71,12 +80,21 @@ module Sidekiq
71
80
  ver = Sidekiq.redis_info['redis_version']
72
81
  raise "You are using Redis v#{ver}, Sidekiq requires Redis v2.8.0 or greater" if ver < '2.8'
73
82
 
83
+ # Since the user can pass us a connection pool explicitly in the initializer, we
84
+ # need to verify the size is large enough or else Sidekiq's performance is dramatically slowed.
85
+ cursize = Sidekiq.redis_pool.size
86
+ needed = Sidekiq.options[:concurrency] + 2
87
+ raise "Your pool of #{cursize} Redis connections is too small, please increase the size to at least #{needed}" if cursize < needed
88
+
89
+ # cache process identity
90
+ Sidekiq.options[:identity] = identity
91
+
74
92
  # Touch middleware so it isn't lazy loaded by multiple threads, #3043
75
93
  Sidekiq.server_middleware
76
94
 
77
95
  # Before this point, the process is initializing with just the main thread.
78
96
  # Starting here the process will now have multiple threads running.
79
- fire_event(:startup)
97
+ fire_event(:startup, reverse: false, reraise: true)
80
98
 
81
99
  logger.debug { "Client Middleware: #{Sidekiq.client_middleware.map(&:klass).join(', ')}" }
82
100
  logger.debug { "Server Middleware: #{Sidekiq.server_middleware.map(&:klass).join(', ')}" }
@@ -122,33 +140,45 @@ module Sidekiq
122
140
  }
123
141
  end
124
142
 
125
- def handle_signal(sig)
126
- Sidekiq.logger.debug "Got #{sig} signal"
127
- case sig
128
- when 'INT'
129
- # Handle Ctrl-C in JRuby like MRI
130
- # http://jira.codehaus.org/browse/JRUBY-4637
131
- raise Interrupt
132
- when 'TERM'
133
- # Heroku sends TERM and then waits 10 seconds for process to exit.
134
- raise Interrupt
135
- when 'USR1'
143
+ SIGNAL_HANDLERS = {
144
+ # Ctrl-C in terminal
145
+ 'INT' => ->(cli) { raise Interrupt },
146
+ # TERM is the signal that Sidekiq must exit.
147
+ # Heroku sends TERM and then waits 30 seconds for process to exit.
148
+ 'TERM' => ->(cli) { raise Interrupt },
149
+ 'USR1' => ->(cli) {
136
150
  Sidekiq.logger.info "Received USR1, no longer accepting new work"
137
- launcher.quiet
138
- when 'USR2'
151
+ cli.launcher.quiet
152
+ },
153
+ 'TSTP' => ->(cli) {
154
+ Sidekiq.logger.info "Received TSTP, no longer accepting new work"
155
+ cli.launcher.quiet
156
+ },
157
+ 'USR2' => ->(cli) {
139
158
  if Sidekiq.options[:logfile]
140
159
  Sidekiq.logger.info "Received USR2, reopening log file"
141
160
  Sidekiq::Logging.reopen_logs
142
161
  end
143
- when 'TTIN'
162
+ },
163
+ 'TTIN' => ->(cli) {
144
164
  Thread.list.each do |thread|
145
- Sidekiq.logger.warn "Thread TID-#{thread.object_id.to_s(36)} #{thread['label']}"
165
+ Sidekiq.logger.warn "Thread TID-#{(thread.object_id ^ ::Process.pid).to_s(36)} #{thread['sidekiq_label']}"
146
166
  if thread.backtrace
147
167
  Sidekiq.logger.warn thread.backtrace.join("\n")
148
168
  else
149
169
  Sidekiq.logger.warn "<no backtrace available>"
150
170
  end
151
171
  end
172
+ },
173
+ }
174
+
175
+ def handle_signal(sig)
176
+ Sidekiq.logger.debug "Got #{sig} signal"
177
+ handy = SIGNAL_HANDLERS[sig]
178
+ if handy
179
+ handy.call(self)
180
+ else
181
+ Sidekiq.logger.info { "No signal handler for #{sig}" }
152
182
  end
153
183
  end
154
184
 
@@ -197,6 +227,14 @@ module Sidekiq
197
227
  @environment = cli_env || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
198
228
  end
199
229
 
230
+ def symbolize_keys_deep!(hash)
231
+ hash.keys.each do |k|
232
+ symkey = k.respond_to?(:to_sym) ? k.to_sym : k
233
+ hash[symkey] = hash.delete k
234
+ symbolize_keys_deep! hash[symkey] if hash[symkey].kind_of? Hash
235
+ end
236
+ end
237
+
200
238
  alias_method :die, :exit
201
239
  alias_method :☠, :exit
202
240
 
@@ -209,7 +247,6 @@ module Sidekiq
209
247
 
210
248
  opts[:strict] = true if opts[:strict].nil?
211
249
  opts[:concurrency] = Integer(ENV["RAILS_MAX_THREADS"]) if !opts[:concurrency] && ENV["RAILS_MAX_THREADS"]
212
- opts[:identity] = identity
213
250
 
214
251
  options.merge!(opts)
215
252
  end
@@ -226,11 +263,10 @@ module Sidekiq
226
263
  if File.directory?(options[:require])
227
264
  require 'rails'
228
265
  if ::Rails::VERSION::MAJOR < 4
229
- require 'sidekiq/rails'
230
- require File.expand_path("#{options[:require]}/config/environment.rb")
231
- ::Rails.application.eager_load!
266
+ raise "Sidekiq no longer supports this version of Rails"
232
267
  elsif ::Rails::VERSION::MAJOR == 4
233
268
  # Painful contortions, see 1791 for discussion
269
+ # No autoloading, we want to force eager load for everything.
234
270
  require File.expand_path("#{options[:require]}/config/application.rb")
235
271
  ::Rails::Application.initializer "sidekiq.eager_load" do
236
272
  ::Rails.application.config.eager_load = true
@@ -267,7 +303,7 @@ module Sidekiq
267
303
  if !File.exist?(options[:require]) ||
268
304
  (File.directory?(options[:require]) && !File.exist?("#{options[:require]}/config/application.rb"))
269
305
  logger.info "=================================================================="
270
- logger.info " Please point sidekiq to a Rails 3/4 application or a Ruby file "
306
+ logger.info " Please point sidekiq to a Rails 4/5 application or a Ruby file "
271
307
  logger.info " to load your worker classes with -r [DIR|FILE]."
272
308
  logger.info "=================================================================="
273
309
  logger.info @parser
@@ -299,6 +335,8 @@ module Sidekiq
299
335
  opts[:tag] = arg
300
336
  end
301
337
 
338
+ # this index remains here for backwards compatibility but none of the Sidekiq
339
+ # family use this value anymore. it was used by Pro's original reliable_fetch.
302
340
  o.on '-i', '--index INT', "unique process index on this machine" do |arg|
303
341
  opts[:index] = Integer(arg.match(/\d+/)[0])
304
342
  end
@@ -371,7 +409,14 @@ module Sidekiq
371
409
  opts = {}
372
410
  if File.exist?(cfile)
373
411
  opts = YAML.load(ERB.new(IO.read(cfile)).result) || opts
374
- opts = opts.merge(opts.delete(environment) || {})
412
+
413
+ if opts.respond_to? :deep_symbolize_keys!
414
+ opts.deep_symbolize_keys!
415
+ else
416
+ symbolize_keys_deep!(opts)
417
+ end
418
+
419
+ opts = opts.merge(opts.delete(environment.to_sym) || {})
375
420
  parse_queues(opts, opts.delete(:queues) || [])
376
421
  else
377
422
  # allow a non-existent config file so Sidekiq
@@ -48,9 +48,15 @@ module Sidekiq
48
48
  # queue - the named queue to use, default 'default'
49
49
  # class - the worker class to call, required
50
50
  # args - an array of simple arguments to the perform method, must be JSON-serializable
51
+ # at - timestamp to schedule the job (optional), must be Numeric (e.g. Time.now.to_f)
51
52
  # retry - whether to retry this job if it fails, default true or an integer number of retries
52
53
  # backtrace - whether to save any error backtrace, default false
53
54
  #
55
+ # If class is set to the class name, the jobs' options will be based on Sidekiq's default
56
+ # worker options. Otherwise, they will be based on the job class's options.
57
+ #
58
+ # Any options valid for a worker class's sidekiq_options are also available here.
59
+ #
54
60
  # All options must be strings, not symbols. NB: because we are serializing to JSON, all
55
61
  # symbols in 'args' will be converted to strings. Note that +backtrace: true+ can take quite a bit of
56
62
  # space in Redis; a large volume of failing jobs can start Redis swapping if you aren't careful.
@@ -71,9 +77,10 @@ module Sidekiq
71
77
  end
72
78
 
73
79
  ##
74
- # Push a large number of jobs to Redis. In practice this method is only
75
- # useful if you are pushing thousands of jobs or more. This method
76
- # cuts out the redis network round trip latency.
80
+ # Push a large number of jobs to Redis. This method cuts out the redis
81
+ # network round trip latency. I wouldn't recommend pushing more than
82
+ # 1000 per call but YMMV based on network quality, size of job args, etc.
83
+ # A large number of jobs can cause a bit of Redis command processing latency.
77
84
  #
78
85
  # Takes the same arguments as #push except that args is expected to be
79
86
  # an Array of Arrays. All other keys are duplicated for each job. Each job
@@ -113,11 +120,10 @@ module Sidekiq
113
120
  def self.via(pool)
114
121
  raise ArgumentError, "No pool given" if pool.nil?
115
122
  current_sidekiq_pool = Thread.current[:sidekiq_via_pool]
116
- raise RuntimeError, "Sidekiq::Client.via is not re-entrant" if current_sidekiq_pool && current_sidekiq_pool != pool
117
123
  Thread.current[:sidekiq_via_pool] = pool
118
124
  yield
119
125
  ensure
120
- Thread.current[:sidekiq_via_pool] = nil
126
+ Thread.current[:sidekiq_via_pool] = current_sidekiq_pool
121
127
  end
122
128
 
123
129
  class << self
@@ -158,7 +164,7 @@ module Sidekiq
158
164
  ts = (int < 1_000_000_000 ? now + int : int)
159
165
 
160
166
  item = { 'class' => klass, 'args' => args, 'at' => ts, 'queue' => queue }
161
- item.delete('at'.freeze) if ts <= now
167
+ item.delete('at') if ts <= now
162
168
 
163
169
  klass.client_push(item)
164
170
  end
@@ -184,18 +190,18 @@ module Sidekiq
184
190
 
185
191
  def atomic_push(conn, payloads)
186
192
  if payloads.first['at']
187
- conn.zadd('schedule'.freeze, payloads.map do |hash|
188
- at = hash.delete('at'.freeze).to_s
193
+ conn.zadd('schedule', payloads.map do |hash|
194
+ at = hash.delete('at').to_s
189
195
  [at, Sidekiq.dump_json(hash)]
190
196
  end)
191
197
  else
192
198
  q = payloads.first['queue']
193
199
  now = Time.now.to_f
194
200
  to_push = payloads.map do |entry|
195
- entry['enqueued_at'.freeze] = now
201
+ entry['enqueued_at'] = now
196
202
  Sidekiq.dump_json(entry)
197
203
  end
198
- conn.sadd('queues'.freeze, q)
204
+ conn.sadd('queues', q)
199
205
  conn.lpush("queue:#{q}", to_push)
200
206
  end
201
207
  end
@@ -209,24 +215,25 @@ module Sidekiq
209
215
  end
210
216
 
211
217
  def normalize_item(item)
212
- raise(ArgumentError, "Job must be a Hash with 'class' and 'args' keys: { 'class' => SomeWorker, 'args' => ['bob', 1, :foo => 'bar'] }") unless item.is_a?(Hash) && item.has_key?('class'.freeze) && item.has_key?('args'.freeze)
218
+ raise(ArgumentError, "Job must be a Hash with 'class' and 'args' keys: { 'class' => SomeWorker, 'args' => ['bob', 1, :foo => 'bar'] }") unless item.is_a?(Hash) && item.has_key?('class') && item.has_key?('args')
213
219
  raise(ArgumentError, "Job args must be an Array") unless item['args'].is_a?(Array)
214
- raise(ArgumentError, "Job class must be either a Class or String representation of the class name") unless item['class'.freeze].is_a?(Class) || item['class'.freeze].is_a?(String)
220
+ raise(ArgumentError, "Job class must be either a Class or String representation of the class name") unless item['class'].is_a?(Class) || item['class'].is_a?(String)
221
+ raise(ArgumentError, "Job 'at' must be a Numeric timestamp") if item.has_key?('at') && !item['at'].is_a?(Numeric)
215
222
  #raise(ArgumentError, "Arguments must be native JSON types, see https://github.com/mperham/sidekiq/wiki/Best-Practices") unless JSON.load(JSON.dump(item['args'])) == item['args']
216
223
 
217
- normalized_hash(item['class'.freeze])
224
+ normalized_hash(item['class'])
218
225
  .each{ |key, value| item[key] = value if item[key].nil? }
219
226
 
220
- item['class'.freeze] = item['class'.freeze].to_s
221
- item['queue'.freeze] = item['queue'.freeze].to_s
222
- item['jid'.freeze] ||= SecureRandom.hex(12)
223
- item['created_at'.freeze] ||= Time.now.to_f
227
+ item['class'] = item['class'].to_s
228
+ item['queue'] = item['queue'].to_s
229
+ item['jid'] ||= SecureRandom.hex(12)
230
+ item['created_at'] ||= Time.now.to_f
224
231
  item
225
232
  end
226
233
 
227
234
  def normalized_hash(item_class)
228
235
  if item_class.is_a?(Class)
229
- raise(ArgumentError, "Message must include a Sidekiq::Worker class, not class name: #{item_class.ancestors.inspect}") if !item_class.respond_to?('get_sidekiq_options'.freeze)
236
+ raise(ArgumentError, "Message must include a Sidekiq::Worker class, not class name: #{item_class.ancestors.inspect}") if !item_class.respond_to?('get_sidekiq_options')
230
237
  item_class.get_sidekiq_options
231
238
  else
232
239
  Sidekiq.default_worker_options
@@ -1,106 +1 @@
1
- # frozen_string_literal: true
2
- begin
3
- require 'active_support/core_ext/class/attribute'
4
- rescue LoadError
5
-
6
- # A dumbed down version of ActiveSupport's
7
- # Class#class_attribute helper.
8
- class Class
9
- def class_attribute(*attrs)
10
- instance_writer = true
11
-
12
- attrs.each do |name|
13
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
14
- def self.#{name}() nil end
15
- def self.#{name}?() !!#{name} end
16
-
17
- def self.#{name}=(val)
18
- singleton_class.class_eval do
19
- define_method(:#{name}) { val }
20
- end
21
-
22
- if singleton_class?
23
- class_eval do
24
- def #{name}
25
- defined?(@#{name}) ? @#{name} : singleton_class.#{name}
26
- end
27
- end
28
- end
29
- val
30
- end
31
-
32
- def #{name}
33
- defined?(@#{name}) ? @#{name} : self.class.#{name}
34
- end
35
-
36
- def #{name}?
37
- !!#{name}
38
- end
39
- RUBY
40
-
41
- attr_writer name if instance_writer
42
- end
43
- end
44
-
45
- private
46
- def singleton_class?
47
- ancestors.first != self
48
- end
49
- end
50
- end
51
-
52
- begin
53
- require 'active_support/core_ext/hash/keys'
54
- require 'active_support/core_ext/hash/deep_merge'
55
- rescue LoadError
56
- class Hash
57
- def stringify_keys
58
- keys.each do |key|
59
- self[key.to_s] = delete(key)
60
- end
61
- self
62
- end if !{}.respond_to?(:stringify_keys)
63
-
64
- def symbolize_keys
65
- keys.each do |key|
66
- self[(key.to_sym rescue key) || key] = delete(key)
67
- end
68
- self
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!)
86
- end
87
- end
88
-
89
- begin
90
- require 'active_support/core_ext/string/inflections'
91
- rescue LoadError
92
- class String
93
- def constantize
94
- names = self.split('::')
95
- names.shift if names.empty? || names.first.empty?
96
-
97
- constant = Object
98
- names.each do |name|
99
- constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
100
- end
101
- constant
102
- end
103
- end if !"".respond_to?(:constantize)
104
- end
105
-
106
-
1
+ raise "no longer used, will be removed in 5.1"
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+ module Sidekiq
3
+ module Extensions
4
+
5
+ def self.enable_delay!
6
+ if defined?(::ActiveSupport)
7
+ require 'sidekiq/extensions/active_record'
8
+ require 'sidekiq/extensions/action_mailer'
9
+
10
+ # Need to patch Psych so it can autoload classes whose names are serialized
11
+ # in the delayed YAML.
12
+ Psych::Visitors::ToRuby.prepend(Sidekiq::Extensions::PsychAutoload)
13
+
14
+ ActiveSupport.on_load(:active_record) do
15
+ include Sidekiq::Extensions::ActiveRecord
16
+ end
17
+ ActiveSupport.on_load(:action_mailer) do
18
+ extend Sidekiq::Extensions::ActionMailer
19
+ end
20
+ end
21
+
22
+ require 'sidekiq/extensions/class_methods'
23
+ Module.__send__(:include, Sidekiq::Extensions::Klass)
24
+ end
25
+
26
+ module PsychAutoload
27
+ def resolve_class(klass_name)
28
+ return nil if !klass_name || klass_name.empty?
29
+ # constantize
30
+ names = klass_name.split('::')
31
+ names.shift if names.empty? || names.first.empty?
32
+
33
+ names.inject(Object) do |constant, name|
34
+ constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
35
+ end
36
+ rescue NameError
37
+ super
38
+ end
39
+ end
40
+ end
41
+ end
42
+
@@ -7,11 +7,10 @@ module Sidekiq
7
7
  class Logger
8
8
  def call(ex, ctxHash)
9
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?
10
+ Sidekiq.logger.warn("#{ex.class.name}: #{ex.message}")
11
+ Sidekiq.logger.warn(ex.backtrace.join("\n")) unless ex.backtrace.nil?
12
12
  end
13
13
 
14
- # Set up default handler which just logs the error
15
14
  Sidekiq.error_handlers << Sidekiq::ExceptionHandler::Logger.new
16
15
  end
17
16
 
@@ -26,6 +25,5 @@ module Sidekiq
26
25
  end
27
26
  end
28
27
  end
29
-
30
28
  end
31
29
  end
@@ -3,6 +3,8 @@ require 'yaml'
3
3
 
4
4
  module Sidekiq
5
5
  module Extensions
6
+ SIZE_LIMIT = 8_192
7
+
6
8
  class Proxy < BasicObject
7
9
  def initialize(performable, target, options={})
8
10
  @performable = performable
@@ -17,7 +19,11 @@ module Sidekiq
17
19
  # to JSON and then deserialized on the other side back into a
18
20
  # Ruby object.
19
21
  obj = [@target, name, args]
20
- @performable.client_push({ 'class' => @performable, 'args' => [::YAML.dump(obj)] }.merge(@opts))
22
+ marshalled = ::YAML.dump(obj)
23
+ if marshalled.size > SIZE_LIMIT
24
+ ::Sidekiq.logger.warn { "#{@target}.#{name} job argument is #{marshalled.bytesize} bytes, you should refactor it to reduce the size" }
25
+ end
26
+ @performable.client_push({ 'class' => @performable, 'args' => [marshalled] }.merge(@opts))
21
27
  end
22
28
  end
23
29
 
data/lib/sidekiq/fetch.rb CHANGED
@@ -13,7 +13,7 @@ module Sidekiq
13
13
  end
14
14
 
15
15
  def queue_name
16
- queue.sub(/.*queue:/, ''.freeze)
16
+ queue.sub(/.*queue:/, '')
17
17
  end
18
18
 
19
19
  def requeue
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+ module Sidekiq
3
+ class JobLogger
4
+
5
+ def call(item, queue)
6
+ start = Time.now
7
+ logger.info("start")
8
+ yield
9
+ logger.info("done: #{elapsed(start)} sec")
10
+ rescue Exception
11
+ logger.info("fail: #{elapsed(start)} sec")
12
+ raise
13
+ end
14
+
15
+ private
16
+
17
+ def elapsed(start)
18
+ (Time.now - start).round(3)
19
+ end
20
+
21
+ def logger
22
+ Sidekiq.logger
23
+ end
24
+ end
25
+ end