sidekiq 7.3.2 → 7.3.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|