sidekiq 5.0.5 → 5.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 96202101069aaee71e462e2f3b91f5d4c58e952f
4
- data.tar.gz: ad75e0b5dc019bb8d1058b124535190f00b06f60
3
+ metadata.gz: 4ec2845461ba55bb7f8424359c49ee8e339ae4be
4
+ data.tar.gz: b578722c371f8dc196294da1058279a8794e960e
5
5
  SHA512:
6
- metadata.gz: 4de121e1a00611b97f5c8838c5beb1d5a4fa5e6fb37e7cd7b2ac2074239d8a48d1d9526d4a8c0a94fcfcebe7ee3507209735569c78309f18d29363fbab24b992
7
- data.tar.gz: 239a247dd69bab58148229f64d7b8ff12a658bb696c08c9f00b9ee9170c5d40ea052891eef5d89742633282d99095b4eb6004df298aa2f06b5f114fbbcfb10de
6
+ metadata.gz: 8c900629c592c5eb88b63863e4202667575501cf472257bbf58c211ef743ee887a288bc14744d5da50ea0ff9163285427d93a8946bfb48a26896cd55b5c7b4b3
7
+ data.tar.gz: 639a844489ccf182d8a3444594c1e5528978f536b3a7c0954d5a8d47d203002285e28ee84e0f47829d1ed7545475400ff3928b6304b65aee7e7595ccc3dd0765
@@ -4,6 +4,8 @@ Sidekiq / Pro / Enterprise version(s):
4
4
  Please include your initializer and any error message with the full backtrace.
5
5
 
6
6
  Are you using an old version?
7
- Have you checked the changelog to see if your issue has been fixed in a later version?
7
+ Have you checked the changelogs to see if your issue has been fixed in a later version?
8
8
 
9
9
  https://github.com/mperham/sidekiq/blob/master/Changes.md
10
+ https://github.com/mperham/sidekiq/blob/master/Pro-Changes.md
11
+ https://github.com/mperham/sidekiq/blob/master/Ent-Changes.md
@@ -7,7 +7,8 @@ before_install:
7
7
  - gem install bundler
8
8
  - gem update bundler
9
9
  rvm:
10
- - 2.2.4
11
- - 2.3.0
12
- - 2.4.0
13
- - jruby-9.1.6.0
10
+ - 2.2.2
11
+ - 2.3.5
12
+ - 2.4.2
13
+ - 2.5.0
14
+ - jruby-9.1.14.0
data/Changes.md CHANGED
@@ -2,12 +2,27 @@
2
2
 
3
3
  [Sidekiq Changes](https://github.com/mperham/sidekiq/blob/master/Changes.md) | [Sidekiq Pro Changes](https://github.com/mperham/sidekiq/blob/master/Pro-Changes.md) | [Sidekiq Enterprise Changes](https://github.com/mperham/sidekiq/blob/master/Ent-Changes.md)
4
4
 
5
- HEAD
5
+ 5.1.0
6
+ -----------
7
+
8
+ - **NEW** Global death handlers - called when your job exhausts all
9
+ retries and dies. Now you can take action when a job fails permanently. [#3721]
10
+ - **NEW** Enable ActiveRecord query cache within jobs by default [#3718, sobrinho]
11
+ This will prevent duplicate SELECTS; cache is cleared upon any UPDATE/INSERT/DELETE.
12
+ See the issue for how to bypass the cache or disable it completely.
13
+ - Scheduler timing is now more accurate, 15 -> 5 seconds [#3734]
14
+ - Exceptions during the :startup event will now kill the process [#3717]
15
+ - Make `Sidekiq::Client.via` reentrant [#3715]
16
+ - Fix use of Sidekiq logger outside of the server process [#3714]
17
+ - Tweak `constantize` to better match Rails class lookup. [#3701, caffeinated-tech]
18
+
19
+ 5.0.5
6
20
  -----------
7
21
 
8
22
  - Update gemspec to allow newer versions of the Redis gem [#3617]
9
23
  - Refactor Worker.set so it can be memoized [#3602]
10
24
  - Fix display of Redis URL in web footer, broken in 5.0.3 [#3560]
25
+ - Update `Sidekiq::Job#display_args` to avoid mutation [#3621]
11
26
 
12
27
  5.0.4
13
28
  -----------
@@ -4,6 +4,13 @@
4
4
 
5
5
  Please see [http://sidekiq.org/](http://sidekiq.org/) for more details and how to buy.
6
6
 
7
+ HEAD
8
+ -------------
9
+
10
+ - **NEW FEATURE** [Rolling restarts](https://github.com/mperham/sidekiq/wiki/Ent-Rolling-Restarts) - great for long running jobs!
11
+ - Adjust middleware so failed unique jobs don't affect batches [#3662]
12
+ - Add new unlimited rate limiter, useful for testing [#3743]
13
+
7
14
  1.6.1
8
15
  -------------
9
16
 
data/Gemfile CHANGED
@@ -2,31 +2,7 @@ source 'https://rubygems.org'
2
2
  gemspec
3
3
 
4
4
  gem 'rails', '>= 5.0.1'
5
- gem "hiredis"
5
+ #gem "hiredis"
6
6
  gem 'simplecov'
7
7
  gem 'minitest'
8
- #gem 'minitest-utils'
9
- gem 'toxiproxy'
10
-
11
- # For Redis 4.0 support. Unreleased 9cb81bf.
12
- gem 'redis-namespace', git: 'https://github.com/resque/redis-namespace'
13
-
14
- platforms :rbx do
15
- gem 'rubysl', '~> 2.0' # if using anything in the ruby standard library
16
- gem 'psych' # if using yaml
17
- gem 'rubinius-developer_tools' # if using any of coverage, debugger, profiler
18
- end
19
-
20
- platforms :ruby do
21
- gem 'sqlite3'
22
- end
23
-
24
- platforms :mri do
25
- gem 'pry-byebug'
26
- gem 'ruby-prof'
27
- end
28
-
29
- #platforms :jruby do
30
- #gem 'jruby-openssl'
31
- #gem 'activerecord-jdbcsqlite3-adapter'
32
- #end
8
+ #gem 'toxiproxy'
@@ -0,0 +1,32 @@
1
+ # Welcome to Sidekiq Pro 4.0!
2
+
3
+ Sidekiq Pro 4.0 is designed to work with Sidekiq 5.0.
4
+
5
+ ## What's New
6
+
7
+ * Batches now "die" if any of their jobs die. You can enumerate the set
8
+ of dead batches and their associated dead jobs. The success callback
9
+ for a dead batch will never fire unless these jobs are fixed.
10
+ ```ruby
11
+ Sidekiq::Batch::DeadSet.new.each do |status|
12
+ status.dead? # => true
13
+ status.dead_jobs # => [...]
14
+ end
15
+ ```
16
+ * The older `reliable_fetch` and `timed_fetch` algorithms have been
17
+ removed. Only super\_fetch is available in 4.0.
18
+ * The statsd middleware has been tweaked to remove support for legacy,
19
+ pre-3.6.0 configuration.
20
+
21
+ ## Upgrade
22
+
23
+ * Upgrade to the latest Sidekiq Pro 3.x.
24
+ ```ruby
25
+ gem 'sidekiq-pro', '< 4'
26
+ ```
27
+ * Fix any deprecation warnings you see.
28
+ * Upgrade to 4.x.
29
+ ```ruby
30
+ gem 'sidekiq-pro', '< 5'
31
+ ```
32
+
@@ -4,6 +4,69 @@
4
4
 
5
5
  Please see [http://sidekiq.org/](http://sidekiq.org/) for more details and how to buy.
6
6
 
7
+ HEAD
8
+ ---------
9
+
10
+ - See the [Sidekiq Pro 4.0](Pro-4.0-Upgrade.md) release notes.
11
+
12
+
13
+ 3.7.1
14
+ ---------
15
+
16
+ - Deprecate timed\_fetch. Switch to super\_fetch:
17
+ ```ruby
18
+ config.super_fetch!
19
+ ```
20
+
21
+
22
+ 3.7.0
23
+ ---------
24
+
25
+ - Refactor batch job success/failure to gracefully handle several edge
26
+ cases with regard to Sidekiq::Shutdown. This should greatly reduce
27
+ the chances of seeing the long-standing "negative pending count" problem. [#3710]
28
+
29
+
30
+ 3.6.1
31
+ ---------
32
+
33
+ - Add support for Datadog::Statsd, it is the recommended Statsd client. [#3699]
34
+ ```ruby
35
+ Sidekiq::Pro.dogstatsd = ->{ Datadog::Statsd.new("metrics.example.com", 8125) }
36
+ ```
37
+ - Size the statsd connection pool based on Sidekiq's concurrency [#3700]
38
+
39
+
40
+ 3.6.0
41
+ ---------
42
+
43
+ This release overhauls the Statsd metrics support and adds more
44
+ metrics for tracking Pro feature usage. In your initializer:
45
+ ```ruby
46
+ Sidekiq::Pro.statsd = ->{ ::Statsd.new("127.0.0.1", 8125) }
47
+ ```
48
+ Sidekiq Pro will emit more metrics to Statsd:
49
+ ```
50
+ jobs.expired - when a job is expired
51
+ jobs.recovered.push - when a job is recovered by reliable_push after network outage
52
+ jobs.recovered.fetch - when a job is recovered by super_fetch after process crash
53
+ batch.created - when a batch is created
54
+ batch.complete - when a batch is completed
55
+ batch.success - when a batch is successful
56
+ ```
57
+ Sidekiq Pro's existing Statsd middleware has been rewritten to leverage the new API.
58
+ Everything should be backwards compatible with one deprecation notice.
59
+
60
+
61
+ 3.5.4
62
+ ---------
63
+
64
+ - Fix case in SuperFetch where Redis downtime can lead to processor thread death [#3684]
65
+ - Fix case where TimedFetch might not recover some pending jobs
66
+ - Fix edge case in Batch::Status#poll leading to premature completion [#3640]
67
+ - Adjust scan API to check 100 elements at a time, to minimize network round trips
68
+ when scanning large sets.
69
+
7
70
  3.5.3
8
71
  ---------
9
72
 
data/README.md CHANGED
@@ -77,16 +77,18 @@ Problems?
77
77
  If you have a problem, please review the [FAQ](https://github.com/mperham/sidekiq/wiki/FAQ) and [Troubleshooting](https://github.com/mperham/sidekiq/wiki/Problems-and-Troubleshooting) wiki pages.
78
78
  Searching the [issues](https://github.com/mperham/sidekiq/issues) for your problem is also a good idea.
79
79
 
80
+ Sidekiq Pro and Sidekiq Enterprise customers get private email support. You can purchase at http://sidekiq.org; email support@contribsys.com for help.
81
+
80
82
  Useful resources:
81
83
 
82
84
  * Product documentation is in the [wiki](https://github.com/mperham/sidekiq/wiki).
83
85
  * Release announcements are made to the [@sidekiq](https://twitter.com/sidekiq) Twitter account.
84
86
  * The [Sidekiq tag](https://stackoverflow.com/questions/tagged/sidekiq) on Stack Overflow has lots of useful Q &amp; A.
85
87
 
86
- **No support via Twitter, 140 characters is not enough.**
88
+ **No support via Twitter**
87
89
 
88
90
  Every Friday morning is Sidekiq happy hour: I video chat and answer questions.
89
- See the [Sidekiq support page](http://sidekiq.org/support) for details.
91
+ See the [Sidekiq support page](http://sidekiq.org/support.html) for details.
90
92
 
91
93
  Thanks
92
94
  -----------------
data/Rakefile CHANGED
@@ -6,7 +6,3 @@ Rake::TestTask.new(:test) do |test|
6
6
  end
7
7
 
8
8
  task :default => :test
9
-
10
- task :appraise do
11
- exec("cd myapp && rake appraise")
12
- end
@@ -72,7 +72,7 @@ def handle_signal(launcher, sig)
72
72
  launcher.quiet
73
73
  when 'TTIN'
74
74
  Thread.list.each do |thread|
75
- Sidekiq.logger.warn "Thread TID-#{thread.object_id.to_s(36)} #{thread['label']}"
75
+ Sidekiq.logger.warn "Thread TID-#{(thread.object_id ^ ::Process.pid).to_s(36)} #{thread['label']}"
76
76
  if thread.backtrace
77
77
  Sidekiq.logger.warn thread.backtrace.join("\n")
78
78
  else
@@ -23,8 +23,9 @@ module Sidekiq
23
23
  environment: nil,
24
24
  timeout: 8,
25
25
  poll_interval_average: nil,
26
- average_scheduled_poll_interval: 15,
26
+ average_scheduled_poll_interval: 5,
27
27
  error_handlers: [],
28
+ death_handlers: [],
28
29
  lifecycle_events: {
29
30
  startup: [],
30
31
  quiet: [],
@@ -156,16 +157,23 @@ module Sidekiq
156
157
  defined?(@default_worker_options) ? @default_worker_options : DEFAULT_WORKER_OPTIONS
157
158
  end
158
159
 
160
+ def self.default_retries_exhausted=(prok)
161
+ logger.info { "default_retries_exhausted is deprecated, please use `config.death_handlers << -> {|job, ex| }`" }
162
+ return nil unless prok
163
+ death_handlers << prok
164
+ end
165
+
166
+ ##
167
+ # Death handlers are called when all retries for a job have been exhausted and
168
+ # the job dies. It's the notification to your application
169
+ # that this job will not succeed without manual intervention.
170
+ #
159
171
  # Sidekiq.configure_server do |config|
160
- # config.default_retries_exhausted = -> (job, ex) do
172
+ # config.death_handlers << ->(job, ex) do
161
173
  # end
162
174
  # end
163
- def self.default_retries_exhausted=(prok)
164
- @default_retries_exhausted = prok
165
- end
166
- @default_retries_exhausted = ->(job, ex) { }
167
- def self.default_retries_exhausted
168
- @default_retries_exhausted
175
+ def self.death_handlers
176
+ options[:death_handlers]
169
177
  end
170
178
 
171
179
  def self.load_json(string)
@@ -548,7 +548,7 @@ module Sidekiq
548
548
  end
549
549
  break if elements.empty?
550
550
  page -= 1
551
- elements.each do |element, score|
551
+ elements.reverse.each do |element, score|
552
552
  yield SortedEntry.new(self, score, element)
553
553
  end
554
554
  offset_size = initial_size - @_size
@@ -656,7 +656,7 @@ module Sidekiq
656
656
  super 'dead'
657
657
  end
658
658
 
659
- def kill(message)
659
+ def kill(message, opts={})
660
660
  now = Time.now.to_f
661
661
  Sidekiq.redis do |conn|
662
662
  conn.multi do
@@ -665,6 +665,16 @@ module Sidekiq
665
665
  conn.zremrangebyrank(name, 0, - self.class.max_jobs)
666
666
  end
667
667
  end
668
+
669
+ if opts[:notify_failure] != false
670
+ job = Sidekiq.load_json(message)
671
+ r = RuntimeError.new("Job killed by API")
672
+ r.set_backtrace(caller)
673
+ Sidekiq.death_handlers.each do |handle|
674
+ handle.call(job, r)
675
+ end
676
+ end
677
+ true
668
678
  end
669
679
 
670
680
  def retry_all
@@ -89,7 +89,7 @@ module Sidekiq
89
89
 
90
90
  # Before this point, the process is initializing with just the main thread.
91
91
  # Starting here the process will now have multiple threads running.
92
- fire_event(:startup)
92
+ fire_event(:startup, reverse: false, reraise: true)
93
93
 
94
94
  logger.debug { "Client Middleware: #{Sidekiq.client_middleware.map(&:klass).join(', ')}" }
95
95
  logger.debug { "Server Middleware: #{Sidekiq.server_middleware.map(&:klass).join(', ')}" }
@@ -135,37 +135,45 @@ module Sidekiq
135
135
  }
136
136
  end
137
137
 
138
- def handle_signal(sig)
139
- Sidekiq.logger.debug "Got #{sig} signal"
140
- case sig
141
- when 'INT'
142
- # Handle Ctrl-C in JRuby like MRI
143
- # http://jira.codehaus.org/browse/JRUBY-4637
144
- raise Interrupt
145
- when 'TERM'
146
- # Heroku sends TERM and then waits 10 seconds for process to exit.
147
- raise Interrupt
148
- when 'USR1'
138
+ SIGNAL_HANDLERS = {
139
+ # Ctrl-C in terminal
140
+ 'INT' => ->(cli) { raise Interrupt },
141
+ # TERM is the signal that Sidekiq must exit.
142
+ # Heroku sends TERM and then waits 30 seconds for process to exit.
143
+ 'TERM' => ->(cli) { raise Interrupt },
144
+ 'USR1' => ->(cli) {
149
145
  Sidekiq.logger.info "Received USR1, no longer accepting new work"
150
- launcher.quiet
151
- when 'TSTP'
152
- # USR1 is not available on JVM, allow TSTP as an alternate signal
146
+ cli.launcher.quiet
147
+ },
148
+ 'TSTP' => ->(cli) {
153
149
  Sidekiq.logger.info "Received TSTP, no longer accepting new work"
154
- launcher.quiet
155
- when 'USR2'
150
+ cli.launcher.quiet
151
+ },
152
+ 'USR2' => ->(cli) {
156
153
  if Sidekiq.options[:logfile]
157
154
  Sidekiq.logger.info "Received USR2, reopening log file"
158
155
  Sidekiq::Logging.reopen_logs
159
156
  end
160
- when 'TTIN'
157
+ },
158
+ 'TTIN' => ->(cli) {
161
159
  Thread.list.each do |thread|
162
- Sidekiq.logger.warn "Thread TID-#{thread.object_id.to_s(36)} #{thread['sidekiq_label']}"
160
+ Sidekiq.logger.warn "Thread TID-#{(thread.object_id ^ ::Process.pid).to_s(36)} #{thread['sidekiq_label']}"
163
161
  if thread.backtrace
164
162
  Sidekiq.logger.warn thread.backtrace.join("\n")
165
163
  else
166
164
  Sidekiq.logger.warn "<no backtrace available>"
167
165
  end
168
166
  end
167
+ },
168
+ }
169
+
170
+ def handle_signal(sig)
171
+ Sidekiq.logger.debug "Got #{sig} signal"
172
+ handy = SIGNAL_HANDLERS[sig]
173
+ if handy
174
+ handy.call(self)
175
+ else
176
+ Sidekiq.logger.info { "No signal handler for #{sig}" }
169
177
  end
170
178
  end
171
179
 
@@ -214,6 +222,14 @@ module Sidekiq
214
222
  @environment = cli_env || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
215
223
  end
216
224
 
225
+ def symbolize_keys_deep!(hash)
226
+ hash.keys.each do |k|
227
+ symkey = k.respond_to?(:to_sym) ? k.to_sym : k
228
+ hash[symkey] = hash.delete k
229
+ symbolize_keys_deep! hash[symkey] if hash[symkey].kind_of? Hash
230
+ end
231
+ end
232
+
217
233
  alias_method :die, :exit
218
234
  alias_method :☠, :exit
219
235
 
@@ -282,7 +298,7 @@ module Sidekiq
282
298
  if !File.exist?(options[:require]) ||
283
299
  (File.directory?(options[:require]) && !File.exist?("#{options[:require]}/config/application.rb"))
284
300
  logger.info "=================================================================="
285
- logger.info " Please point sidekiq to a Rails 3/4 application or a Ruby file "
301
+ logger.info " Please point sidekiq to a Rails 4/5 application or a Ruby file "
286
302
  logger.info " to load your worker classes with -r [DIR|FILE]."
287
303
  logger.info "=================================================================="
288
304
  logger.info @parser
@@ -386,7 +402,14 @@ module Sidekiq
386
402
  opts = {}
387
403
  if File.exist?(cfile)
388
404
  opts = YAML.load(ERB.new(IO.read(cfile)).result) || opts
389
- opts = opts.merge(opts.delete(environment) || {})
405
+
406
+ if opts.respond_to? :deep_symbolize_keys!
407
+ opts.deep_symbolize_keys!
408
+ else
409
+ symbolize_keys_deep!(opts)
410
+ end
411
+
412
+ opts = opts.merge(opts.delete(environment.to_sym) || {})
390
413
  parse_queues(opts, opts.delete(:queues) || [])
391
414
  else
392
415
  # allow a non-existent config file so Sidekiq
@@ -119,11 +119,10 @@ module Sidekiq
119
119
  def self.via(pool)
120
120
  raise ArgumentError, "No pool given" if pool.nil?
121
121
  current_sidekiq_pool = Thread.current[:sidekiq_via_pool]
122
- raise RuntimeError, "Sidekiq::Client.via is not re-entrant" if current_sidekiq_pool && current_sidekiq_pool != pool
123
122
  Thread.current[:sidekiq_via_pool] = pool
124
123
  yield
125
124
  ensure
126
- Thread.current[:sidekiq_via_pool] = nil
125
+ Thread.current[:sidekiq_via_pool] = current_sidekiq_pool
127
126
  end
128
127
 
129
128
  class << self
@@ -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
@@ -172,10 +172,18 @@ module Sidekiq
172
172
  def retries_exhausted(worker, msg, exception)
173
173
  logger.debug { "Retries exhausted for job" }
174
174
  begin
175
- block = worker && worker.sidekiq_retries_exhausted_block || Sidekiq.default_retries_exhausted
175
+ block = worker && worker.sidekiq_retries_exhausted_block
176
176
  block.call(msg, exception) if block
177
177
  rescue => e
178
- handle_exception(e, { context: "Error calling retries_exhausted for #{msg['class']}", job: msg })
178
+ handle_exception(e, { context: "Error calling retries_exhausted", job: msg })
179
+ end
180
+
181
+ Sidekiq.death_handlers.each do |handler|
182
+ begin
183
+ handler.call(msg, exception)
184
+ rescue => e
185
+ handle_exception(e, { context: "Error calling death handler", job: msg })
186
+ end
179
187
  end
180
188
 
181
189
  send_to_morgue(msg) unless msg['dead'] == false
@@ -184,7 +192,7 @@ module Sidekiq
184
192
  def send_to_morgue(msg)
185
193
  Sidekiq.logger.info { "Adding dead #{msg['class']} job #{msg['jid']}" }
186
194
  payload = Sidekiq.dump_json(msg)
187
- DeadSet.new.kill(payload)
195
+ DeadSet.new.kill(payload, notify_failure: false)
188
196
  end
189
197
 
190
198
  def retry_attempts_from(msg_retry, default)
@@ -11,7 +11,7 @@ module Sidekiq
11
11
 
12
12
  # Provide a call() method that returns the formatted message.
13
13
  def call(severity, time, program_name, message)
14
- "#{time.utc.iso8601(3)} #{::Process.pid} TID-#{Thread.current.object_id.to_s(36)}#{context} #{severity}: #{message}\n"
14
+ "#{time.utc.iso8601(3)} #{::Process.pid} TID-#{Sidekiq::Logging.tid}#{context} #{severity}: #{message}\n"
15
15
  end
16
16
 
17
17
  def context
@@ -22,10 +22,14 @@ module Sidekiq
22
22
 
23
23
  class WithoutTimestamp < Pretty
24
24
  def call(severity, time, program_name, message)
25
- "#{::Process.pid} TID-#{Thread.current.object_id.to_s(36)}#{context} #{severity}: #{message}\n"
25
+ "#{::Process.pid} TID-#{Sidekiq::Logging.tid}#{context} #{severity}: #{message}\n"
26
26
  end
27
27
  end
28
28
 
29
+ def self.tid
30
+ Thread.current['sidekiq_tid'] ||= (Thread.current.object_id ^ ::Process.pid).to_s(36)
31
+ end
32
+
29
33
  def self.job_hash_context(job_hash)
30
34
  # If we're using a wrapper class, like ActiveJob, use the "wrapped"
31
35
  # attribute to expose the underlying thing.
@@ -54,7 +54,7 @@ module Sidekiq
54
54
 
55
55
  logger.info { "Terminating quiet workers" }
56
56
  @workers.each { |x| x.terminate }
57
- fire_event(:quiet, true)
57
+ fire_event(:quiet, reverse: true)
58
58
  end
59
59
 
60
60
  # hack for quicker development / testing environment #2774
@@ -62,7 +62,7 @@ module Sidekiq
62
62
 
63
63
  def stop(deadline)
64
64
  quiet
65
- fire_event(:shutdown, true)
65
+ fire_event(:shutdown, reverse: true)
66
66
 
67
67
  # some of the shutdown events can be async,
68
68
  # we don't have any way to know when they're done but
@@ -0,0 +1,11 @@
1
+ module Sidekiq
2
+ module Middleware
3
+ module Server
4
+ class ActiveRecordCache
5
+ def call(*args, &block)
6
+ ::ActiveRecord::Base.cache(&block)
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -111,9 +111,7 @@ module Sidekiq
111
111
  if !@down
112
112
  @down = Time.now
113
113
  logger.error("Error fetching job: #{ex}")
114
- ex.backtrace.each do |bt|
115
- logger.error(bt)
116
- end
114
+ handle_exception(ex)
117
115
  end
118
116
  sleep(1)
119
117
  nil
@@ -159,7 +157,8 @@ module Sidekiq
159
157
  job_hash = Sidekiq.load_json(jobstr)
160
158
  rescue => ex
161
159
  handle_exception(ex, { :context => "Invalid JSON for job", :jobstr => jobstr })
162
- DeadSet.new.kill(jobstr)
160
+ # we can't notify because the job isn't a valid hash payload.
161
+ DeadSet.new.kill(jobstr, notify_failure: false)
163
162
  ack = true
164
163
  raise
165
164
  end
@@ -188,16 +187,12 @@ module Sidekiq
188
187
  worker.perform(*cloned_args)
189
188
  end
190
189
 
191
- def thread_identity
192
- @str ||= Thread.current.object_id.to_s(36)
193
- end
194
-
195
190
  WORKER_STATE = Concurrent::Map.new
196
191
  PROCESSED = Concurrent::AtomicFixnum.new
197
192
  FAILURE = Concurrent::AtomicFixnum.new
198
193
 
199
194
  def stats(job_hash, queue)
200
- tid = thread_identity
195
+ tid = Sidekiq::Logging.tid
201
196
  WORKER_STATE[tid] = {:queue => queue, :payload => job_hash, :run_at => Time.now.to_i }
202
197
 
203
198
  begin
@@ -223,7 +218,9 @@ module Sidekiq
223
218
  names.shift if names.empty? || names.first.empty?
224
219
 
225
220
  names.inject(Object) do |constant, name|
226
- constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
221
+ # the false flag limits search for name to under the constant namespace
222
+ # which mimics Rails' behaviour
223
+ constant.const_defined?(name, false) ? constant.const_get(name, false) : constant.const_missing(name)
227
224
  end
228
225
  end
229
226
 
@@ -9,10 +9,15 @@ module Sidekiq
9
9
  # class block. Definitely before config/environments/*.rb and
10
10
  # config/initializers/*.rb.
11
11
  config.before_configuration do
12
- if ::Rails::VERSION::MAJOR < 5 && defined?(::ActiveRecord)
12
+ if defined?(::ActiveRecord)
13
13
  Sidekiq.server_middleware do |chain|
14
- require 'sidekiq/middleware/server/active_record'
15
- chain.add Sidekiq::Middleware::Server::ActiveRecord
14
+ if ::Rails::VERSION::MAJOR < 5
15
+ require 'sidekiq/middleware/server/active_record'
16
+ chain.add Sidekiq::Middleware::Server::ActiveRecord
17
+ end
18
+
19
+ require 'sidekiq/middleware/server/active_record_cache'
20
+ chain.add Sidekiq::Middleware::Server::ActiveRecordCache
16
21
  end
17
22
  end
18
23
  end
@@ -49,3 +54,9 @@ module Sidekiq
49
54
  end
50
55
  end if defined?(::Rails)
51
56
  end
57
+
58
+ if defined?(::Rails) && ::Rails::VERSION::MAJOR < 4
59
+ $stderr.puts("**************************************************")
60
+ $stderr.puts("⛔️ WARNING: Sidekiq server is no longer supported by Rails 3.2 - please ensure your server/workers are updated")
61
+ $stderr.puts("**************************************************")
62
+ end
@@ -38,7 +38,7 @@ module Sidekiq
38
38
  # - enterprise's leader election
39
39
  # - enterprise's cron support
40
40
  def verify_sizing(size, concurrency)
41
- raise ArgumentError, "Your Redis connection pool is too small for Sidekiq to work. Your pool has #{size} connections but really needs to have at least #{concurrency + 2}" if size <= concurrency
41
+ raise ArgumentError, "Your Redis connection pool is too small for Sidekiq to work. Your pool has #{size} connections but must have at least #{concurrency + 2}" if size <= concurrency
42
42
  end
43
43
 
44
44
  def build_client(options)
@@ -79,9 +79,7 @@ module Sidekiq
79
79
  # Most likely a problem with redis networking.
80
80
  # Punt and try again at the next interval
81
81
  logger.error ex.message
82
- ex.backtrace.each do |bt|
83
- logger.error(bt)
84
- end
82
+ handle_exception(ex)
85
83
  end
86
84
  end
87
85
 
@@ -95,7 +93,7 @@ module Sidekiq
95
93
  # if poll_interval_average hasn't been calculated yet, we can
96
94
  # raise an error trying to reach Redis.
97
95
  logger.error ex.message
98
- logger.error ex.backtrace.first
96
+ handle_exception(ex)
99
97
  sleep 5
100
98
  end
101
99
 
@@ -46,7 +46,10 @@ module Sidekiq
46
46
  @@identity ||= "#{hostname}:#{$$}:#{process_nonce}"
47
47
  end
48
48
 
49
- def fire_event(event, reverse=false)
49
+ def fire_event(event, options={})
50
+ reverse = options[:reverse]
51
+ reraise = options[:reraise]
52
+
50
53
  arr = Sidekiq.options[:lifecycle_events][event]
51
54
  arr.reverse! if reverse
52
55
  arr.each do |block|
@@ -54,6 +57,7 @@ module Sidekiq
54
57
  block.call
55
58
  rescue => ex
56
59
  handle_exception(ex, { context: "Exception during Sidekiq lifecycle event.", event: event })
60
+ raise ex if reraise
57
61
  end
58
62
  end
59
63
  arr.clear
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Sidekiq
3
- VERSION = "5.0.5"
3
+ VERSION = "5.1.0"
4
4
  end
@@ -77,7 +77,7 @@ module Sidekiq
77
77
  private
78
78
 
79
79
  def _erb(file, locals)
80
- locals.each {|k, v| define_singleton_method(k){ v } } if locals
80
+ locals.each {|k, v| define_singleton_method(k){ v } unless (singleton_methods.include? k)} if locals
81
81
 
82
82
  if file.kind_of?(String)
83
83
  ERB.new(file).result(binding)
@@ -148,8 +148,10 @@ module Sidekiq
148
148
  end
149
149
 
150
150
  def redis_connection
151
- attrs = Sidekiq.redis { |conn| conn.connection }
152
- "redis://#{attrs[:location]}/#{attrs[:db]}"
151
+ Sidekiq.redis do |conn|
152
+ c = conn._client
153
+ "redis://#{c.location}/#{c.db}"
154
+ end
153
155
  end
154
156
 
155
157
  def namespace
@@ -77,3 +77,4 @@ en: # <---- change this to your locale code
77
77
  NotYetEnqueued: Not yet enqueued
78
78
  CreatedAt: Created At
79
79
  BackToApp: Back to App
80
+ Latency: Latency
@@ -67,3 +67,4 @@ es:
67
67
  Thread: Hilo
68
68
  Threads: Hilos
69
69
  Jobs: Trabajos
70
+ Latency: Latencia
@@ -60,9 +60,9 @@ ja:
60
60
  SixMonths: 6 ヶ月
61
61
  Batches: バッチ
62
62
  Failures: 失敗
63
- DeadJobs: 死亡したジョブ
64
- NoDeadJobsFound: 死亡したジョブはありません
65
- Dead: 死亡
63
+ DeadJobs: デッドジョブ
64
+ NoDeadJobsFound: デッドジョブはありません
65
+ Dead: デッド
66
66
  Processes: プロセス
67
67
  Thread: スレッド
68
68
  Threads: スレッド
@@ -76,3 +76,5 @@ ja:
76
76
  Plugins: プラグイン
77
77
  NotYetEnqueued: キューに入っていません
78
78
  CreatedAt: 作成日時
79
+ BackToApp: アプリに戻る
80
+ Latency: レイテンシ
@@ -5,6 +5,7 @@
5
5
  <thead>
6
6
  <th><%= t('Queue') %></th>
7
7
  <th><%= t('Size') %></th>
8
+ <th><%= t('Latency') %></th>
8
9
  <th><%= t('Actions') %></th>
9
10
  </thead>
10
11
  <% @queues.each do |queue| %>
@@ -16,6 +17,7 @@
16
17
  <% end %>
17
18
  </td>
18
19
  <td><%= number_with_delimiter(queue.size) %> </td>
20
+ <td><%= number_with_delimiter(queue.latency.round(2)) %> </td>
19
21
  <td class="delete-confirm">
20
22
  <form action="<%=root_path %>queues/<%= CGI.escape(queue.name) %>" method="post">
21
23
  <%= csrf_tag %>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sidekiq
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.5
4
+ version: 5.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Perham
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-02 00:00:00.000000000 Z
11
+ date: 2018-02-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis
@@ -169,6 +169,7 @@ files:
169
169
  - LICENSE
170
170
  - Pro-2.0-Upgrade.md
171
171
  - Pro-3.0-Upgrade.md
172
+ - Pro-4.0-Upgrade.md
172
173
  - Pro-Changes.md
173
174
  - README.md
174
175
  - Rakefile
@@ -200,6 +201,7 @@ files:
200
201
  - lib/sidekiq/middleware/chain.rb
201
202
  - lib/sidekiq/middleware/i18n.rb
202
203
  - lib/sidekiq/middleware/server/active_record.rb
204
+ - lib/sidekiq/middleware/server/active_record_cache.rb
203
205
  - lib/sidekiq/paginator.rb
204
206
  - lib/sidekiq/processor.rb
205
207
  - lib/sidekiq/rails.rb
@@ -289,7 +291,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
289
291
  version: '0'
290
292
  requirements: []
291
293
  rubyforge_project:
292
- rubygems_version: 2.5.2
294
+ rubygems_version: 2.6.13
293
295
  signing_key:
294
296
  specification_version: 4
295
297
  summary: Simple, efficient background processing for Ruby