sidekiq 7.3.2 → 7.3.5
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 +39 -1
- data/lib/active_job/queue_adapters/sidekiq_adapter.rb +88 -0
- data/lib/sidekiq/api.rb +54 -31
- data/lib/sidekiq/capsule.rb +3 -3
- data/lib/sidekiq/client.rb +17 -0
- data/lib/sidekiq/config.rb +14 -2
- data/lib/sidekiq/job/iterable.rb +69 -6
- data/lib/sidekiq/job_logger.rb +10 -20
- data/lib/sidekiq/launcher.rb +1 -1
- data/lib/sidekiq/metrics/shared.rb +14 -5
- data/lib/sidekiq/middleware/current_attributes.rb +17 -2
- data/lib/sidekiq/processor.rb +10 -10
- data/lib/sidekiq/rails.rb +2 -0
- data/lib/sidekiq/testing.rb +5 -5
- data/lib/sidekiq/version.rb +5 -1
- data/lib/sidekiq/web/action.rb +6 -2
- data/lib/sidekiq/web/application.rb +6 -32
- data/lib/sidekiq/web/router.rb +5 -2
- data/lib/sidekiq/web.rb +1 -1
- data/lib/sidekiq.rb +4 -3
- data/sidekiq.gemspec +0 -1
- data/web/assets/stylesheets/application.css +5 -0
- data/web/locales/en.yml +0 -1
- data/web/locales/fr.yml +0 -1
- data/web/locales/gd.yml +0 -1
- data/web/locales/it.yml +32 -1
- data/web/locales/ja.yml +0 -1
- data/web/locales/pt-br.yml +1 -2
- data/web/locales/tr.yml +0 -1
- data/web/locales/uk.yml +24 -1
- data/web/locales/zh-cn.yml +0 -1
- data/web/locales/zh-tw.yml +0 -1
- data/web/views/metrics.erb +2 -2
- metadata +4 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ada259b22664fbbb740c3d28fa06578cb6fc00a42590ea459a1f2395f8e38a92
|
4
|
+
data.tar.gz: 0636466a99e8a0df4d955b0928d76b504df74bba4e3ab13a2d08237ccd57b162
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 209f76b8ceebdb2cac83d22aab78873dad373a9ba488e7d320972e8ced4d3ac71454ef6669db321727ce3e4a85fdc5744005ff64d1a0f4cd48d9a4231bddf384
|
7
|
+
data.tar.gz: df094fd4baa169249e92309814d67d0fb5a53b5da4990c0510f5ae1d96e07541356a3014f75b8b79a97f0a91b03b92b576331422c54f36bb2c4943f2f0f87b08
|
data/Changes.md
CHANGED
@@ -2,12 +2,50 @@
|
|
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.3.5
|
6
|
+
----------
|
7
|
+
|
8
|
+
- Reimplement `retry_all` and `kill_all` API methods to use ZPOPMIN,
|
9
|
+
approximately 30-60% faster. [#6481]
|
10
|
+
- Add preload testing binary at `examples/testing/sidekiq_boot` to verify your Rails app boots correctly with Sidekiq Enterprise's app preloading.
|
11
|
+
- Fix circular require with ActiveJob adapter [#6477]
|
12
|
+
- Fix potential race condition leading to incorrect serialized values for CurrentAttributes [#6475]
|
13
|
+
- Restore missing elapsed time when default job logging is disabled
|
14
|
+
|
15
|
+
7.3.4
|
16
|
+
----------
|
17
|
+
|
18
|
+
- Fix FrozenError when starting Sidekiq [#6470]
|
19
|
+
|
20
|
+
7.3.3
|
21
|
+
----------
|
22
|
+
|
23
|
+
- Freeze global configuration once boot is complete, to avoid configuration race conditions [#6466, #6465]
|
24
|
+
- Sidekiq now warns if a job iteration takes longer than the `-t` timeout setting (defaults to 25 seconds)
|
25
|
+
- Iteration callbacks now have easy access to job arguments via the `arguments` method:
|
26
|
+
```ruby
|
27
|
+
def on_stop
|
28
|
+
p arguments # => `[123, "string", {"key" => "value"}]`
|
29
|
+
id, str, hash = arguments
|
30
|
+
end
|
31
|
+
```
|
32
|
+
- Iterable jobs can be cancelled via `Sidekiq::Client#cancel!`:
|
33
|
+
```ruby
|
34
|
+
c = Sidekiq::Client.new
|
35
|
+
jid = c.push("class" => SomeJob, "args" => [123])
|
36
|
+
c.cancel!(jid) # => true
|
37
|
+
```
|
38
|
+
- Take over support for ActiveJob's `:sidekiq` adapter [#6430, fatkodima]
|
39
|
+
- Ensure CurrentAttributes are in scope when creating batch callbacks [#6455]
|
40
|
+
- Add `Sidekiq.gem_version` API.
|
41
|
+
- Update Ukranian translations
|
42
|
+
|
5
43
|
7.3.2
|
6
44
|
----------
|
7
45
|
|
8
46
|
- Adjust ActiveRecord batch iteration to restart an interrupted batch from the beginning.
|
9
47
|
Each batch should be processed as a single transaction in order to be idempotent. [#6405]
|
10
|
-
- Fix typo in
|
48
|
+
- Fix typo in Sidekiq::DeadSet#kill [#6397]
|
11
49
|
- Fix CSS issue with bottom bar in Web UI [#6414]
|
12
50
|
|
13
51
|
7.3.1
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sidekiq
|
4
|
+
module ActiveJob
|
5
|
+
# @api private
|
6
|
+
class Wrapper
|
7
|
+
include Sidekiq::Job
|
8
|
+
|
9
|
+
def perform(job_data)
|
10
|
+
::ActiveJob::Base.execute(job_data.merge("provider_job_id" => jid))
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module ActiveJob
|
17
|
+
module QueueAdapters
|
18
|
+
# Explicitly remove the implementation existing in older rails'.
|
19
|
+
remove_const(:SidekiqAdapter) if defined?("::#{name}::SidekiqAdapter")
|
20
|
+
|
21
|
+
# Sidekiq adapter for Active Job
|
22
|
+
#
|
23
|
+
# To use Sidekiq set the queue_adapter config to +:sidekiq+.
|
24
|
+
#
|
25
|
+
# Rails.application.config.active_job.queue_adapter = :sidekiq
|
26
|
+
class SidekiqAdapter
|
27
|
+
# Defines whether enqueuing should happen implicitly to after commit when called
|
28
|
+
# from inside a transaction.
|
29
|
+
# @api private
|
30
|
+
def enqueue_after_transaction_commit?
|
31
|
+
true
|
32
|
+
end
|
33
|
+
|
34
|
+
# @api private
|
35
|
+
def enqueue(job)
|
36
|
+
job.provider_job_id = JobWrapper.set(
|
37
|
+
wrapped: job.class,
|
38
|
+
queue: job.queue_name
|
39
|
+
).perform_async(job.serialize)
|
40
|
+
end
|
41
|
+
|
42
|
+
# @api private
|
43
|
+
def enqueue_at(job, timestamp)
|
44
|
+
job.provider_job_id = JobWrapper.set(
|
45
|
+
wrapped: job.class,
|
46
|
+
queue: job.queue_name
|
47
|
+
).perform_at(timestamp, job.serialize)
|
48
|
+
end
|
49
|
+
|
50
|
+
# @api private
|
51
|
+
def enqueue_all(jobs)
|
52
|
+
enqueued_count = 0
|
53
|
+
jobs.group_by(&:class).each do |job_class, same_class_jobs|
|
54
|
+
same_class_jobs.group_by(&:queue_name).each do |queue, same_class_and_queue_jobs|
|
55
|
+
immediate_jobs, scheduled_jobs = same_class_and_queue_jobs.partition { |job| job.scheduled_at.nil? }
|
56
|
+
|
57
|
+
if immediate_jobs.any?
|
58
|
+
jids = Sidekiq::Client.push_bulk(
|
59
|
+
"class" => JobWrapper,
|
60
|
+
"wrapped" => job_class,
|
61
|
+
"queue" => queue,
|
62
|
+
"args" => immediate_jobs.map { |job| [job.serialize] }
|
63
|
+
)
|
64
|
+
enqueued_count += jids.compact.size
|
65
|
+
end
|
66
|
+
|
67
|
+
if scheduled_jobs.any?
|
68
|
+
jids = Sidekiq::Client.push_bulk(
|
69
|
+
"class" => JobWrapper,
|
70
|
+
"wrapped" => job_class,
|
71
|
+
"queue" => queue,
|
72
|
+
"args" => scheduled_jobs.map { |job| [job.serialize] },
|
73
|
+
"at" => scheduled_jobs.map { |job| job.scheduled_at&.to_f }
|
74
|
+
)
|
75
|
+
enqueued_count += jids.compact.size
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
enqueued_count
|
80
|
+
end
|
81
|
+
|
82
|
+
# Defines a class alias for backwards compatibility with enqueued Active Job jobs.
|
83
|
+
# @api private
|
84
|
+
class JobWrapper < Sidekiq::ActiveJob::Wrapper
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
data/lib/sidekiq/api.rb
CHANGED
@@ -373,7 +373,7 @@ module Sidekiq
|
|
373
373
|
def display_class
|
374
374
|
# Unwrap known wrappers so they show up in a human-friendly manner in the Web UI
|
375
375
|
@klass ||= self["display_class"] || begin
|
376
|
-
if klass == "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper"
|
376
|
+
if klass == "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper" || klass == "Sidekiq::ActiveJob::Wrapper"
|
377
377
|
job_class = @item["wrapped"] || args[0]
|
378
378
|
if job_class == "ActionMailer::DeliveryJob" || job_class == "ActionMailer::MailDeliveryJob"
|
379
379
|
# MailerClass#mailer_method
|
@@ -389,7 +389,7 @@ module Sidekiq
|
|
389
389
|
|
390
390
|
def display_args
|
391
391
|
# Unwrap known wrappers so they show up in a human-friendly manner in the Web UI
|
392
|
-
@display_args ||= if klass == "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper"
|
392
|
+
@display_args ||= if klass == "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper" || klass == "Sidekiq::ActiveJob::Wrapper"
|
393
393
|
job_args = self["wrapped"] ? deserialize_argument(args[0]["arguments"]) : []
|
394
394
|
if (self["wrapped"] || args[0]) == "ActionMailer::DeliveryJob"
|
395
395
|
# remove MailerClass, mailer_method and 'deliver_now'
|
@@ -668,6 +668,41 @@ module Sidekiq
|
|
668
668
|
end
|
669
669
|
end
|
670
670
|
|
671
|
+
def pop_each
|
672
|
+
Sidekiq.redis do |c|
|
673
|
+
size.times do
|
674
|
+
data, score = c.zpopmin(name, 1)&.first
|
675
|
+
break unless data
|
676
|
+
yield data, score
|
677
|
+
end
|
678
|
+
end
|
679
|
+
end
|
680
|
+
|
681
|
+
def retry_all
|
682
|
+
c = Sidekiq::Client.new
|
683
|
+
pop_each do |msg, _|
|
684
|
+
job = Sidekiq.load_json(msg)
|
685
|
+
# Manual retries should not count against the retry limit.
|
686
|
+
job["retry_count"] -= 1 if job["retry_count"]
|
687
|
+
c.push(job)
|
688
|
+
end
|
689
|
+
end
|
690
|
+
|
691
|
+
# Move all jobs from this Set to the Dead Set.
|
692
|
+
# See DeadSet#kill
|
693
|
+
def kill_all(notify_failure: false, ex: nil)
|
694
|
+
ds = DeadSet.new
|
695
|
+
opts = {notify_failure: notify_failure, ex: ex, trim: false}
|
696
|
+
|
697
|
+
begin
|
698
|
+
pop_each do |msg, _|
|
699
|
+
ds.kill(msg, opts)
|
700
|
+
end
|
701
|
+
ensure
|
702
|
+
ds.trim
|
703
|
+
end
|
704
|
+
end
|
705
|
+
|
671
706
|
def each
|
672
707
|
initial_size = @_size
|
673
708
|
offset_size = 0
|
@@ -765,10 +800,6 @@ module Sidekiq
|
|
765
800
|
|
766
801
|
##
|
767
802
|
# The set of scheduled jobs within Sidekiq.
|
768
|
-
# Based on this, you can search/filter for jobs. Here's an
|
769
|
-
# example where I'm selecting jobs based on some complex logic
|
770
|
-
# and deleting them from the scheduled set.
|
771
|
-
#
|
772
803
|
# See the API wiki page for usage notes and examples.
|
773
804
|
#
|
774
805
|
class ScheduledSet < JobSet
|
@@ -779,26 +810,12 @@ module Sidekiq
|
|
779
810
|
|
780
811
|
##
|
781
812
|
# The set of retries within Sidekiq.
|
782
|
-
# Based on this, you can search/filter for jobs. Here's an
|
783
|
-
# example where I'm selecting all jobs of a certain type
|
784
|
-
# and deleting them from the retry queue.
|
785
|
-
#
|
786
813
|
# See the API wiki page for usage notes and examples.
|
787
814
|
#
|
788
815
|
class RetrySet < JobSet
|
789
816
|
def initialize
|
790
817
|
super("retry")
|
791
818
|
end
|
792
|
-
|
793
|
-
# Enqueues all jobs pending within the retry set.
|
794
|
-
def retry_all
|
795
|
-
each(&:retry) while size > 0
|
796
|
-
end
|
797
|
-
|
798
|
-
# Kills all jobs pending within the retry set.
|
799
|
-
def kill_all
|
800
|
-
each(&:kill) while size > 0
|
801
|
-
end
|
802
819
|
end
|
803
820
|
|
804
821
|
##
|
@@ -811,20 +828,31 @@ module Sidekiq
|
|
811
828
|
super("dead")
|
812
829
|
end
|
813
830
|
|
831
|
+
# Trim dead jobs which are over our storage limits
|
832
|
+
def trim
|
833
|
+
hash = Sidekiq.default_configuration
|
834
|
+
now = Time.now.to_f
|
835
|
+
Sidekiq.redis do |conn|
|
836
|
+
conn.multi do |transaction|
|
837
|
+
transaction.zremrangebyscore(name, "-inf", now - hash[:dead_timeout_in_seconds])
|
838
|
+
transaction.zremrangebyrank(name, 0, - hash[:dead_max_jobs])
|
839
|
+
end
|
840
|
+
end
|
841
|
+
end
|
842
|
+
|
814
843
|
# Add the given job to the Dead set.
|
815
844
|
# @param message [String] the job data as JSON
|
816
|
-
# @option opts [Boolean] :notify_failure
|
845
|
+
# @option opts [Boolean] :notify_failure (true) Whether death handlers should be called
|
846
|
+
# @option opts [Boolean] :trim (true) Whether Sidekiq should trim the structure to keep it within configuration
|
817
847
|
# @option opts [Exception] :ex (RuntimeError) An exception to pass to the death handlers
|
818
848
|
def kill(message, opts = {})
|
819
849
|
now = Time.now.to_f
|
820
850
|
Sidekiq.redis do |conn|
|
821
|
-
conn.
|
822
|
-
transaction.zadd(name, now.to_s, message)
|
823
|
-
transaction.zremrangebyscore(name, "-inf", now - Sidekiq::Config::DEFAULTS[:dead_timeout_in_seconds])
|
824
|
-
transaction.zremrangebyrank(name, 0, - Sidekiq::Config::DEFAULTS[:dead_max_jobs])
|
825
|
-
end
|
851
|
+
conn.zadd(name, now.to_s, message)
|
826
852
|
end
|
827
853
|
|
854
|
+
trim if opts[:trim] != false
|
855
|
+
|
828
856
|
if opts[:notify_failure] != false
|
829
857
|
job = Sidekiq.load_json(message)
|
830
858
|
if opts[:ex]
|
@@ -839,11 +867,6 @@ module Sidekiq
|
|
839
867
|
end
|
840
868
|
true
|
841
869
|
end
|
842
|
-
|
843
|
-
# Enqueue all dead jobs
|
844
|
-
def retry_all
|
845
|
-
each(&:retry) while size > 0
|
846
|
-
end
|
847
870
|
end
|
848
871
|
|
849
872
|
##
|
data/lib/sidekiq/capsule.rb
CHANGED
@@ -40,9 +40,9 @@ module Sidekiq
|
|
40
40
|
|
41
41
|
def fetcher
|
42
42
|
@fetcher ||= begin
|
43
|
-
|
44
|
-
|
45
|
-
|
43
|
+
instance = (config[:fetch_class] || Sidekiq::BasicFetch).new(self)
|
44
|
+
instance.setup(config[:fetch_setup]) if instance.respond_to?(:setup)
|
45
|
+
instance
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
data/lib/sidekiq/client.rb
CHANGED
@@ -58,6 +58,23 @@ module Sidekiq
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
+
# Cancel the IterableJob with the given JID.
|
62
|
+
# **NB: Cancellation is asynchronous.** Iteration checks every
|
63
|
+
# five seconds so this will not immediately stop the given job.
|
64
|
+
def cancel!(jid)
|
65
|
+
key = "it-#{jid}"
|
66
|
+
_, result, _ = Sidekiq.redis do |c|
|
67
|
+
c.pipelined do |p|
|
68
|
+
p.hsetnx(key, "cancelled", Time.now.to_i)
|
69
|
+
p.hget(key, "cancelled")
|
70
|
+
p.expire(key, Sidekiq::Job::Iterable::STATE_TTL)
|
71
|
+
# TODO When Redis 7.2 is required
|
72
|
+
# p.expire(key, Sidekiq::Job::Iterable::STATE_TTL, "nx")
|
73
|
+
end
|
74
|
+
end
|
75
|
+
result.to_i
|
76
|
+
end
|
77
|
+
|
61
78
|
##
|
62
79
|
# The main method used to push a job to Redis. Accepts a number of options:
|
63
80
|
#
|
data/lib/sidekiq/config.rb
CHANGED
@@ -185,7 +185,13 @@ module Sidekiq
|
|
185
185
|
|
186
186
|
# register global singletons which can be accessed elsewhere
|
187
187
|
def register(name, instance)
|
188
|
-
|
188
|
+
# logger.debug("register[#{name}] = #{instance}")
|
189
|
+
# Sidekiq Enterprise lazy registers a few services so we
|
190
|
+
# can't lock down this hash completely.
|
191
|
+
hash = @directory.dup
|
192
|
+
hash[name] = instance
|
193
|
+
@directory = hash.freeze
|
194
|
+
instance
|
189
195
|
end
|
190
196
|
|
191
197
|
# find a singleton
|
@@ -193,10 +199,16 @@ module Sidekiq
|
|
193
199
|
# JNDI is just a fancy name for a hash lookup
|
194
200
|
@directory.fetch(name) do |key|
|
195
201
|
return nil unless default_class
|
196
|
-
|
202
|
+
register(key, default_class.new(self))
|
197
203
|
end
|
198
204
|
end
|
199
205
|
|
206
|
+
def freeze!
|
207
|
+
@directory.freeze
|
208
|
+
@options.freeze
|
209
|
+
true
|
210
|
+
end
|
211
|
+
|
200
212
|
##
|
201
213
|
# Death handlers are called when all retries for a job have been exhausted and
|
202
214
|
# the job dies. It's the notification to your application
|
data/lib/sidekiq/job/iterable.rb
CHANGED
@@ -30,6 +30,40 @@ module Sidekiq
|
|
30
30
|
@_cursor = nil
|
31
31
|
@_start_time = nil
|
32
32
|
@_runtime = 0
|
33
|
+
@_args = nil
|
34
|
+
@_cancelled = nil
|
35
|
+
end
|
36
|
+
|
37
|
+
def arguments
|
38
|
+
@_args
|
39
|
+
end
|
40
|
+
|
41
|
+
# Three days is the longest period you generally need to wait for a retry to
|
42
|
+
# execute when using the default retry scheme. We don't want to "forget" the job
|
43
|
+
# is cancelled before it has a chance to execute and cancel itself.
|
44
|
+
CANCELLATION_PERIOD = (3 * 86_400).to_s
|
45
|
+
|
46
|
+
# Set a flag in Redis to mark this job as cancelled.
|
47
|
+
# Cancellation is asynchronous and is checked at the start of iteration
|
48
|
+
# and every 5 seconds thereafter as part of the recurring state flush.
|
49
|
+
def cancel!
|
50
|
+
return @_cancelled if cancelled?
|
51
|
+
|
52
|
+
key = "it-#{jid}"
|
53
|
+
_, result, _ = Sidekiq.redis do |c|
|
54
|
+
c.pipelined do |p|
|
55
|
+
p.hsetnx(key, "cancelled", Time.now.to_i)
|
56
|
+
p.hget(key, "cancelled")
|
57
|
+
# TODO When Redis 7.2 is required
|
58
|
+
# p.expire(key, Sidekiq::Job::Iterable::STATE_TTL, "nx")
|
59
|
+
p.expire(key, Sidekiq::Job::Iterable::STATE_TTL)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
@_cancelled = result.to_i
|
63
|
+
end
|
64
|
+
|
65
|
+
def cancelled?
|
66
|
+
@_cancelled
|
33
67
|
end
|
34
68
|
|
35
69
|
# A hook to override that will be called when the job starts iterating.
|
@@ -91,13 +125,14 @@ module Sidekiq
|
|
91
125
|
end
|
92
126
|
|
93
127
|
# @api private
|
94
|
-
def perform(*
|
128
|
+
def perform(*args)
|
129
|
+
@_args = args.dup.freeze
|
95
130
|
fetch_previous_iteration_state
|
96
131
|
|
97
132
|
@_executions += 1
|
98
133
|
@_start_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
99
134
|
|
100
|
-
enumerator = build_enumerator(*
|
135
|
+
enumerator = build_enumerator(*args, cursor: @_cursor)
|
101
136
|
unless enumerator
|
102
137
|
logger.info("'#build_enumerator' returned nil, skipping the job.")
|
103
138
|
return
|
@@ -112,7 +147,7 @@ module Sidekiq
|
|
112
147
|
end
|
113
148
|
|
114
149
|
completed = catch(:abort) do
|
115
|
-
iterate_with_enumerator(enumerator,
|
150
|
+
iterate_with_enumerator(enumerator, args)
|
116
151
|
end
|
117
152
|
|
118
153
|
on_stop
|
@@ -128,6 +163,10 @@ module Sidekiq
|
|
128
163
|
|
129
164
|
private
|
130
165
|
|
166
|
+
def is_cancelled?
|
167
|
+
@_cancelled = Sidekiq.redis { |c| c.hget("it-#{jid}", "cancelled") }
|
168
|
+
end
|
169
|
+
|
131
170
|
def fetch_previous_iteration_state
|
132
171
|
state = Sidekiq.redis { |conn| conn.hgetall(iteration_key) }
|
133
172
|
|
@@ -144,6 +183,12 @@ module Sidekiq
|
|
144
183
|
STATE_TTL = 30 * 24 * 60 * 60 # one month
|
145
184
|
|
146
185
|
def iterate_with_enumerator(enumerator, arguments)
|
186
|
+
if is_cancelled?
|
187
|
+
logger.info { "Job cancelled" }
|
188
|
+
return true
|
189
|
+
end
|
190
|
+
|
191
|
+
time_limit = Sidekiq.default_configuration[:timeout]
|
147
192
|
found_record = false
|
148
193
|
state_flushed_at = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
149
194
|
|
@@ -153,14 +198,21 @@ module Sidekiq
|
|
153
198
|
|
154
199
|
is_interrupted = interrupted?
|
155
200
|
if ::Process.clock_gettime(::Process::CLOCK_MONOTONIC) - state_flushed_at >= STATE_FLUSH_INTERVAL || is_interrupted
|
156
|
-
flush_state
|
201
|
+
_, _, cancelled = flush_state
|
157
202
|
state_flushed_at = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
203
|
+
if cancelled == 1
|
204
|
+
@_cancelled = true
|
205
|
+
logger.info { "Job cancelled" }
|
206
|
+
return true
|
207
|
+
end
|
158
208
|
end
|
159
209
|
|
160
210
|
return false if is_interrupted
|
161
211
|
|
162
|
-
|
163
|
-
|
212
|
+
verify_iteration_time(time_limit, object) do
|
213
|
+
around_iteration do
|
214
|
+
each_iteration(object, *arguments)
|
215
|
+
end
|
164
216
|
end
|
165
217
|
end
|
166
218
|
|
@@ -170,6 +222,16 @@ module Sidekiq
|
|
170
222
|
@_runtime += (::Process.clock_gettime(::Process::CLOCK_MONOTONIC) - @_start_time)
|
171
223
|
end
|
172
224
|
|
225
|
+
def verify_iteration_time(time_limit, object)
|
226
|
+
start = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
227
|
+
yield
|
228
|
+
finish = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
229
|
+
total = finish - start
|
230
|
+
if total > time_limit
|
231
|
+
logger.warn { "Iteration took longer (%.2f) than Sidekiq's shutdown timeout (%d) when processing `%s`. This can lead to job processing problems during deploys" % [total, time_limit, object] }
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
173
235
|
def reenqueue_iteration_job
|
174
236
|
flush_state
|
175
237
|
logger.debug { "Interrupting job (cursor=#{@_cursor.inspect})" }
|
@@ -204,6 +266,7 @@ module Sidekiq
|
|
204
266
|
conn.multi do |pipe|
|
205
267
|
pipe.hset(key, state)
|
206
268
|
pipe.expire(key, STATE_TTL)
|
269
|
+
pipe.hget(key, "cancelled")
|
207
270
|
end
|
208
271
|
end
|
209
272
|
end
|
data/lib/sidekiq/job_logger.rb
CHANGED
@@ -5,31 +5,21 @@ module Sidekiq
|
|
5
5
|
def initialize(config)
|
6
6
|
@config = config
|
7
7
|
@logger = @config.logger
|
8
|
-
|
9
|
-
|
10
|
-
# If true we won't do any job logging out of the box.
|
11
|
-
# The user is responsible for any logging.
|
12
|
-
def skip_default_logging?
|
13
|
-
@config[:skip_default_job_logging]
|
8
|
+
@skip = !!@config[:skip_default_job_logging]
|
14
9
|
end
|
15
10
|
|
16
11
|
def call(item, queue)
|
17
|
-
|
18
|
-
|
19
|
-
begin
|
20
|
-
start = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
21
|
-
@logger.info("start")
|
12
|
+
start = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
13
|
+
@logger.info { "start" } unless @skip
|
22
14
|
|
23
|
-
|
24
|
-
|
25
|
-
Sidekiq::Context.add(:elapsed, elapsed(start))
|
26
|
-
@logger.info("done")
|
27
|
-
rescue Exception
|
28
|
-
Sidekiq::Context.add(:elapsed, elapsed(start))
|
29
|
-
@logger.info("fail")
|
15
|
+
yield
|
30
16
|
|
31
|
-
|
32
|
-
|
17
|
+
Sidekiq::Context.add(:elapsed, elapsed(start))
|
18
|
+
@logger.info { "done" } unless @skip
|
19
|
+
rescue Exception
|
20
|
+
Sidekiq::Context.add(:elapsed, elapsed(start))
|
21
|
+
@logger.info { "fail" } unless @skip
|
22
|
+
raise
|
33
23
|
end
|
34
24
|
|
35
25
|
def prepare(job_hash, &block)
|
data/lib/sidekiq/launcher.rb
CHANGED
@@ -36,8 +36,8 @@ module Sidekiq
|
|
36
36
|
# has a heartbeat thread, caller can use `async_beat: false`
|
37
37
|
# and instead have thread call Launcher#heartbeat every N seconds.
|
38
38
|
def run(async_beat: true)
|
39
|
-
Sidekiq.freeze!
|
40
39
|
logger.debug { @config.merge!({}) }
|
40
|
+
Sidekiq.freeze!
|
41
41
|
@thread = safe_thread("heartbeat", &method(:start_heartbeat)) if async_beat
|
42
42
|
@poller.start
|
43
43
|
@managers.each(&:start)
|
@@ -1,12 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "concurrent"
|
4
|
-
|
5
3
|
module Sidekiq
|
6
4
|
module Metrics
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
class Counter
|
6
|
+
def initialize
|
7
|
+
@value = 0
|
8
|
+
@lock = Mutex.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def increment
|
12
|
+
@lock.synchronize { @value += 1 }
|
13
|
+
end
|
14
|
+
|
15
|
+
def value
|
16
|
+
@lock.synchronize { @value }
|
17
|
+
end
|
18
|
+
end
|
10
19
|
|
11
20
|
# Implements space-efficient but statistically useful histogram storage.
|
12
21
|
# A precise time histogram stores every time. Instead we break times into a set of
|
@@ -33,11 +33,26 @@ module Sidekiq
|
|
33
33
|
attrs = strklass.constantize.attributes
|
34
34
|
# Retries can push the job N times, we don't
|
35
35
|
# want retries to reset cattr. #5692, #5090
|
36
|
-
|
36
|
+
if attrs.any?
|
37
|
+
# Older rails has a bug that `CurrentAttributes#attributes` always returns
|
38
|
+
# the same hash instance. We need to dup it to avoid being accidentally mutated.
|
39
|
+
job[key] = if returns_same_object?
|
40
|
+
attrs.dup
|
41
|
+
else
|
42
|
+
attrs
|
43
|
+
end
|
44
|
+
end
|
37
45
|
end
|
38
46
|
end
|
39
47
|
yield
|
40
48
|
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def returns_same_object?
|
53
|
+
ActiveSupport::VERSION::MAJOR < 8 ||
|
54
|
+
(ActiveSupport::VERSION::MAJOR == 8 && ActiveSupport::VERSION::MINOR == 0)
|
55
|
+
end
|
41
56
|
end
|
42
57
|
|
43
58
|
class Load
|
@@ -88,7 +103,7 @@ module Sidekiq
|
|
88
103
|
cattrs = build_cattrs_hash(klass_or_array)
|
89
104
|
|
90
105
|
config.client_middleware.add Save, cattrs
|
91
|
-
config.server_middleware.
|
106
|
+
config.server_middleware.prepend Load, cattrs
|
92
107
|
end
|
93
108
|
|
94
109
|
private
|
data/lib/sidekiq/processor.rb
CHANGED
@@ -138,11 +138,11 @@ module Sidekiq
|
|
138
138
|
# Effectively this block denotes a "unit of work" to Rails.
|
139
139
|
@reloader.call do
|
140
140
|
klass = Object.const_get(job_hash["class"])
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
@retrier.local(
|
145
|
-
yield
|
141
|
+
instance = klass.new
|
142
|
+
instance.jid = job_hash["jid"]
|
143
|
+
instance._context = self
|
144
|
+
@retrier.local(instance, jobstr, queue) do
|
145
|
+
yield instance
|
146
146
|
end
|
147
147
|
end
|
148
148
|
end
|
@@ -180,9 +180,9 @@ module Sidekiq
|
|
180
180
|
ack = false
|
181
181
|
Thread.handle_interrupt(IGNORE_SHUTDOWN_INTERRUPTS) do
|
182
182
|
Thread.handle_interrupt(ALLOW_SHUTDOWN_INTERRUPTS) do
|
183
|
-
dispatch(job_hash, queue, jobstr) do |
|
184
|
-
config.server_middleware.invoke(
|
185
|
-
execute_job(
|
183
|
+
dispatch(job_hash, queue, jobstr) do |instance|
|
184
|
+
config.server_middleware.invoke(instance, job_hash, queue) do
|
185
|
+
execute_job(instance, job_hash["args"])
|
186
186
|
end
|
187
187
|
end
|
188
188
|
ack = true
|
@@ -216,8 +216,8 @@ module Sidekiq
|
|
216
216
|
end
|
217
217
|
end
|
218
218
|
|
219
|
-
def execute_job(
|
220
|
-
|
219
|
+
def execute_job(instance, cloned_args)
|
220
|
+
instance.perform(*cloned_args)
|
221
221
|
end
|
222
222
|
|
223
223
|
# Ruby doesn't provide atomic counters out of the box so we'll
|
data/lib/sidekiq/rails.rb
CHANGED
data/lib/sidekiq/testing.rb
CHANGED
@@ -283,11 +283,11 @@ module Sidekiq
|
|
283
283
|
end
|
284
284
|
|
285
285
|
def process_job(job)
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
Sidekiq::Testing.server_middleware.invoke(
|
290
|
-
execute_job(
|
286
|
+
instance = new
|
287
|
+
instance.jid = job["jid"]
|
288
|
+
instance.bid = job["bid"] if instance.respond_to?(:bid=)
|
289
|
+
Sidekiq::Testing.server_middleware.invoke(instance, job, job["queue"]) do
|
290
|
+
execute_job(instance, job["args"])
|
291
291
|
end
|
292
292
|
end
|
293
293
|
|
data/lib/sidekiq/version.rb
CHANGED
data/lib/sidekiq/web/action.rb
CHANGED
@@ -48,8 +48,12 @@ module Sidekiq
|
|
48
48
|
if content.is_a? Symbol
|
49
49
|
unless respond_to?(:"_erb_#{content}")
|
50
50
|
views = options[:views] || Web.settings.views
|
51
|
-
|
52
|
-
|
51
|
+
filename = "#{views}/#{content}.erb"
|
52
|
+
src = ERB.new(File.read(filename)).src
|
53
|
+
|
54
|
+
# Need to use lineno less by 1 because erb generates a
|
55
|
+
# comment before the source code.
|
56
|
+
WebAction.class_eval <<-RUBY, filename, -1 # standard:disable Style/EvalWithLocation
|
53
57
|
def _erb_#{content}
|
54
58
|
#{src}
|
55
59
|
end
|
@@ -331,12 +331,10 @@ module Sidekiq
|
|
331
331
|
########
|
332
332
|
# Filtering
|
333
333
|
|
334
|
-
get "/filter/metrics" do
|
335
|
-
redirect "#{root_path}metrics"
|
336
|
-
end
|
337
|
-
|
338
|
-
post "/filter/metrics" do
|
334
|
+
route :get, :post, "/filter/metrics" do
|
339
335
|
x = params[:substr]
|
336
|
+
return redirect "#{root_path}metrics" unless x && x != ""
|
337
|
+
|
340
338
|
q = Sidekiq::Metrics::Query.new
|
341
339
|
@period = h((params[:period] || "")[0..1])
|
342
340
|
@periods = METRICS_PERIODS
|
@@ -346,15 +344,7 @@ module Sidekiq
|
|
346
344
|
erb :metrics
|
347
345
|
end
|
348
346
|
|
349
|
-
get "/filter/retries" do
|
350
|
-
x = params[:substr]
|
351
|
-
return redirect "#{root_path}retries" unless x && x != ""
|
352
|
-
|
353
|
-
@retries = search(Sidekiq::RetrySet.new, params[:substr])
|
354
|
-
erb :retries
|
355
|
-
end
|
356
|
-
|
357
|
-
post "/filter/retries" do
|
347
|
+
route :get, :post, "/filter/retries" do
|
358
348
|
x = params[:substr]
|
359
349
|
return redirect "#{root_path}retries" unless x && x != ""
|
360
350
|
|
@@ -362,15 +352,7 @@ module Sidekiq
|
|
362
352
|
erb :retries
|
363
353
|
end
|
364
354
|
|
365
|
-
get "/filter/scheduled" do
|
366
|
-
x = params[:substr]
|
367
|
-
return redirect "#{root_path}scheduled" unless x && x != ""
|
368
|
-
|
369
|
-
@scheduled = search(Sidekiq::ScheduledSet.new, params[:substr])
|
370
|
-
erb :scheduled
|
371
|
-
end
|
372
|
-
|
373
|
-
post "/filter/scheduled" do
|
355
|
+
route :get, :post, "/filter/scheduled" do
|
374
356
|
x = params[:substr]
|
375
357
|
return redirect "#{root_path}scheduled" unless x && x != ""
|
376
358
|
|
@@ -378,15 +360,7 @@ module Sidekiq
|
|
378
360
|
erb :scheduled
|
379
361
|
end
|
380
362
|
|
381
|
-
get "/filter/dead" do
|
382
|
-
x = params[:substr]
|
383
|
-
return redirect "#{root_path}morgue" unless x && x != ""
|
384
|
-
|
385
|
-
@dead = search(Sidekiq::DeadSet.new, params[:substr])
|
386
|
-
erb :morgue
|
387
|
-
end
|
388
|
-
|
389
|
-
post "/filter/dead" do
|
363
|
+
route :get, :post, "/filter/dead" do
|
390
364
|
x = params[:substr]
|
391
365
|
return redirect "#{root_path}morgue" unless x && x != ""
|
392
366
|
|
data/lib/sidekiq/web/router.rb
CHANGED
@@ -39,10 +39,13 @@ module Sidekiq
|
|
39
39
|
route(DELETE, path, &block)
|
40
40
|
end
|
41
41
|
|
42
|
-
def route(
|
42
|
+
def route(*methods, path, &block)
|
43
43
|
@routes ||= {GET => [], POST => [], PUT => [], PATCH => [], DELETE => [], HEAD => []}
|
44
44
|
|
45
|
-
|
45
|
+
methods.each do |method|
|
46
|
+
method = method.to_s.upcase
|
47
|
+
@routes[method] << WebRoute.new(method, path, block)
|
48
|
+
end
|
46
49
|
end
|
47
50
|
|
48
51
|
def match(env)
|
data/lib/sidekiq/web.rb
CHANGED
@@ -213,7 +213,7 @@ module Sidekiq
|
|
213
213
|
Sidekiq::WebApplication.helpers WebHelpers
|
214
214
|
Sidekiq::WebApplication.helpers Sidekiq::Paginator
|
215
215
|
|
216
|
-
Sidekiq::WebAction.class_eval <<-RUBY,
|
216
|
+
Sidekiq::WebAction.class_eval <<-RUBY, Web::LAYOUT, -1 # standard:disable Style/EvalWithLocation
|
217
217
|
def _render
|
218
218
|
#{ERB.new(File.read(Web::LAYOUT)).src}
|
219
219
|
end
|
data/lib/sidekiq.rb
CHANGED
@@ -102,18 +102,19 @@ module Sidekiq
|
|
102
102
|
def self.freeze!
|
103
103
|
@frozen = true
|
104
104
|
@config_blocks = nil
|
105
|
+
default_configuration.freeze!
|
105
106
|
end
|
106
107
|
|
107
108
|
# Creates a Sidekiq::Config instance that is more tuned for embedding
|
108
109
|
# within an arbitrary Ruby process. Notably it reduces concurrency by
|
109
110
|
# default so there is less contention for CPU time with other threads.
|
110
111
|
#
|
111
|
-
#
|
112
|
+
# instance = Sidekiq.configure_embed do |config|
|
112
113
|
# config.queues = %w[critical default low]
|
113
114
|
# end
|
114
|
-
#
|
115
|
+
# instance.run
|
115
116
|
# sleep 10
|
116
|
-
#
|
117
|
+
# instance.stop
|
117
118
|
#
|
118
119
|
# NB: it is really easy to overload a Ruby process with threads due to the GIL.
|
119
120
|
# I do not recommend setting concurrency higher than 2-3.
|
data/sidekiq.gemspec
CHANGED
data/web/locales/en.yml
CHANGED
data/web/locales/fr.yml
CHANGED
data/web/locales/gd.yml
CHANGED
data/web/locales/it.yml
CHANGED
@@ -6,44 +6,60 @@ it:
|
|
6
6
|
AreYouSureDeleteJob: Sei sicuro di voler cancellare questo lavoro?
|
7
7
|
AreYouSureDeleteQueue: Sei sicuro di voler cancellare la coda %{queue}?
|
8
8
|
Arguments: Argomenti
|
9
|
+
BackToApp: Torna all'App
|
9
10
|
Busy: Occupato
|
10
11
|
Class: Classe
|
11
12
|
Connections: Connessioni
|
13
|
+
CreatedAt: Creato il
|
12
14
|
CurrentMessagesInQueue: Messaggi in <span class='title'>%{queue}</span>
|
13
15
|
Dashboard: Dashboard
|
14
16
|
Dead: Arrestato
|
15
17
|
DeadJobs: Lavori arrestati
|
16
18
|
Delete: Cancella
|
17
19
|
DeleteAll: Cancella tutti
|
20
|
+
Deploy: Distribuire
|
18
21
|
Enqueued: In coda
|
19
22
|
Error: Errore
|
20
23
|
ErrorBacktrace: Backtrace dell'errore
|
21
24
|
ErrorClass: Classe dell'errore
|
22
25
|
ErrorMessage: Messaggio di errore
|
26
|
+
ExecutionTime: Tempo di esecuzione
|
23
27
|
Extras: Extra
|
24
28
|
Failed: Fallito
|
25
29
|
Failures: Fallimenti
|
30
|
+
Failure: Fallimento
|
26
31
|
GoBack: ← Indietro
|
27
32
|
History: Storia
|
28
33
|
Job: Lavoro
|
29
34
|
Jobs: Lavori
|
30
35
|
Kill: Uccidere
|
36
|
+
KillAll: Uccidere tutti
|
31
37
|
LastRetry: Ultimo tentativo
|
38
|
+
Latency: Latenza
|
32
39
|
LivePoll: Live poll
|
33
40
|
MemoryUsage: Memoria utilizzata
|
41
|
+
Name: Nome
|
34
42
|
Namespace: Namespace
|
35
43
|
NextRetry: Prossimo tentativo
|
36
44
|
NoDeadJobsFound: Non ci sono lavori arrestati
|
37
45
|
NoRetriesFound: Non sono stati trovati nuovi tentativi
|
38
46
|
NoScheduledFound: Non ci sono lavori pianificati
|
47
|
+
NotYetEnqueued: Non ancora in coda
|
39
48
|
OneMonth: 1 mese
|
40
49
|
OneWeek: 1 settimana
|
41
50
|
OriginallyFailed: Primo fallimento
|
51
|
+
Pause: Metti in pausa
|
52
|
+
Paused: In pausa
|
42
53
|
PeakMemoryUsage: Memoria utilizzata (max.)
|
54
|
+
Plugins: Plugins
|
55
|
+
PollingInterval: Intervallo di polling
|
56
|
+
Process: Processo
|
43
57
|
Processed: Processato
|
44
58
|
Processes: Processi
|
45
59
|
Queue: Coda
|
46
60
|
Queues: Code
|
61
|
+
Quiet: Silenzia
|
62
|
+
QuietAll: Silenzia Tutti
|
47
63
|
Realtime: Tempo reale
|
48
64
|
Retries: Nuovi tentativi
|
49
65
|
RetryAll: Riprova tutti
|
@@ -51,19 +67,34 @@ it:
|
|
51
67
|
RetryNow: Riprova
|
52
68
|
Scheduled: Pianificato
|
53
69
|
ScheduledJobs: Lavori pianificati
|
70
|
+
Seconds: Secondi
|
54
71
|
ShowAll: Mostra tutti
|
55
72
|
SixMonths: 6 mesi
|
56
73
|
Size: Dimensione
|
57
74
|
Started: Iniziato
|
58
75
|
Status: Stato
|
76
|
+
Stop: Ferma
|
77
|
+
StopAll: Ferma Tutti
|
59
78
|
StopPolling: Ferma il polling
|
79
|
+
Success: Successo
|
80
|
+
Summary: Riepilogo
|
60
81
|
Thread: Thread
|
61
|
-
Threads:
|
82
|
+
Threads: Threads
|
62
83
|
ThreeMonths: 3 mesi
|
63
84
|
Time: Ora
|
85
|
+
Unpause: Riattiva
|
64
86
|
Uptime: Uptime (giorni)
|
87
|
+
Utilization: Utilizzo
|
65
88
|
Version: Versione
|
66
89
|
When: Quando
|
67
90
|
Worker: Lavoratore
|
68
91
|
active: attivo
|
69
92
|
idle: inattivo
|
93
|
+
Metrics: Metriche
|
94
|
+
NoDataFound: Nessun dato trovato
|
95
|
+
TotalExecutionTime: Tempo totale di esecuzione
|
96
|
+
AvgExecutionTime: Tempo medio di esecuzione
|
97
|
+
Context: Contesto
|
98
|
+
NoJobMetricsFound: Metriche recenti di lavoro non trovate
|
99
|
+
Filter: Filtro
|
100
|
+
AnyJobContent: Qualsiasi contenuto di lavoro
|
data/web/locales/ja.yml
CHANGED
data/web/locales/pt-br.yml
CHANGED
@@ -7,7 +7,6 @@
|
|
7
7
|
Arguments: Argumentos
|
8
8
|
AvgExecutionTime: Tempo médio de execução
|
9
9
|
BackToApp: De volta ao aplicativo
|
10
|
-
Bucket: Bucket
|
11
10
|
Busy: Ocupados
|
12
11
|
Class: Classe
|
13
12
|
Connections: Conexões
|
@@ -93,4 +92,4 @@
|
|
93
92
|
Utilization: Utilização
|
94
93
|
Version: Versão
|
95
94
|
When: Quando
|
96
|
-
Worker: Trabalhador
|
95
|
+
Worker: Trabalhador
|
data/web/locales/tr.yml
CHANGED
data/web/locales/uk.yml
CHANGED
@@ -6,31 +6,39 @@ uk:
|
|
6
6
|
AreYouSureDeleteJob: Ви впевнені у тому, що хочете видалити задачу?
|
7
7
|
AreYouSureDeleteQueue: Ви впевнені у тому, що хочете видалити чергу %{queue}?
|
8
8
|
Arguments: Аргументи
|
9
|
+
BackToApp: Назад
|
9
10
|
Busy: Зайнятих
|
10
11
|
Class: Клас
|
11
12
|
Connections: З'єднань
|
13
|
+
CreatedAt: Створено
|
12
14
|
CurrentMessagesInQueue: Поточні задачі у черзі <span class='title'>%{queue}</span>
|
13
15
|
Dashboard: Панель керування
|
14
16
|
Dead: Вбитих
|
15
17
|
DeadJobs: Вбиті задачі
|
16
18
|
Delete: Видалити
|
17
19
|
DeleteAll: Видалити усі
|
20
|
+
Deploy: Деплой
|
18
21
|
Enqueued: У черзі
|
19
22
|
Error: Помилка
|
20
23
|
ErrorBacktrace: Трасування помилки
|
21
24
|
ErrorClass: Клас помилки
|
22
25
|
ErrorMessage: Повідомлення про помилку
|
26
|
+
ExecutionTime: Час виконання
|
23
27
|
Extras: Додатково
|
24
28
|
Failed: Невдалих
|
25
29
|
Failures: Невдачі
|
30
|
+
Failure: Невдача
|
26
31
|
GoBack: ← Назад
|
27
32
|
History: Історія
|
28
33
|
Job: Задача
|
29
34
|
Jobs: Задачі
|
30
|
-
Kill:
|
35
|
+
Kill: Вбити
|
36
|
+
KillAll: Вбити все
|
31
37
|
LastRetry: Остання спроба
|
38
|
+
Latency: Затримка
|
32
39
|
LivePoll: Постійне опитування
|
33
40
|
MemoryUsage: Використання пам'яті
|
41
|
+
Name: Назва
|
34
42
|
Namespace: Простір імен
|
35
43
|
NextRetry: Наступна спроба
|
36
44
|
NoDeadJobsFound: Вбитих задач не знайдено
|
@@ -40,10 +48,12 @@ uk:
|
|
40
48
|
OneMonth: 1 місяць
|
41
49
|
OneWeek: 1 тиждень
|
42
50
|
OriginallyFailed: Перша невдала спроба
|
51
|
+
Pause: Призупинити
|
43
52
|
Paused: Призупинено
|
44
53
|
PeakMemoryUsage: Максимальне використання пам'яті
|
45
54
|
Plugins: Плагіни
|
46
55
|
PollingInterval: Інтервал опитування
|
56
|
+
Process: Процес
|
47
57
|
Processed: Опрацьовано
|
48
58
|
Processes: Процеси
|
49
59
|
Queue: Черга
|
@@ -57,6 +67,7 @@ uk:
|
|
57
67
|
RetryNow: Повторити зараз
|
58
68
|
Scheduled: Заплановано
|
59
69
|
ScheduledJobs: Заплановані задачі
|
70
|
+
Seconds: Секунди
|
60
71
|
ShowAll: Відобразити усі
|
61
72
|
SixMonths: 6 місяців
|
62
73
|
Size: Розмір
|
@@ -65,13 +76,25 @@ uk:
|
|
65
76
|
Stop: Зупинити
|
66
77
|
StopAll: Зупинити усі
|
67
78
|
StopPolling: Зупинити опитування
|
79
|
+
Success: Успіх
|
80
|
+
Summary: Підсумок
|
68
81
|
Thread: Потік
|
69
82
|
Threads: Потоки
|
70
83
|
ThreeMonths: 3 місяці
|
71
84
|
Time: Час
|
85
|
+
Unpause: Відновити
|
72
86
|
Uptime: Днів безперебійної роботи
|
87
|
+
Utilization: Утилізація
|
73
88
|
Version: Версія
|
74
89
|
When: Коли
|
75
90
|
Worker: Обробник
|
76
91
|
active: активний
|
77
92
|
idle: незайнятий
|
93
|
+
Metrics: Метрики
|
94
|
+
NoDataFound: Даних не знайдено
|
95
|
+
TotalExecutionTime: Загальний час виконання
|
96
|
+
AvgExecutionTime: Середній час виконання
|
97
|
+
Context: Контекст
|
98
|
+
NoJobMetricsFound: Недавніх метрик задачі не знайдено
|
99
|
+
Filter: Фільтр
|
100
|
+
AnyJobContent: Будь-який атрибут задачі
|
data/web/locales/zh-cn.yml
CHANGED
data/web/locales/zh-tw.yml
CHANGED
data/web/views/metrics.erb
CHANGED
@@ -54,8 +54,8 @@
|
|
54
54
|
<th><%= t('Name') %></th>
|
55
55
|
<th><%= t('Success') %></th>
|
56
56
|
<th><%= t('Failure') %></th>
|
57
|
-
<th><%= t('TotalExecutionTime') %> (Seconds)</th>
|
58
|
-
<th><%= t('AvgExecutionTime') %> (Seconds)</th>
|
57
|
+
<th><%= t('TotalExecutionTime') %> (<%= t('Seconds') %>)</th>
|
58
|
+
<th><%= t('AvgExecutionTime') %> (<%= t('Seconds') %>)</th>
|
59
59
|
</tr>
|
60
60
|
<% if job_results.any? %>
|
61
61
|
<% job_results.each_with_index do |(kls, jr), i| %>
|
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.3.
|
4
|
+
version: 7.3.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Perham
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-11-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis-client
|
@@ -52,20 +52,6 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: 2.2.4
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: concurrent-ruby
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - "<"
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '2'
|
62
|
-
type: :runtime
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - "<"
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '2'
|
69
55
|
- !ruby/object:Gem::Dependency
|
70
56
|
name: logger
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -96,6 +82,7 @@ files:
|
|
96
82
|
- bin/sidekiq
|
97
83
|
- bin/sidekiqload
|
98
84
|
- bin/sidekiqmon
|
85
|
+
- lib/active_job/queue_adapters/sidekiq_adapter.rb
|
99
86
|
- lib/generators/sidekiq/job_generator.rb
|
100
87
|
- lib/generators/sidekiq/templates/job.rb.erb
|
101
88
|
- lib/generators/sidekiq/templates/job_spec.rb.erb
|
@@ -245,7 +232,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
245
232
|
- !ruby/object:Gem::Version
|
246
233
|
version: '0'
|
247
234
|
requirements: []
|
248
|
-
rubygems_version: 3.5.
|
235
|
+
rubygems_version: 3.5.16
|
249
236
|
signing_key:
|
250
237
|
specification_version: 4
|
251
238
|
summary: Simple, efficient background processing for Ruby
|