sidekiq 6.5.1 → 6.5.6
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sidekiq might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Changes.md +34 -0
- data/lib/sidekiq/api.rb +128 -24
- data/lib/sidekiq/cli.rb +1 -0
- data/lib/sidekiq/client.rb +1 -1
- data/lib/sidekiq/component.rb +2 -1
- data/lib/sidekiq/fetch.rb +2 -2
- data/lib/sidekiq/job_retry.rb +55 -35
- data/lib/sidekiq/launcher.rb +6 -4
- data/lib/sidekiq/metrics/deploy.rb +47 -0
- data/lib/sidekiq/metrics/query.rb +153 -0
- data/lib/sidekiq/metrics/shared.rb +94 -0
- data/lib/sidekiq/metrics/tracking.rb +134 -0
- data/lib/sidekiq/middleware/chain.rb +70 -35
- data/lib/sidekiq/middleware/current_attributes.rb +6 -4
- data/lib/sidekiq/processor.rb +9 -3
- data/lib/sidekiq/redis_connection.rb +0 -2
- data/lib/sidekiq/scheduled.rb +1 -7
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web/action.rb +3 -3
- data/lib/sidekiq/web/application.rb +18 -5
- data/lib/sidekiq/web/helpers.rb +24 -1
- data/lib/sidekiq/web.rb +5 -1
- data/lib/sidekiq.rb +9 -1
- data/sidekiq.gemspec +2 -2
- data/web/assets/javascripts/application.js +1 -1
- data/web/assets/javascripts/chart.min.js +13 -0
- data/web/assets/javascripts/chartjs-plugin-annotation.min.js +7 -0
- data/web/assets/javascripts/dashboard.js +0 -17
- data/web/assets/javascripts/graph.js +16 -0
- data/web/assets/javascripts/metrics.js +262 -0
- data/web/assets/stylesheets/application.css +44 -1
- data/web/locales/el.yml +43 -19
- data/web/locales/en.yml +7 -0
- data/web/views/_nav.erb +1 -1
- data/web/views/busy.erb +1 -1
- data/web/views/dashboard.erb +1 -0
- data/web/views/metrics.erb +69 -0
- data/web/views/metrics_for_job.erb +87 -0
- data/web/views/queue.erb +5 -1
- metadata +22 -7
- data/lib/sidekiq/.DS_Store +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7e12ddc46413e3e476d620e04428a86476f4826d7802575110b5c3697a096137
|
4
|
+
data.tar.gz: 802bdbc7c0d45a9b793222baca250e292ce852d67902446bc75a0961a36f5677
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6180da0e7aefa1573d6b283c56ad365063b290afb5c10a15dc83fb367cb981391d8304acc9ebb1219279a749da71e0af8b37979baea770b0b1efeb04627e0e4c
|
7
|
+
data.tar.gz: 35c51c58b73450c6bbd3479cc55d873ed54a6a1ce6a5b7414ca78fc807984acea11d4697ce8c05bdb2e9eb799c30dc7b377872b4c48a3de60bee5d6d71e07b3a
|
data/Changes.md
CHANGED
@@ -2,6 +2,40 @@
|
|
2
2
|
|
3
3
|
[Sidekiq Changes](https://github.com/mperham/sidekiq/blob/main/Changes.md) | [Sidekiq Pro Changes](https://github.com/mperham/sidekiq/blob/main/Pro-Changes.md) | [Sidekiq Enterprise Changes](https://github.com/mperham/sidekiq/blob/main/Ent-Changes.md)
|
4
4
|
|
5
|
+
6.5.6
|
6
|
+
----------
|
7
|
+
|
8
|
+
- Fix deprecation warnings with redis-rb 4.8.0 [#5484]
|
9
|
+
- Lock redis-rb to < 5.0 as we are moving to redis-client in Sidekiq 7.0
|
10
|
+
|
11
|
+
6.5.5
|
12
|
+
----------
|
13
|
+
|
14
|
+
- Fix require issue with job_retry.rb [#5462]
|
15
|
+
- Improve Sidekiq::Web compatibility with Rack 3.x
|
16
|
+
|
17
|
+
6.5.4
|
18
|
+
----------
|
19
|
+
|
20
|
+
- Fix invalid code on Ruby 2.5 [#5460]
|
21
|
+
- Fix further metrics dependency issues [#5457]
|
22
|
+
|
23
|
+
6.5.3
|
24
|
+
----------
|
25
|
+
|
26
|
+
- Don't require metrics code without explicit opt-in [#5456]
|
27
|
+
|
28
|
+
6.5.2
|
29
|
+
----------
|
30
|
+
|
31
|
+
- [Job Metrics are under active development, help wanted!](https://github.com/mperham/sidekiq/wiki/Metrics#contributing) **BETA**
|
32
|
+
- Add `Context` column on queue page which shows any CurrentAttributes [#5450]
|
33
|
+
- `sidekiq_retry_in` may now return `:discard` or `:kill` to dynamically stop job retries [#5406]
|
34
|
+
- Smarter sorting of processes in /busy Web UI [#5398]
|
35
|
+
- Fix broken hamburger menu in mobile UI [#5428]
|
36
|
+
- Require redis-rb 4.5.0. Note that Sidekiq will break if you use the
|
37
|
+
[`Redis.exists_returns_integer = false`](https://github.com/redis/redis-rb/blob/master/CHANGELOG.md#450) flag. [#5394]
|
38
|
+
|
5
39
|
6.5.1
|
6
40
|
----------
|
7
41
|
|
data/lib/sidekiq/api.rb
CHANGED
@@ -3,9 +3,20 @@
|
|
3
3
|
require "sidekiq"
|
4
4
|
|
5
5
|
require "zlib"
|
6
|
+
require "set"
|
6
7
|
require "base64"
|
7
8
|
|
9
|
+
if ENV["SIDEKIQ_METRICS_BETA"]
|
10
|
+
require "sidekiq/metrics/deploy"
|
11
|
+
require "sidekiq/metrics/query"
|
12
|
+
end
|
13
|
+
|
8
14
|
module Sidekiq
|
15
|
+
# Retrieve runtime statistics from Redis regarding
|
16
|
+
# this Sidekiq cluster.
|
17
|
+
#
|
18
|
+
# stat = Sidekiq::Stats.new
|
19
|
+
# stat.processed
|
9
20
|
class Stats
|
10
21
|
def initialize
|
11
22
|
fetch_stats_fast!
|
@@ -52,6 +63,7 @@ module Sidekiq
|
|
52
63
|
end
|
53
64
|
|
54
65
|
# O(1) redis calls
|
66
|
+
# @api private
|
55
67
|
def fetch_stats_fast!
|
56
68
|
pipe1_res = Sidekiq.redis { |conn|
|
57
69
|
conn.pipelined do |pipeline|
|
@@ -91,6 +103,7 @@ module Sidekiq
|
|
91
103
|
end
|
92
104
|
|
93
105
|
# O(number of processes + number of queues) redis calls
|
106
|
+
# @api private
|
94
107
|
def fetch_stats_slow!
|
95
108
|
processes = Sidekiq.redis { |conn|
|
96
109
|
conn.sscan_each("processes").to_a
|
@@ -116,11 +129,13 @@ module Sidekiq
|
|
116
129
|
@stats
|
117
130
|
end
|
118
131
|
|
132
|
+
# @api private
|
119
133
|
def fetch_stats!
|
120
134
|
fetch_stats_fast!
|
121
135
|
fetch_stats_slow!
|
122
136
|
end
|
123
137
|
|
138
|
+
# @api private
|
124
139
|
def reset(*stats)
|
125
140
|
all = %w[failed processed]
|
126
141
|
stats = stats.empty? ? all : all & stats.flatten.compact.map(&:to_s)
|
@@ -202,9 +217,10 @@ module Sidekiq
|
|
202
217
|
end
|
203
218
|
|
204
219
|
##
|
205
|
-
#
|
220
|
+
# Represents a queue within Sidekiq.
|
206
221
|
# Allows enumeration of all jobs within the queue
|
207
|
-
# and deletion of jobs.
|
222
|
+
# and deletion of jobs. NB: this queue data is real-time
|
223
|
+
# and is changing within Redis moment by moment.
|
208
224
|
#
|
209
225
|
# queue = Sidekiq::Queue.new("mailer")
|
210
226
|
# queue.each do |job|
|
@@ -212,7 +228,6 @@ module Sidekiq
|
|
212
228
|
# job.args # => [1, 2, 3]
|
213
229
|
# job.delete if job.jid == 'abcdef1234567890'
|
214
230
|
# end
|
215
|
-
#
|
216
231
|
class Queue
|
217
232
|
include Enumerable
|
218
233
|
|
@@ -296,41 +311,53 @@ module Sidekiq
|
|
296
311
|
end
|
297
312
|
|
298
313
|
# delete all jobs within this queue
|
314
|
+
# @return [Boolean] true
|
299
315
|
def clear
|
300
316
|
Sidekiq.redis do |conn|
|
301
317
|
conn.multi do |transaction|
|
302
318
|
transaction.unlink(@rname)
|
303
|
-
transaction.srem("queues", name)
|
319
|
+
transaction.srem("queues", [name])
|
304
320
|
end
|
305
321
|
end
|
322
|
+
true
|
306
323
|
end
|
307
324
|
alias_method :💣, :clear
|
308
325
|
|
309
|
-
|
326
|
+
# :nodoc:
|
327
|
+
# @api private
|
328
|
+
def as_json(options = nil)
|
310
329
|
{name: name} # 5336
|
311
330
|
end
|
312
331
|
end
|
313
332
|
|
314
333
|
##
|
315
|
-
#
|
316
|
-
# sorted set.
|
334
|
+
# Represents a pending job within a Sidekiq queue.
|
317
335
|
#
|
318
336
|
# The job should be considered immutable but may be
|
319
337
|
# removed from the queue via JobRecord#delete.
|
320
|
-
#
|
321
338
|
class JobRecord
|
339
|
+
# the parsed Hash of job data
|
340
|
+
# @!attribute [r] Item
|
322
341
|
attr_reader :item
|
342
|
+
# the underlying String in Redis
|
343
|
+
# @!attribute [r] Value
|
323
344
|
attr_reader :value
|
345
|
+
# the queue associated with this job
|
346
|
+
# @!attribute [r] Queue
|
324
347
|
attr_reader :queue
|
325
348
|
|
326
|
-
|
349
|
+
# :nodoc:
|
350
|
+
# @api private
|
351
|
+
def initialize(item, queue_name = nil)
|
327
352
|
@args = nil
|
328
353
|
@value = item
|
329
354
|
@item = item.is_a?(Hash) ? item : parse(item)
|
330
355
|
@queue = queue_name || @item["queue"]
|
331
356
|
end
|
332
357
|
|
333
|
-
|
358
|
+
# :nodoc:
|
359
|
+
# @api private
|
360
|
+
def parse(item)
|
334
361
|
Sidekiq.load_json(item)
|
335
362
|
rescue JSON::ParserError
|
336
363
|
# If the job payload in Redis is invalid JSON, we'll load
|
@@ -341,6 +368,8 @@ module Sidekiq
|
|
341
368
|
{}
|
342
369
|
end
|
343
370
|
|
371
|
+
# This is the job class which Sidekiq will execute. If using ActiveJob,
|
372
|
+
# this class will be the ActiveJob adapter class rather than a specific job.
|
344
373
|
def klass
|
345
374
|
self["class"]
|
346
375
|
end
|
@@ -457,7 +486,7 @@ module Sidekiq
|
|
457
486
|
# #1761 in dev mode, it's possible to have jobs enqueued which haven't been loaded into
|
458
487
|
# memory yet so the YAML can't be loaded.
|
459
488
|
# TODO is this still necessary? Zeitwerk reloader should handle?
|
460
|
-
Sidekiq.logger.warn "Unable to load YAML: #{ex.message}" unless Sidekiq.
|
489
|
+
Sidekiq.logger.warn "Unable to load YAML: #{ex.message}" unless Sidekiq.options[:environment] == "development"
|
461
490
|
default
|
462
491
|
end
|
463
492
|
|
@@ -480,21 +509,27 @@ module Sidekiq
|
|
480
509
|
end
|
481
510
|
|
482
511
|
# Represents a job within a Redis sorted set where the score
|
483
|
-
# represents a timestamp
|
512
|
+
# represents a timestamp associated with the job. This timestamp
|
513
|
+
# could be the scheduled time for it to run (e.g. scheduled set),
|
514
|
+
# or the expiration date after which the entry should be deleted (e.g. dead set).
|
484
515
|
class SortedEntry < JobRecord
|
485
516
|
attr_reader :score
|
486
517
|
attr_reader :parent
|
487
518
|
|
488
|
-
|
519
|
+
# :nodoc:
|
520
|
+
# @api private
|
521
|
+
def initialize(parent, score, item)
|
489
522
|
super(item)
|
490
523
|
@score = Float(score)
|
491
524
|
@parent = parent
|
492
525
|
end
|
493
526
|
|
527
|
+
# The timestamp associated with this entry
|
494
528
|
def at
|
495
529
|
Time.at(score).utc
|
496
530
|
end
|
497
531
|
|
532
|
+
# remove this entry from the sorted set
|
498
533
|
def delete
|
499
534
|
if @value
|
500
535
|
@parent.delete_by_value(@parent.name, @value)
|
@@ -505,7 +540,7 @@ module Sidekiq
|
|
505
540
|
|
506
541
|
# Change the scheduled time for this job.
|
507
542
|
#
|
508
|
-
# @param [Time] the new timestamp
|
543
|
+
# @param at [Time] the new timestamp for this job
|
509
544
|
def reschedule(at)
|
510
545
|
Sidekiq.redis do |conn|
|
511
546
|
conn.zincrby(@parent.name, at.to_f - @score, Sidekiq.dump_json(@item))
|
@@ -579,20 +614,32 @@ module Sidekiq
|
|
579
614
|
end
|
580
615
|
end
|
581
616
|
|
617
|
+
# Base class for all sorted sets within Sidekiq.
|
582
618
|
class SortedSet
|
583
619
|
include Enumerable
|
584
620
|
|
621
|
+
# Redis key of the set
|
622
|
+
# @!attribute [r] Name
|
585
623
|
attr_reader :name
|
586
624
|
|
625
|
+
# :nodoc:
|
626
|
+
# @api private
|
587
627
|
def initialize(name)
|
588
628
|
@name = name
|
589
629
|
@_size = size
|
590
630
|
end
|
591
631
|
|
632
|
+
# real-time size of the set, will change
|
592
633
|
def size
|
593
634
|
Sidekiq.redis { |c| c.zcard(name) }
|
594
635
|
end
|
595
636
|
|
637
|
+
# Scan through each element of the sorted set, yielding each to the supplied block.
|
638
|
+
# Please see Redis's <a href="https://redis.io/commands/scan/">SCAN documentation</a> for implementation details.
|
639
|
+
#
|
640
|
+
# @param match [String] a snippet or regexp to filter matches.
|
641
|
+
# @param count [Integer] number of elements to retrieve at a time, default 100
|
642
|
+
# @yieldparam [Sidekiq::SortedEntry] each entry
|
596
643
|
def scan(match, count = 100)
|
597
644
|
return to_enum(:scan, match, count) unless block_given?
|
598
645
|
|
@@ -604,22 +651,32 @@ module Sidekiq
|
|
604
651
|
end
|
605
652
|
end
|
606
653
|
|
654
|
+
# @return [Boolean] always true
|
607
655
|
def clear
|
608
656
|
Sidekiq.redis do |conn|
|
609
657
|
conn.unlink(name)
|
610
658
|
end
|
659
|
+
true
|
611
660
|
end
|
612
661
|
alias_method :💣, :clear
|
613
662
|
|
614
|
-
|
663
|
+
# :nodoc:
|
664
|
+
# @api private
|
665
|
+
def as_json(options = nil)
|
615
666
|
{name: name} # 5336
|
616
667
|
end
|
617
668
|
end
|
618
669
|
|
670
|
+
# Base class for all sorted sets which contain jobs, e.g. scheduled, retry and dead.
|
671
|
+
# Sidekiq Pro and Enterprise add additional sorted sets which do not contain job data,
|
672
|
+
# e.g. Batches.
|
619
673
|
class JobSet < SortedSet
|
620
|
-
|
674
|
+
# Add a job with the associated timestamp to this set.
|
675
|
+
# @param timestamp [Time] the score for the job
|
676
|
+
# @param job [Hash] the job data
|
677
|
+
def schedule(timestamp, job)
|
621
678
|
Sidekiq.redis do |conn|
|
622
|
-
conn.zadd(name, timestamp.to_f.to_s, Sidekiq.dump_json(
|
679
|
+
conn.zadd(name, timestamp.to_f.to_s, Sidekiq.dump_json(job))
|
623
680
|
end
|
624
681
|
end
|
625
682
|
|
@@ -647,6 +704,10 @@ module Sidekiq
|
|
647
704
|
##
|
648
705
|
# Fetch jobs that match a given time or Range. Job ID is an
|
649
706
|
# optional second argument.
|
707
|
+
#
|
708
|
+
# @param score [Time,Range] a specific timestamp or range
|
709
|
+
# @param jid [String, optional] find a specific JID within the score
|
710
|
+
# @return [Array<SortedEntry>] any results found, can be empty
|
650
711
|
def fetch(score, jid = nil)
|
651
712
|
begin_score, end_score =
|
652
713
|
if score.is_a?(Range)
|
@@ -668,7 +729,10 @@ module Sidekiq
|
|
668
729
|
|
669
730
|
##
|
670
731
|
# Find the job with the given JID within this sorted set.
|
671
|
-
# This is a
|
732
|
+
# *This is a slow O(n) operation*. Do not use for app logic.
|
733
|
+
#
|
734
|
+
# @param jid [String] the job identifier
|
735
|
+
# @return [SortedEntry] the record or nil
|
672
736
|
def find_job(jid)
|
673
737
|
Sidekiq.redis do |conn|
|
674
738
|
conn.zscan_each(name, match: "*#{jid}*", count: 100) do |entry, score|
|
@@ -680,6 +744,8 @@ module Sidekiq
|
|
680
744
|
nil
|
681
745
|
end
|
682
746
|
|
747
|
+
# :nodoc:
|
748
|
+
# @api private
|
683
749
|
def delete_by_value(name, value)
|
684
750
|
Sidekiq.redis do |conn|
|
685
751
|
ret = conn.zrem(name, value)
|
@@ -688,6 +754,8 @@ module Sidekiq
|
|
688
754
|
end
|
689
755
|
end
|
690
756
|
|
757
|
+
# :nodoc:
|
758
|
+
# @api private
|
691
759
|
def delete_by_jid(score, jid)
|
692
760
|
Sidekiq.redis do |conn|
|
693
761
|
elements = conn.zrangebyscore(name, score, score)
|
@@ -708,10 +776,10 @@ module Sidekiq
|
|
708
776
|
end
|
709
777
|
|
710
778
|
##
|
711
|
-
#
|
779
|
+
# The set of scheduled jobs within Sidekiq.
|
712
780
|
# Based on this, you can search/filter for jobs. Here's an
|
713
|
-
# example where I'm selecting
|
714
|
-
# and deleting them from the
|
781
|
+
# example where I'm selecting jobs based on some complex logic
|
782
|
+
# and deleting them from the scheduled set.
|
715
783
|
#
|
716
784
|
# r = Sidekiq::ScheduledSet.new
|
717
785
|
# r.select do |scheduled|
|
@@ -726,7 +794,7 @@ module Sidekiq
|
|
726
794
|
end
|
727
795
|
|
728
796
|
##
|
729
|
-
#
|
797
|
+
# The set of retries within Sidekiq.
|
730
798
|
# Based on this, you can search/filter for jobs. Here's an
|
731
799
|
# example where I'm selecting all jobs of a certain type
|
732
800
|
# and deleting them from the retry queue.
|
@@ -742,23 +810,29 @@ module Sidekiq
|
|
742
810
|
super "retry"
|
743
811
|
end
|
744
812
|
|
813
|
+
# Enqueues all jobs pending within the retry set.
|
745
814
|
def retry_all
|
746
815
|
each(&:retry) while size > 0
|
747
816
|
end
|
748
817
|
|
818
|
+
# Kills all jobs pending within the retry set.
|
749
819
|
def kill_all
|
750
820
|
each(&:kill) while size > 0
|
751
821
|
end
|
752
822
|
end
|
753
823
|
|
754
824
|
##
|
755
|
-
#
|
825
|
+
# The set of dead jobs within Sidekiq. Dead jobs have failed all of
|
826
|
+
# their retries and are helding in this set pending some sort of manual
|
827
|
+
# fix. They will be removed after 6 months (dead_timeout) if not.
|
756
828
|
#
|
757
829
|
class DeadSet < JobSet
|
758
830
|
def initialize
|
759
831
|
super "dead"
|
760
832
|
end
|
761
833
|
|
834
|
+
# Add the given job to the Dead set.
|
835
|
+
# @param message [String] the job data as JSON
|
762
836
|
def kill(message, opts = {})
|
763
837
|
now = Time.now.to_f
|
764
838
|
Sidekiq.redis do |conn|
|
@@ -780,14 +854,19 @@ module Sidekiq
|
|
780
854
|
true
|
781
855
|
end
|
782
856
|
|
857
|
+
# Enqueue all dead jobs
|
783
858
|
def retry_all
|
784
859
|
each(&:retry) while size > 0
|
785
860
|
end
|
786
861
|
|
862
|
+
# The maximum size of the Dead set. Older entries will be trimmed
|
863
|
+
# to stay within this limit. Default value is 10,000.
|
787
864
|
def self.max_jobs
|
788
865
|
Sidekiq[:dead_max_jobs]
|
789
866
|
end
|
790
867
|
|
868
|
+
# The time limit for entries within the Dead set. Older entries will be thrown away.
|
869
|
+
# Default value is six months.
|
791
870
|
def self.timeout
|
792
871
|
Sidekiq[:dead_timeout_in_seconds]
|
793
872
|
end
|
@@ -798,18 +877,23 @@ module Sidekiq
|
|
798
877
|
# right now. Each process sends a heartbeat to Redis every 5 seconds
|
799
878
|
# so this set should be relatively accurate, barring network partitions.
|
800
879
|
#
|
801
|
-
#
|
880
|
+
# @yieldparam [Sidekiq::Process]
|
802
881
|
#
|
803
882
|
class ProcessSet
|
804
883
|
include Enumerable
|
805
884
|
|
885
|
+
# :nodoc:
|
886
|
+
# @api private
|
806
887
|
def initialize(clean_plz = true)
|
807
888
|
cleanup if clean_plz
|
808
889
|
end
|
809
890
|
|
810
891
|
# Cleans up dead processes recorded in Redis.
|
811
892
|
# Returns the number of processes cleaned.
|
893
|
+
# :nodoc:
|
894
|
+
# @api private
|
812
895
|
def cleanup
|
896
|
+
return 0 unless Sidekiq.redis { |conn| conn.set("process_cleanup", "1", nx: true, ex: 60) }
|
813
897
|
count = 0
|
814
898
|
Sidekiq.redis do |conn|
|
815
899
|
procs = conn.sscan_each("processes").to_a.sort
|
@@ -863,6 +947,7 @@ module Sidekiq
|
|
863
947
|
# based on current heartbeat. #each does that and ensures the set only
|
864
948
|
# contains Sidekiq processes which have sent a heartbeat within the last
|
865
949
|
# 60 seconds.
|
950
|
+
# @return [Integer] current number of registered Sidekiq processes
|
866
951
|
def size
|
867
952
|
Sidekiq.redis { |conn| conn.scard("processes") }
|
868
953
|
end
|
@@ -870,10 +955,12 @@ module Sidekiq
|
|
870
955
|
# Total number of threads available to execute jobs.
|
871
956
|
# For Sidekiq Enterprise customers this number (in production) must be
|
872
957
|
# less than or equal to your licensed concurrency.
|
958
|
+
# @return [Integer] the sum of process concurrency
|
873
959
|
def total_concurrency
|
874
960
|
sum { |x| x["concurrency"].to_i }
|
875
961
|
end
|
876
962
|
|
963
|
+
# @return [Integer] total amount of RSS memory consumed by Sidekiq processes
|
877
964
|
def total_rss_in_kb
|
878
965
|
sum { |x| x["rss"].to_i }
|
879
966
|
end
|
@@ -882,6 +969,8 @@ module Sidekiq
|
|
882
969
|
# Returns the identity of the current cluster leader or "" if no leader.
|
883
970
|
# This is a Sidekiq Enterprise feature, will always return "" in Sidekiq
|
884
971
|
# or Sidekiq Pro.
|
972
|
+
# @return [String] Identity of cluster leader
|
973
|
+
# @return [String] empty string if no leader
|
885
974
|
def leader
|
886
975
|
@leader ||= begin
|
887
976
|
x = Sidekiq.redis { |c| c.get("dear-leader") }
|
@@ -908,6 +997,8 @@ module Sidekiq
|
|
908
997
|
# 'identity' => <unique string identifying the process>,
|
909
998
|
# }
|
910
999
|
class Process
|
1000
|
+
# :nodoc:
|
1001
|
+
# @api private
|
911
1002
|
def initialize(hash)
|
912
1003
|
@attribs = hash
|
913
1004
|
end
|
@@ -932,18 +1023,31 @@ module Sidekiq
|
|
932
1023
|
self["queues"]
|
933
1024
|
end
|
934
1025
|
|
1026
|
+
# Signal this process to stop processing new jobs.
|
1027
|
+
# It will continue to execute jobs it has already fetched.
|
1028
|
+
# This method is *asynchronous* and it can take 5-10
|
1029
|
+
# seconds for the process to quiet.
|
935
1030
|
def quiet!
|
936
1031
|
signal("TSTP")
|
937
1032
|
end
|
938
1033
|
|
1034
|
+
# Signal this process to shutdown.
|
1035
|
+
# It will shutdown within its configured :timeout value, default 25 seconds.
|
1036
|
+
# This method is *asynchronous* and it can take 5-10
|
1037
|
+
# seconds for the process to start shutting down.
|
939
1038
|
def stop!
|
940
1039
|
signal("TERM")
|
941
1040
|
end
|
942
1041
|
|
1042
|
+
# Signal this process to log backtraces for all threads.
|
1043
|
+
# Useful if you have a frozen or deadlocked process which is
|
1044
|
+
# still sending a heartbeat.
|
1045
|
+
# This method is *asynchronous* and it can take 5-10 seconds.
|
943
1046
|
def dump_threads
|
944
1047
|
signal("TTIN")
|
945
1048
|
end
|
946
1049
|
|
1050
|
+
# @return [Boolean] true if this process is quiet or shutting down
|
947
1051
|
def stopping?
|
948
1052
|
self["quiet"] == "true"
|
949
1053
|
end
|
data/lib/sidekiq/cli.rb
CHANGED
data/lib/sidekiq/client.rb
CHANGED
data/lib/sidekiq/component.rb
CHANGED
@@ -47,6 +47,7 @@ module Sidekiq
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def fire_event(event, options = {})
|
50
|
+
oneshot = options.fetch(:oneshot, true)
|
50
51
|
reverse = options[:reverse]
|
51
52
|
reraise = options[:reraise]
|
52
53
|
|
@@ -58,7 +59,7 @@ module Sidekiq
|
|
58
59
|
handle_exception(ex, {context: "Exception during Sidekiq lifecycle event.", event: event})
|
59
60
|
raise ex if reraise
|
60
61
|
end
|
61
|
-
arr.clear # once we've fired an event, we never fire it again
|
62
|
+
arr.clear if oneshot # once we've fired an event, we never fire it again
|
62
63
|
end
|
63
64
|
end
|
64
65
|
end
|
data/lib/sidekiq/fetch.rb
CHANGED
@@ -33,7 +33,7 @@ module Sidekiq # :nodoc:
|
|
33
33
|
@queues = @config[:queues].map { |q| "queue:#{q}" }
|
34
34
|
if @strictly_ordered_queues
|
35
35
|
@queues.uniq!
|
36
|
-
@queues << TIMEOUT
|
36
|
+
@queues << {timeout: TIMEOUT}
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
@@ -83,7 +83,7 @@ module Sidekiq # :nodoc:
|
|
83
83
|
else
|
84
84
|
permute = @queues.shuffle
|
85
85
|
permute.uniq!
|
86
|
-
permute << TIMEOUT
|
86
|
+
permute << {timeout: TIMEOUT}
|
87
87
|
permute
|
88
88
|
end
|
89
89
|
end
|