sidekiq 7.1.4 → 7.1.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0a6064918f9c33be1d21f890b9cff080969fb44a916fe67ccb36958fe0a3b8f3
4
- data.tar.gz: baf268f21f27e0dac2fc287f247910afe493e4dcaee21aa769ccebbed03e7699
3
+ metadata.gz: b50ab03f32263dd24ee37ce2ddadc7a4e5e226860146c1a677262dd3a417329d
4
+ data.tar.gz: 0af1051781796465d5ce5dd0d0e454016fdc04b7cb5fcf0b8d62e447faff11ed
5
5
  SHA512:
6
- metadata.gz: c8f4e3caaeab143f20fdd592dc7939f09a302642867bddb4fcd02cbbaa0e734d7685ee3ad02543d3bb3ba6cbedaf2cbab3577a849c03d2f351aa7918d6eab73f
7
- data.tar.gz: 1cf71898600afb872ee717be6496da7a146aa8e2f528b6c73e3630a64f71869bc23bfa2d7130f021c7f5e12b473ed3b537cebb4a8fedcfbe517af48dde5bbea6
6
+ metadata.gz: f2e84e49ceb024e8cb24a7213ffe81e40ed9423d646e39778ed51049bf89a04c28890a21e93eeb38bb9daefe88b94b150d71a0cdf80ecdad712a2167dd0a3421
7
+ data.tar.gz: 39ffc3e4eee3e2c27a3f774f2a2120c50a52ab9e2049b0fc925123c622553bf4fd19512c16e63882031909bba6ea5b2d15cf856256a3c453d080e89253196fc6
data/Changes.md CHANGED
@@ -2,6 +2,26 @@
2
2
 
3
3
  [Sidekiq Changes](https://github.com/sidekiq/sidekiq/blob/main/Changes.md) | [Sidekiq Pro Changes](https://github.com/sidekiq/sidekiq/blob/main/Pro-Changes.md) | [Sidekiq Enterprise Changes](https://github.com/sidekiq/sidekiq/blob/main/Ent-Changes.md)
4
4
 
5
+ 7.1.6
6
+ ----------
7
+
8
+ - The block forms of testing modes (inline, fake) are now thread-safe so you can have
9
+ a multithreaded test suite which uses different modes for different tests. [#6069]
10
+ - Fix breakage with non-Proc error handlers [#6065]
11
+
12
+ 7.1.5
13
+ ----------
14
+
15
+ - **FEATURE**: Job filtering within the Web UI. This feature has been open
16
+ sourced from Sidekiq Pro. [#6052]
17
+ - **API CHANGE** Error handlers now take three arguments `->(ex, context, config)`.
18
+ The previous calling convention will work until Sidekiq 8.0 but will print
19
+ out a deprecation warning. [#6051]
20
+ - Fix issue with the `batch_size` and `at` options in `S::Client.push_bulk` [#6040]
21
+ - Fix inline testing firing batch callbacks early [#6057]
22
+ - Use new log broadcast API in Rails 7.1 [#6054]
23
+ - Crash if user tries to use RESP2 `protocol: 2` [#6061]
24
+
5
25
  7.1.4
6
26
  ----------
7
27
 
data/README.md CHANGED
@@ -83,7 +83,7 @@ You can purchase at https://sidekiq.org; email support@contribsys.com for help.
83
83
  Useful resources:
84
84
 
85
85
  * Product documentation is in the [wiki](https://github.com/sidekiq/sidekiq/wiki).
86
- * Occasional announcements are made to the [@sidekiq](https://twitter.com/sidekiq) Twitter account.
86
+ * Occasional announcements are made to the [@sidekiq](https://ruby.social/@sidekiq) Mastodon account.
87
87
  * The [Sidekiq tag](https://stackoverflow.com/questions/tagged/sidekiq) on Stack Overflow has lots of useful Q & A.
88
88
 
89
89
  Every Friday morning is Sidekiq office hour: I video chat and answer questions.
@@ -103,4 +103,4 @@ The license for Sidekiq Pro and Sidekiq Enterprise can be found in [COMM-LICENSE
103
103
  Author
104
104
  -----------------
105
105
 
106
- Mike Perham, [@getajobmike](https://twitter.com/getajobmike) / [@sidekiq](https://twitter.com/sidekiq), [https://www.mikeperham.com](https://www.mikeperham.com) / [https://www.contribsys.com](https://www.contribsys.com)
106
+ Mike Perham, [@getajobmike](https://ruby.social/@getajobmike) / [@sidekiq](https://ruby.social/@sidekiq), [https://www.mikeperham.com](https://www.mikeperham.com) / [https://www.contribsys.com](https://www.contribsys.com)
@@ -74,7 +74,7 @@ module Sidekiq
74
74
  #
75
75
  # Any options valid for a job class's sidekiq_options are also available here.
76
76
  #
77
- # All options must be strings, not symbols. NB: because we are serializing to JSON, all
77
+ # All keys must be strings, not symbols. NB: because we are serializing to JSON, all
78
78
  # symbols in 'args' will be converted to strings. Note that +backtrace: true+ can take quite a bit of
79
79
  # space in Redis; a large volume of failing jobs can start Redis swapping if you aren't careful.
80
80
  #
@@ -111,7 +111,7 @@ module Sidekiq
111
111
  # prevented a job push.
112
112
  #
113
113
  # Example (pushing jobs in batches):
114
- # push_bulk('class' => 'MyJob', 'args' => (1..100_000).to_a, batch_size: 1_000)
114
+ # push_bulk('class' => MyJob, 'args' => (1..100_000).to_a, batch_size: 1_000)
115
115
  #
116
116
  def push_bulk(items)
117
117
  batch_size = items.delete(:batch_size) || items.delete("batch_size") || 1_000
@@ -124,19 +124,21 @@ module Sidekiq
124
124
  raise ArgumentError, "Explicitly passing 'jid' when pushing more than one job is not supported" if jid && args.size > 1
125
125
 
126
126
  normed = normalize_item(items)
127
+ slice_index = 0
127
128
  result = args.each_slice(batch_size).flat_map do |slice|
128
129
  raise ArgumentError, "Bulk arguments must be an Array of Arrays: [[1], [2]]" unless slice.is_a?(Array) && slice.all?(Array)
129
130
  break [] if slice.empty? # no jobs to push
130
131
 
131
132
  payloads = slice.map.with_index { |job_args, index|
132
133
  copy = normed.merge("args" => job_args, "jid" => SecureRandom.hex(12))
133
- copy["at"] = (at.is_a?(Array) ? at[index] : at) if at
134
+ copy["at"] = (at.is_a?(Array) ? at[slice_index + index] : at) if at
134
135
  result = middleware.invoke(items["class"], copy, copy["queue"], @redis_pool) do
135
136
  verify_json(copy)
136
137
  copy
137
138
  end
138
139
  result || nil
139
140
  }
141
+ slice_index += batch_size
140
142
 
141
143
  to_push = payloads.compact
142
144
  raw_push(to_push) unless to_push.empty?
@@ -34,8 +34,7 @@ module Sidekiq
34
34
  backtrace_cleaner: ->(backtrace) { backtrace }
35
35
  }
36
36
 
37
- ERROR_HANDLER = ->(ex, ctx) {
38
- cfg = ctx[:_config] || Sidekiq.default_configuration
37
+ ERROR_HANDLER = ->(ex, ctx, cfg = Sidekiq.default_configuration) {
39
38
  l = cfg.logger
40
39
  l.warn(Sidekiq.dump_json(ctx)) unless ctx.empty?
41
40
  l.warn("#{ex.class.name}: #{ex.message}")
@@ -259,14 +258,24 @@ module Sidekiq
259
258
  @logger = logger
260
259
  end
261
260
 
261
+ private def arity(handler)
262
+ return handler.arity if handler.is_a?(Proc)
263
+ handler.method(:call).arity
264
+ end
265
+
262
266
  # INTERNAL USE ONLY
263
267
  def handle_exception(ex, ctx = {})
264
268
  if @options[:error_handlers].size == 0
265
269
  p ["!!!!!", ex]
266
270
  end
267
- ctx[:_config] = self
268
271
  @options[:error_handlers].each do |handler|
269
- handler.call(ex, ctx)
272
+ if arity(handler) == 2
273
+ # TODO Remove in 8.0
274
+ logger.info { "DEPRECATION: Sidekiq exception handlers now take three arguments, see #{handler}" }
275
+ handler.call(ex, {_config: self}.merge(ctx))
276
+ else
277
+ handler.call(ex, ctx, self)
278
+ end
270
279
  rescue Exception => e
271
280
  l = logger
272
281
  l.error "!!! ERROR HANDLER THREW AN ERROR !!!"
data/lib/sidekiq/rails.rb CHANGED
@@ -20,10 +20,6 @@ module Sidekiq
20
20
  def inspect
21
21
  "#<Sidekiq::Rails::Reloader @app=#{@app.class.name}>"
22
22
  end
23
-
24
- def to_json(*)
25
- Sidekiq.dump_json(inspect)
26
- end
27
23
  end
28
24
 
29
25
  # By including the Options module, we allow AJs to directly control sidekiq features
@@ -43,17 +39,6 @@ module Sidekiq
43
39
  end
44
40
  end
45
41
 
46
- initializer "sidekiq.rails_logger" do
47
- Sidekiq.configure_server do |config|
48
- # This is the integration code necessary so that if a job uses `Rails.logger.info "Hello"`,
49
- # it will appear in the Sidekiq console with all of the job context. See #5021 and
50
- # https://github.com/rails/rails/blob/b5f2b550f69a99336482739000c58e4e04e033aa/railties/lib/rails/commands/server/server_command.rb#L82-L84
51
- unless ::Rails.logger == config.logger || ::ActiveSupport::Logger.logger_outputs_to?(::Rails.logger, $stdout)
52
- ::Rails.logger.extend(::ActiveSupport::Logger.broadcast(config.logger))
53
- end
54
- end
55
- end
56
-
57
42
  initializer "sidekiq.backtrace_cleaner" do
58
43
  Sidekiq.configure_server do |config|
59
44
  config[:backtrace_cleaner] = ->(backtrace) { ::Rails.backtrace_cleaner.clean(backtrace) }
@@ -67,6 +52,16 @@ module Sidekiq
67
52
  config.after_initialize do
68
53
  Sidekiq.configure_server do |config|
69
54
  config[:reloader] = Sidekiq::Rails::Reloader.new
55
+
56
+ # This is the integration code necessary so that if a job uses `Rails.logger.info "Hello"`,
57
+ # it will appear in the Sidekiq console with all of the job context.
58
+ unless ::Rails.logger == config.logger || ::ActiveSupport::Logger.logger_outputs_to?(::Rails.logger, $stdout)
59
+ if ::Rails::VERSION::STRING < "7.1"
60
+ ::Rails.logger.extend(::ActiveSupport::Logger.broadcast(config.logger))
61
+ else
62
+ ::Rails.logger.broadcast_to(config.logger)
63
+ end
64
+ end
70
65
  end
71
66
  end
72
67
  end
@@ -63,8 +63,7 @@ module Sidekiq
63
63
  opts = options.dup
64
64
 
65
65
  if opts[:namespace]
66
- raise ArgumentError, "Your Redis configuration uses the namespace '#{opts[:namespace]}' but this feature isn't supported by redis-client. " \
67
- "Either use the redis adapter or remove the namespace."
66
+ raise ArgumentError, "Your Redis configuration uses the namespace '#{opts[:namespace]}' but this feature is no longer supported in Sidekiq 7+. See https://github.com/sidekiq/sidekiq/blob/main/docs/7.0-Upgrade.md#redis-namespace."
68
67
  end
69
68
 
70
69
  opts.delete(:size)
@@ -14,6 +14,7 @@ module Sidekiq
14
14
  logger = symbolized_options.delete(:logger)
15
15
  logger&.info { "Sidekiq #{Sidekiq::VERSION} connecting to Redis with options #{scrub(symbolized_options)}" }
16
16
 
17
+ raise "Sidekiq 7+ does not support Redis protocol 2" if symbolized_options[:protocol] == 2
17
18
  size = symbolized_options.delete(:size) || 5
18
19
  pool_timeout = symbolized_options.delete(:pool_timeout) || 1
19
20
  pool_name = symbolized_options.delete(:pool_name)
@@ -6,22 +6,35 @@ require "sidekiq"
6
6
  module Sidekiq
7
7
  class Testing
8
8
  class << self
9
- attr_accessor :__test_mode
9
+ attr_accessor :__global_test_mode
10
10
 
11
+ # Calling without a block sets the global test mode, affecting
12
+ # all threads. Calling with a block only affects the current Thread.
11
13
  def __set_test_mode(mode)
12
14
  if block_given?
13
- current_mode = __test_mode
14
15
  begin
15
- self.__test_mode = mode
16
+ self.__local_test_mode = mode
16
17
  yield
17
18
  ensure
18
- self.__test_mode = current_mode
19
+ self.__local_test_mode = nil
19
20
  end
20
21
  else
21
- self.__test_mode = mode
22
+ self.__global_test_mode = mode
22
23
  end
23
24
  end
24
25
 
26
+ def __test_mode
27
+ __local_test_mode || __global_test_mode
28
+ end
29
+
30
+ def __local_test_mode
31
+ Thread.current[:__sidekiq_test_mode]
32
+ end
33
+
34
+ def __local_test_mode=(value)
35
+ Thread.current[:__sidekiq_test_mode] = value
36
+ end
37
+
25
38
  def disable!(&block)
26
39
  __set_test_mode(:disable, &block)
27
40
  end
@@ -64,7 +77,7 @@ module Sidekiq
64
77
  class EmptyQueueError < RuntimeError; end
65
78
 
66
79
  module TestingClient
67
- def raw_push(payloads)
80
+ def atomic_push(conn, payloads)
68
81
  if Sidekiq::Testing.fake?
69
82
  payloads.each do |job|
70
83
  job = Sidekiq.load_json(Sidekiq.dump_json(job))
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sidekiq
4
- VERSION = "7.1.4"
4
+ VERSION = "7.1.6"
5
5
  MAJOR = 7
6
6
  end
@@ -328,6 +328,56 @@ module Sidekiq
328
328
  json Sidekiq::Stats.new.queues
329
329
  end
330
330
 
331
+ ########
332
+ # Filtering
333
+ get "/filter/retries" do
334
+ x = params[:substr]
335
+ return redirect "#{root_path}retries" unless x && x != ""
336
+
337
+ @retries = search(Sidekiq::RetrySet.new, params[:substr])
338
+ erb :retries
339
+ end
340
+
341
+ post "/filter/retries" do
342
+ x = params[:substr]
343
+ return redirect "#{root_path}retries" unless x && x != ""
344
+
345
+ @retries = search(Sidekiq::RetrySet.new, params[:substr])
346
+ erb :retries
347
+ end
348
+
349
+ get "/filter/scheduled" do
350
+ x = params[:substr]
351
+ return redirect "#{root_path}scheduled" unless x && x != ""
352
+
353
+ @scheduled = search(Sidekiq::ScheduledSet.new, params[:substr])
354
+ erb :scheduled
355
+ end
356
+
357
+ post "/filter/scheduled" do
358
+ x = params[:substr]
359
+ return redirect "#{root_path}scheduled" unless x && x != ""
360
+
361
+ @scheduled = search(Sidekiq::ScheduledSet.new, params[:substr])
362
+ erb :scheduled
363
+ end
364
+
365
+ get "/filter/dead" do
366
+ x = params[:substr]
367
+ return redirect "#{root_path}morgue" unless x && x != ""
368
+
369
+ @dead = search(Sidekiq::DeadSet.new, params[:substr])
370
+ erb :morgue
371
+ end
372
+
373
+ post "/filter/dead" do
374
+ x = params[:substr]
375
+ return redirect "#{root_path}morgue" unless x && x != ""
376
+
377
+ @dead = search(Sidekiq::DeadSet.new, params[:substr])
378
+ erb :morgue
379
+ end
380
+
331
381
  def call(env)
332
382
  action = self.class.match(env)
333
383
  return [404, {Rack::CONTENT_TYPE => "text/plain", Web::X_CASCADE => "pass"}, ["Not Found"]] unless action
@@ -49,8 +49,29 @@ module Sidekiq
49
49
  locale_files.select { |file| file =~ /\/#{lang}\.yml$/ }
50
50
  end
51
51
 
52
- # This is a hook for a Sidekiq Pro feature. Please don't touch.
53
- def filtering(*)
52
+ def search(jobset, substr)
53
+ resultset = jobset.scan(substr).to_a
54
+ @current_page = 1
55
+ @count = @total_size = resultset.size
56
+ resultset
57
+ end
58
+
59
+ def filtering(which)
60
+ erb(:filtering, locals: {which: which})
61
+ end
62
+
63
+ def filter_link(jid, within = "retries")
64
+ if within.nil?
65
+ ::Rack::Utils.escape_html(jid)
66
+ else
67
+ "<a href='#{root_path}filter/#{within}?substr=#{jid}'>#{::Rack::Utils.escape_html(jid)}</a>"
68
+ end
69
+ end
70
+
71
+ def display_tags(job, within = "retries")
72
+ job.tags.map { |tag|
73
+ "<span class='label label-info jobtag'>#{filter_link(tag, within)}</span>"
74
+ }.join(" ")
54
75
  end
55
76
 
56
77
  # This view helper provide ability display you html code in
@@ -111,13 +132,6 @@ module Sidekiq
111
132
  end
112
133
  end
113
134
 
114
- # within is used by Sidekiq Pro
115
- def display_tags(job, within = nil)
116
- job.tags.map { |tag|
117
- "<span class='label label-info jobtag'>#{::Rack::Utils.escape_html(tag)}</span>"
118
- }.join(" ")
119
- end
120
-
121
135
  # sidekiq/sidekiq#3243
122
136
  def unfiltered?
123
137
  yield unless env["PATH_INFO"].start_with?("/filter/")
data/web/locales/en.yml CHANGED
@@ -97,3 +97,5 @@ en:
97
97
  Context: Context
98
98
  Bucket: Bucket
99
99
  NoJobMetricsFound: No recent job metrics were found
100
+ Filter: Filter
101
+ AnyJobContent: Any job content
@@ -0,0 +1,7 @@
1
+ <div class="sm-col-3 pull-right" style="display: inline; margin: 25px 15px 0 0;">
2
+ <%= t('Filter') %>:
3
+ <form method="POST" action='<%= root_path %>filter/<%= which %>' style="display: inline-block">
4
+ <%= csrf_tag %>
5
+ <input class="search" type="search" name="substr" value="<%= h params[:substr] %>" placeholder="<%= t('AnyJobContent') %>"/>
6
+ </form>
7
+ </div>
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: 7.1.4
4
+ version: 7.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Perham
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-09-12 00:00:00.000000000 Z
11
+ date: 2023-10-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis-client
@@ -187,6 +187,7 @@ files:
187
187
  - web/views/busy.erb
188
188
  - web/views/dashboard.erb
189
189
  - web/views/dead.erb
190
+ - web/views/filtering.erb
190
191
  - web/views/layout.erb
191
192
  - web/views/metrics.erb
192
193
  - web/views/metrics_for_job.erb
@@ -222,7 +223,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
222
223
  - !ruby/object:Gem::Version
223
224
  version: '0'
224
225
  requirements: []
225
- rubygems_version: 3.4.7
226
+ rubygems_version: 3.4.20
226
227
  signing_key:
227
228
  specification_version: 4
228
229
  summary: Simple, efficient background processing for Ruby