sidekiq 8.0.10 → 8.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Changes.md +33 -0
- data/README.md +15 -0
- data/bin/lint-herb +13 -0
- data/bin/tui +5 -0
- data/lib/active_job/queue_adapters/sidekiq_adapter.rb +5 -2
- data/lib/generators/sidekiq/job_generator.rb +15 -3
- data/lib/sidekiq/api.rb +84 -41
- data/lib/sidekiq/cli.rb +1 -0
- data/lib/sidekiq/config.rb +3 -4
- data/lib/sidekiq/job.rb +2 -0
- data/lib/sidekiq/job_retry.rb +7 -3
- data/lib/sidekiq/launcher.rb +4 -4
- data/lib/sidekiq/scheduled.rb +4 -2
- data/lib/sidekiq/test_api.rb +331 -0
- data/lib/sidekiq/testing/inline.rb +2 -30
- data/lib/sidekiq/testing.rb +2 -334
- data/lib/sidekiq/tui.rb +1019 -0
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web/action.rb +1 -1
- data/lib/sidekiq/web/application.rb +2 -2
- data/lib/sidekiq/web/config.rb +3 -6
- data/lib/sidekiq/web/helpers.rb +12 -1
- data/lib/sidekiq/web.rb +23 -4
- data/lib/sidekiq.rb +7 -0
- data/sidekiq.gemspec +5 -5
- data/web/assets/javascripts/application.js +1 -1
- data/web/assets/stylesheets/style.css +0 -2
- data/web/views/{busy.erb → busy.html.erb} +1 -1
- data/web/views/{metrics.erb → metrics.html.erb} +3 -2
- metadata +38 -35
- data/lib/sidekiq/web/csrf_protection.rb +0 -183
- /data/web/views/{_footer.erb → _footer.html.erb} +0 -0
- /data/web/views/{_job_info.erb → _job_info.html.erb} +0 -0
- /data/web/views/{_metrics_period_select.erb → _metrics_period_select.html.erb} +0 -0
- /data/web/views/{_nav.erb → _nav.html.erb} +0 -0
- /data/web/views/{_paging.erb → _paging.html.erb} +0 -0
- /data/web/views/{_poll_link.erb → _poll_link.html.erb} +0 -0
- /data/web/views/{_summary.erb → _summary.html.erb} +0 -0
- /data/web/views/{dashboard.erb → dashboard.html.erb} +0 -0
- /data/web/views/{dead.erb → dead.html.erb} +0 -0
- /data/web/views/{filtering.erb → filtering.html.erb} +0 -0
- /data/web/views/{layout.erb → layout.html.erb} +0 -0
- /data/web/views/{metrics_for_job.erb → metrics_for_job.html.erb} +0 -0
- /data/web/views/{morgue.erb → morgue.html.erb} +0 -0
- /data/web/views/{profiles.erb → profiles.html.erb} +0 -0
- /data/web/views/{queue.erb → queue.html.erb} +0 -0
- /data/web/views/{queues.erb → queues.html.erb} +0 -0
- /data/web/views/{retries.erb → retries.html.erb} +0 -0
- /data/web/views/{retry.erb → retry.html.erb} +0 -0
- /data/web/views/{scheduled.erb → scheduled.html.erb} +0 -0
- /data/web/views/{scheduled_job_info.erb → scheduled_job_info.html.erb} +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4fb090d79e2cf2b320fdd47ee55a574a68a46b77a23db27b849ddb6f54acb00a
|
|
4
|
+
data.tar.gz: 4863ef28ecdd8ad2cd868caf2f47cc9302b8eb88f4ff9da4f2b5641beca50d88
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4ba71a2c43cec613337119cd29830339e213a8f876db4db84c62ac67890ee020ab841a4f7fe478f7f0fcd135571b885e54c9af12998ea6947ac51b543d52b42c
|
|
7
|
+
data.tar.gz: 9cabfc243aacec3c57c697b83374a5b934cc985c1e4ee86185a6faba7fe18f6540e3fa0b203c5dbfc0e22c03513f66e973be4152d8c8e12db29e97e21a94360f
|
data/Changes.md
CHANGED
|
@@ -2,6 +2,39 @@
|
|
|
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
|
+
8.1.1
|
|
6
|
+
----------
|
|
7
|
+
|
|
8
|
+
- Add new `Sidekiq.testing!(mode)` API [#6931]
|
|
9
|
+
Requiring code should not enable process-wide changes.
|
|
10
|
+
```ruby
|
|
11
|
+
# Old, implicit
|
|
12
|
+
require "sidekiq/testing"
|
|
13
|
+
# New, more explicit
|
|
14
|
+
Sidekiq.testing!(:fake)
|
|
15
|
+
```
|
|
16
|
+
- Fix race condition with Stop button in UI [#6935]
|
|
17
|
+
- Fix javascript error handler [#6893]
|
|
18
|
+
|
|
19
|
+
8.1.0
|
|
20
|
+
----------
|
|
21
|
+
|
|
22
|
+
- `retry_for` and `retry` are now mutually exclusive [#6878, Saidbek]
|
|
23
|
+
- `perform_inline` now enforces `strict_args!` [#6718, Saidbek]
|
|
24
|
+
- Integrate Herb linting for ERB templates [#6760, Saidbek]
|
|
25
|
+
- Remove CSRF code, use `Sec-Fetch-Site` header [#6874, deve1212]
|
|
26
|
+
- Allow custom Web UI `assets_path` for CDN purposes [#6865, stanhu]
|
|
27
|
+
- Upgrade to connection_pool 3.0
|
|
28
|
+
- Allow idle connection reaping after N seconds.
|
|
29
|
+
You can activate this **beta** feature like below.
|
|
30
|
+
Feedback requested: is this feature stable and useful for you in production?
|
|
31
|
+
This feature may or may not be enabled by default in Sidekiq 9.0.
|
|
32
|
+
```ruby
|
|
33
|
+
Sidekiq.configure_server do |cfg|
|
|
34
|
+
cfg.reap_idle_redis_connections(60)
|
|
35
|
+
end
|
|
36
|
+
```
|
|
37
|
+
|
|
5
38
|
8.0.10
|
|
6
39
|
----------
|
|
7
40
|
|
data/README.md
CHANGED
|
@@ -97,6 +97,21 @@ Contributing
|
|
|
97
97
|
|
|
98
98
|
See [the contributing guidelines](https://github.com/sidekiq/sidekiq/blob/main/.github/contributing.md).
|
|
99
99
|
|
|
100
|
+
### ERB Linting with HERB
|
|
101
|
+
|
|
102
|
+
This project uses [HERB](https://herb-tools.dev/) for ERB file linting and formatting. All ERB files have been renamed to use the `.html.erb` extension for better tooling support.
|
|
103
|
+
|
|
104
|
+
**Local Development:**
|
|
105
|
+
```bash
|
|
106
|
+
# Run HERB linting
|
|
107
|
+
bundle exec rake lint:herb
|
|
108
|
+
# or
|
|
109
|
+
bin/lint-herb
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**CI Integration:**
|
|
113
|
+
HERB linting is automatically run in CI to ensure all ERB files are properly formatted and free of parse errors.
|
|
114
|
+
|
|
100
115
|
License
|
|
101
116
|
-----------------
|
|
102
117
|
|
data/bin/lint-herb
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# HERB Linting Script
|
|
5
|
+
# Run this script to lint all ERB files in the project
|
|
6
|
+
# Usage: bin/lint-herb
|
|
7
|
+
|
|
8
|
+
require "bundler/setup"
|
|
9
|
+
|
|
10
|
+
puts "🔍 Running HERB linting on ERB files..."
|
|
11
|
+
puts
|
|
12
|
+
|
|
13
|
+
exec("bundle exec herb analyze web/views -n --no-log-file")
|
data/bin/tui
ADDED
|
@@ -61,10 +61,13 @@ begin
|
|
|
61
61
|
|
|
62
62
|
# @api private
|
|
63
63
|
def enqueue(job)
|
|
64
|
-
|
|
64
|
+
# NB: Active Job only serializes keys it recognizes. We
|
|
65
|
+
# cannot set arbitrary key/values here.
|
|
66
|
+
wrapper = Sidekiq::ActiveJob::Wrapper.set(
|
|
65
67
|
wrapped: job.class,
|
|
66
68
|
queue: job.queue_name
|
|
67
|
-
)
|
|
69
|
+
)
|
|
70
|
+
job.provider_job_id = wrapper.perform_async(job.serialize)
|
|
68
71
|
end
|
|
69
72
|
|
|
70
73
|
# @api private
|
|
@@ -14,7 +14,10 @@ module Sidekiq
|
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def create_job_file
|
|
17
|
-
template
|
|
17
|
+
template(
|
|
18
|
+
"job.rb.erb",
|
|
19
|
+
File.join(jobs_directory, class_path, "#{file_name}_job.rb")
|
|
20
|
+
)
|
|
18
21
|
end
|
|
19
22
|
|
|
20
23
|
def create_test_file
|
|
@@ -31,7 +34,8 @@ module Sidekiq
|
|
|
31
34
|
|
|
32
35
|
def create_job_spec
|
|
33
36
|
template_file = File.join(
|
|
34
|
-
"spec
|
|
37
|
+
"spec",
|
|
38
|
+
jobs_directory.gsub("app/", ""),
|
|
35
39
|
class_path,
|
|
36
40
|
"#{file_name}_job_spec.rb"
|
|
37
41
|
)
|
|
@@ -40,7 +44,8 @@ module Sidekiq
|
|
|
40
44
|
|
|
41
45
|
def create_job_test
|
|
42
46
|
template_file = File.join(
|
|
43
|
-
"test
|
|
47
|
+
"test",
|
|
48
|
+
jobs_directory.gsub("app/", ""),
|
|
44
49
|
class_path,
|
|
45
50
|
"#{file_name}_job_test.rb"
|
|
46
51
|
)
|
|
@@ -54,6 +59,13 @@ module Sidekiq
|
|
|
54
59
|
def test_framework
|
|
55
60
|
::Rails.application.config.generators.options[:rails][:test_framework]
|
|
56
61
|
end
|
|
62
|
+
|
|
63
|
+
# Can be set in an initializer or in application configuration
|
|
64
|
+
# with Rails.application.config.generators.options[:sidekiq][:jobs_directory] = "app/jobs"
|
|
65
|
+
# to change the directory that the job files are generated in to.
|
|
66
|
+
def jobs_directory
|
|
67
|
+
::Rails.application.config.generators.options[:sidekiq].fetch(:jobs_directory, "app/sidekiq")
|
|
68
|
+
end
|
|
57
69
|
end
|
|
58
70
|
end
|
|
59
71
|
end
|
data/lib/sidekiq/api.rb
CHANGED
|
@@ -17,12 +17,37 @@ require "sidekiq/metrics/query"
|
|
|
17
17
|
#
|
|
18
18
|
|
|
19
19
|
module Sidekiq
|
|
20
|
+
module ApiUtils
|
|
21
|
+
# @api private
|
|
22
|
+
# Calculate the latency in seconds for a job based on its enqueued timestamp
|
|
23
|
+
# @param job [Hash] the job hash
|
|
24
|
+
# @return [Float] latency in seconds
|
|
25
|
+
def calculate_latency(job)
|
|
26
|
+
timestamp = job["enqueued_at"] || job["created_at"]
|
|
27
|
+
return 0.0 unless timestamp
|
|
28
|
+
|
|
29
|
+
if timestamp.is_a?(Float)
|
|
30
|
+
# old format
|
|
31
|
+
Time.now.to_f - timestamp
|
|
32
|
+
else
|
|
33
|
+
now = ::Process.clock_gettime(::Process::CLOCK_REALTIME, :millisecond)
|
|
34
|
+
(now - timestamp) / 1000.0
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
20
39
|
# Retrieve runtime statistics from Redis regarding
|
|
21
40
|
# this Sidekiq cluster.
|
|
22
41
|
#
|
|
23
42
|
# stat = Sidekiq::Stats.new
|
|
24
43
|
# stat.processed
|
|
25
44
|
class Stats
|
|
45
|
+
QueueSummary = Data.define(:name, :size, :latency, :paused) do
|
|
46
|
+
alias_method :paused?, :paused
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
include ApiUtils
|
|
50
|
+
|
|
26
51
|
def initialize
|
|
27
52
|
fetch_stats_fast!
|
|
28
53
|
end
|
|
@@ -63,6 +88,7 @@ module Sidekiq
|
|
|
63
88
|
stat :default_queue_latency
|
|
64
89
|
end
|
|
65
90
|
|
|
91
|
+
# @return [Hash{String => Integer}] a hash of queue names to their lengths
|
|
66
92
|
def queues
|
|
67
93
|
Sidekiq.redis do |conn|
|
|
68
94
|
queues = conn.sscan("queues").to_a
|
|
@@ -78,6 +104,41 @@ module Sidekiq
|
|
|
78
104
|
end
|
|
79
105
|
end
|
|
80
106
|
|
|
107
|
+
# More detailed information about each queue: name, size, latency, paused status
|
|
108
|
+
# @return [Array<QueueSummary>]
|
|
109
|
+
def queue_summaries
|
|
110
|
+
Sidekiq.redis do |conn|
|
|
111
|
+
queues = conn.sscan("queues").to_a
|
|
112
|
+
return [] if queues.empty?
|
|
113
|
+
|
|
114
|
+
results = conn.pipelined { |pipeline|
|
|
115
|
+
queues.each do |queue|
|
|
116
|
+
pipeline.llen("queue:#{queue}")
|
|
117
|
+
pipeline.lindex("queue:#{queue}", -1)
|
|
118
|
+
pipeline.sismember("paused", queue)
|
|
119
|
+
end
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
queue_summaries = []
|
|
123
|
+
queues.each_with_index do |name, idx|
|
|
124
|
+
size = results[idx * 3]
|
|
125
|
+
last_item = results[idx * 3 + 1]
|
|
126
|
+
paused = results[idx * 3 + 2] > 0
|
|
127
|
+
|
|
128
|
+
latency = if last_item
|
|
129
|
+
job = Sidekiq.load_json(last_item)
|
|
130
|
+
calculate_latency(job)
|
|
131
|
+
else
|
|
132
|
+
0.0
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
queue_summaries << QueueSummary.new(name:, size:, latency:, paused:)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
queue_summaries.sort_by { |qd| -qd.size }
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
81
142
|
# O(1) redis calls
|
|
82
143
|
# @api private
|
|
83
144
|
def fetch_stats_fast!
|
|
@@ -100,19 +161,7 @@ module Sidekiq
|
|
|
100
161
|
{}
|
|
101
162
|
end
|
|
102
163
|
|
|
103
|
-
|
|
104
|
-
if enqueued_at
|
|
105
|
-
if enqueued_at.is_a?(Float)
|
|
106
|
-
# old format
|
|
107
|
-
now = Time.now.to_f
|
|
108
|
-
now - enqueued_at
|
|
109
|
-
else
|
|
110
|
-
now = ::Process.clock_gettime(::Process::CLOCK_REALTIME, :millisecond)
|
|
111
|
-
(now - enqueued_at) / 1000.0
|
|
112
|
-
end
|
|
113
|
-
else
|
|
114
|
-
0.0
|
|
115
|
-
end
|
|
164
|
+
calculate_latency(job)
|
|
116
165
|
else
|
|
117
166
|
0.0
|
|
118
167
|
end
|
|
@@ -235,6 +284,7 @@ module Sidekiq
|
|
|
235
284
|
# end
|
|
236
285
|
class Queue
|
|
237
286
|
include Enumerable
|
|
287
|
+
include ApiUtils
|
|
238
288
|
|
|
239
289
|
##
|
|
240
290
|
# Fetch all known queues within Redis.
|
|
@@ -245,6 +295,7 @@ module Sidekiq
|
|
|
245
295
|
end
|
|
246
296
|
|
|
247
297
|
attr_reader :name
|
|
298
|
+
alias_method :id, :name
|
|
248
299
|
|
|
249
300
|
# @param name [String] the name of the queue
|
|
250
301
|
def initialize(name = "default")
|
|
@@ -277,19 +328,7 @@ module Sidekiq
|
|
|
277
328
|
return 0.0 unless entry
|
|
278
329
|
|
|
279
330
|
job = Sidekiq.load_json(entry)
|
|
280
|
-
|
|
281
|
-
if enqueued_at
|
|
282
|
-
if enqueued_at.is_a?(Float)
|
|
283
|
-
# old format
|
|
284
|
-
now = Time.now.to_f
|
|
285
|
-
now - enqueued_at
|
|
286
|
-
else
|
|
287
|
-
now = ::Process.clock_gettime(::Process::CLOCK_REALTIME, :millisecond)
|
|
288
|
-
(now - enqueued_at) / 1000.0
|
|
289
|
-
end
|
|
290
|
-
else
|
|
291
|
-
0.0
|
|
292
|
-
end
|
|
331
|
+
calculate_latency(job)
|
|
293
332
|
end
|
|
294
333
|
|
|
295
334
|
def each
|
|
@@ -352,6 +391,8 @@ module Sidekiq
|
|
|
352
391
|
# The job should be considered immutable but may be
|
|
353
392
|
# removed from the queue via JobRecord#delete.
|
|
354
393
|
class JobRecord
|
|
394
|
+
include ApiUtils
|
|
395
|
+
|
|
355
396
|
# the parsed Hash of job data
|
|
356
397
|
# @!attribute [r] Item
|
|
357
398
|
attr_reader :item
|
|
@@ -478,17 +519,7 @@ module Sidekiq
|
|
|
478
519
|
end
|
|
479
520
|
|
|
480
521
|
def latency
|
|
481
|
-
|
|
482
|
-
if timestamp
|
|
483
|
-
if timestamp.is_a?(Float)
|
|
484
|
-
# old format
|
|
485
|
-
Time.now.to_f - timestamp
|
|
486
|
-
else
|
|
487
|
-
(::Process.clock_gettime(::Process::CLOCK_REALTIME, :millisecond) - timestamp) / 1000.0
|
|
488
|
-
end
|
|
489
|
-
else
|
|
490
|
-
0.0
|
|
491
|
-
end
|
|
522
|
+
calculate_latency(@item)
|
|
492
523
|
end
|
|
493
524
|
|
|
494
525
|
# Remove this job from the queue
|
|
@@ -553,17 +584,24 @@ module Sidekiq
|
|
|
553
584
|
# could be the scheduled time for it to run (e.g. scheduled set),
|
|
554
585
|
# or the expiration date after which the entry should be deleted (e.g. dead set).
|
|
555
586
|
class SortedEntry < JobRecord
|
|
556
|
-
attr_reader :score
|
|
557
587
|
attr_reader :parent
|
|
558
588
|
|
|
559
589
|
# :nodoc:
|
|
560
590
|
# @api private
|
|
561
591
|
def initialize(parent, score, item)
|
|
562
592
|
super(item)
|
|
563
|
-
@score =
|
|
593
|
+
@score = score
|
|
564
594
|
@parent = parent
|
|
565
595
|
end
|
|
566
596
|
|
|
597
|
+
def score
|
|
598
|
+
Float(@score)
|
|
599
|
+
end
|
|
600
|
+
|
|
601
|
+
def id
|
|
602
|
+
"#{@score}|#{item["jid"]}"
|
|
603
|
+
end
|
|
604
|
+
|
|
567
605
|
# The timestamp associated with this entry
|
|
568
606
|
def at
|
|
569
607
|
Time.at(score).utc
|
|
@@ -574,7 +612,7 @@ module Sidekiq
|
|
|
574
612
|
if @value
|
|
575
613
|
@parent.delete_by_value(@parent.name, @value)
|
|
576
614
|
else
|
|
577
|
-
@parent.delete_by_jid(score, jid)
|
|
615
|
+
@parent.delete_by_jid(@score, jid)
|
|
578
616
|
end
|
|
579
617
|
end
|
|
580
618
|
|
|
@@ -583,7 +621,7 @@ module Sidekiq
|
|
|
583
621
|
# @param at [Time] the new timestamp for this job
|
|
584
622
|
def reschedule(at)
|
|
585
623
|
Sidekiq.redis do |conn|
|
|
586
|
-
conn.zincrby(@parent.name, at.to_f -
|
|
624
|
+
conn.zincrby(@parent.name, at.to_f - score, Sidekiq.dump_json(@item))
|
|
587
625
|
end
|
|
588
626
|
end
|
|
589
627
|
|
|
@@ -1088,6 +1126,7 @@ module Sidekiq
|
|
|
1088
1126
|
def identity
|
|
1089
1127
|
self["identity"]
|
|
1090
1128
|
end
|
|
1129
|
+
alias_method :id, :identity
|
|
1091
1130
|
|
|
1092
1131
|
# deprecated, use capsules below
|
|
1093
1132
|
def queues
|
|
@@ -1161,6 +1200,10 @@ module Sidekiq
|
|
|
1161
1200
|
self["quiet"] == "true"
|
|
1162
1201
|
end
|
|
1163
1202
|
|
|
1203
|
+
def leader?
|
|
1204
|
+
Sidekiq.redis { |c| c.get("dear-leader") == identity }
|
|
1205
|
+
end
|
|
1206
|
+
|
|
1164
1207
|
private
|
|
1165
1208
|
|
|
1166
1209
|
def signal(sig)
|
data/lib/sidekiq/cli.rb
CHANGED
|
@@ -203,6 +203,7 @@ module Sidekiq # :nodoc:
|
|
|
203
203
|
},
|
|
204
204
|
# deprecated, use INFO
|
|
205
205
|
"TTIN" => ->(cli) {
|
|
206
|
+
cli.logger.error { "DEPRECATED: Please use the INFO signal for backtraces, support for TTIN will be removed in Sidekiq 9.0." }
|
|
206
207
|
Thread.list.each do |thread|
|
|
207
208
|
cli.logger.warn "Thread TID-#{(thread.object_id ^ ::Process.pid).to_s(36)} #{thread.name}"
|
|
208
209
|
if thread.backtrace
|
data/lib/sidekiq/config.rb
CHANGED
|
@@ -37,7 +37,7 @@ module Sidekiq
|
|
|
37
37
|
reloader: proc { |&block| block.call },
|
|
38
38
|
backtrace_cleaner: ->(backtrace) { backtrace },
|
|
39
39
|
logged_job_attributes: ["bid", "tags"],
|
|
40
|
-
|
|
40
|
+
redis_idle_timeout: nil
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
ERROR_HANDLER = ->(ex, ctx, cfg = Sidekiq.default_configuration) {
|
|
@@ -146,10 +146,9 @@ module Sidekiq
|
|
|
146
146
|
@redis_config = @redis_config.merge(hash)
|
|
147
147
|
end
|
|
148
148
|
|
|
149
|
-
def reap_idle_redis_connections(timeout =
|
|
150
|
-
self[:
|
|
149
|
+
def reap_idle_redis_connections(timeout = 60)
|
|
150
|
+
self[:redis_idle_timeout] = timeout
|
|
151
151
|
end
|
|
152
|
-
alias_method :reap, :reap_idle_redis_connections
|
|
153
152
|
|
|
154
153
|
def redis_pool
|
|
155
154
|
Thread.current[:sidekiq_redis_pool] || Thread.current[:sidekiq_capsule]&.redis_pool || local_redis_pool
|
data/lib/sidekiq/job.rb
CHANGED
data/lib/sidekiq/job_retry.rb
CHANGED
|
@@ -178,10 +178,14 @@ module Sidekiq
|
|
|
178
178
|
msg["error_backtrace"] = compress_backtrace(lines)
|
|
179
179
|
end
|
|
180
180
|
|
|
181
|
-
|
|
182
|
-
|
|
181
|
+
# retry_for and retry are mutually exclusive - if retry_for is set,
|
|
182
|
+
# we exclusively use duration-based retry logic and ignore count-based logic
|
|
183
183
|
rf = msg["retry_for"]
|
|
184
|
-
|
|
184
|
+
if rf
|
|
185
|
+
return retries_exhausted(jobinst, msg, exception) if (time_for(msg["failed_at"]) + rf) < Time.now
|
|
186
|
+
elsif count >= max_retry_attempts
|
|
187
|
+
return retries_exhausted(jobinst, msg, exception)
|
|
188
|
+
end
|
|
185
189
|
|
|
186
190
|
strategy, delay = delay_for(jobinst, count, exception, msg)
|
|
187
191
|
case strategy
|
data/lib/sidekiq/launcher.rb
CHANGED
|
@@ -142,10 +142,10 @@ module Sidekiq
|
|
|
142
142
|
key = identity
|
|
143
143
|
fails = procd = 0
|
|
144
144
|
|
|
145
|
-
|
|
146
|
-
if
|
|
147
|
-
config.capsules.each_value { |cap| cap.local_redis_pool.reap(
|
|
148
|
-
config.local_redis_pool.reap(
|
|
145
|
+
idle_timeout = config[:redis_idle_timeout]
|
|
146
|
+
if idle_timeout
|
|
147
|
+
config.capsules.each_value { |cap| cap.local_redis_pool.reap(idle_seconds: idle_timeout, &:close) }
|
|
148
|
+
config.local_redis_pool.reap(idle_seconds: idle_timeout, &:close)
|
|
149
149
|
end
|
|
150
150
|
|
|
151
151
|
begin
|
data/lib/sidekiq/scheduled.rb
CHANGED
|
@@ -72,6 +72,7 @@ module Sidekiq
|
|
|
72
72
|
include Sidekiq::Component
|
|
73
73
|
|
|
74
74
|
INITIAL_WAIT = 10
|
|
75
|
+
attr_accessor :rnd
|
|
75
76
|
|
|
76
77
|
def initialize(config)
|
|
77
78
|
@config = config
|
|
@@ -80,6 +81,7 @@ module Sidekiq
|
|
|
80
81
|
@done = false
|
|
81
82
|
@thread = nil
|
|
82
83
|
@count_calls = 0
|
|
84
|
+
@rnd = Random.new
|
|
83
85
|
end
|
|
84
86
|
|
|
85
87
|
# Shut down this instance, will pause until the thread is dead.
|
|
@@ -151,11 +153,11 @@ module Sidekiq
|
|
|
151
153
|
|
|
152
154
|
if count < 10
|
|
153
155
|
# For small clusters, calculate a random interval that is ±50% the desired average.
|
|
154
|
-
interval * rand + interval.to_f / 2
|
|
156
|
+
interval * @rnd.rand + interval.to_f / 2
|
|
155
157
|
else
|
|
156
158
|
# With 10+ processes, we should have enough randomness to get decent polling
|
|
157
159
|
# across the entire timespan
|
|
158
|
-
interval * rand * 2
|
|
160
|
+
interval * @rnd.rand * 2
|
|
159
161
|
end
|
|
160
162
|
end
|
|
161
163
|
|