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.

Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/Changes.md +34 -0
  3. data/lib/sidekiq/api.rb +128 -24
  4. data/lib/sidekiq/cli.rb +1 -0
  5. data/lib/sidekiq/client.rb +1 -1
  6. data/lib/sidekiq/component.rb +2 -1
  7. data/lib/sidekiq/fetch.rb +2 -2
  8. data/lib/sidekiq/job_retry.rb +55 -35
  9. data/lib/sidekiq/launcher.rb +6 -4
  10. data/lib/sidekiq/metrics/deploy.rb +47 -0
  11. data/lib/sidekiq/metrics/query.rb +153 -0
  12. data/lib/sidekiq/metrics/shared.rb +94 -0
  13. data/lib/sidekiq/metrics/tracking.rb +134 -0
  14. data/lib/sidekiq/middleware/chain.rb +70 -35
  15. data/lib/sidekiq/middleware/current_attributes.rb +6 -4
  16. data/lib/sidekiq/processor.rb +9 -3
  17. data/lib/sidekiq/redis_connection.rb +0 -2
  18. data/lib/sidekiq/scheduled.rb +1 -7
  19. data/lib/sidekiq/version.rb +1 -1
  20. data/lib/sidekiq/web/action.rb +3 -3
  21. data/lib/sidekiq/web/application.rb +18 -5
  22. data/lib/sidekiq/web/helpers.rb +24 -1
  23. data/lib/sidekiq/web.rb +5 -1
  24. data/lib/sidekiq.rb +9 -1
  25. data/sidekiq.gemspec +2 -2
  26. data/web/assets/javascripts/application.js +1 -1
  27. data/web/assets/javascripts/chart.min.js +13 -0
  28. data/web/assets/javascripts/chartjs-plugin-annotation.min.js +7 -0
  29. data/web/assets/javascripts/dashboard.js +0 -17
  30. data/web/assets/javascripts/graph.js +16 -0
  31. data/web/assets/javascripts/metrics.js +262 -0
  32. data/web/assets/stylesheets/application.css +44 -1
  33. data/web/locales/el.yml +43 -19
  34. data/web/locales/en.yml +7 -0
  35. data/web/views/_nav.erb +1 -1
  36. data/web/views/busy.erb +1 -1
  37. data/web/views/dashboard.erb +1 -0
  38. data/web/views/metrics.erb +69 -0
  39. data/web/views/metrics_for_job.erb +87 -0
  40. data/web/views/queue.erb +5 -1
  41. metadata +22 -7
  42. data/lib/sidekiq/.DS_Store +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1afbc6a1a0b14403e9148e746c08e0a2b24e634fca05288982c96719675607de
4
- data.tar.gz: 3ff3f8df76b565f42030462eb8d09b673b89751dcd6a0b7c41a255789960d321
3
+ metadata.gz: 7e12ddc46413e3e476d620e04428a86476f4826d7802575110b5c3697a096137
4
+ data.tar.gz: 802bdbc7c0d45a9b793222baca250e292ce852d67902446bc75a0961a36f5677
5
5
  SHA512:
6
- metadata.gz: e8a68611735322d98cc517f1d03ef02394497f8eb505e0db496909cac1f6b7f0179f38ce1966546f717115395102c78fdad9ae0fd947360307b9288dcc22b369
7
- data.tar.gz: 163e41dfb153a4e2ec50d407bde08cb8a395909807053f24478a73af1a6a9858b5aec92cbf618d4d066560a2b7bedaa2f88b48f823609e2d78f21320270cb97e
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
- # Encapsulates a queue within Sidekiq.
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
- def as_json(options = nil) # :nodoc:
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
- # Encapsulates a pending job within a Sidekiq queue or
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
- def initialize(item, queue_name = nil) # :nodoc:
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
- def parse(item) # :nodoc:
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.config[:environment] == "development"
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 for the job.
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
- def initialize(parent, score, item) # :nodoc:
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 when this job will be enqueued.
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
- def as_json(options = nil) # :nodoc:
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
- def schedule(timestamp, message)
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(message))
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 slower O(n) operation. Do not use for app logic.
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
- # Allows enumeration of scheduled jobs within Sidekiq.
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 all jobs of a certain type
714
- # and deleting them from the schedule queue.
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
- # Allows enumeration of retries within Sidekiq.
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
- # Allows enumeration of dead jobs within Sidekiq.
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
- # Yields a Sidekiq::Process.
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
@@ -426,3 +426,4 @@ module Sidekiq # :nodoc:
426
426
  end
427
427
 
428
428
  require "sidekiq/systemd"
429
+ require "sidekiq/metrics/tracking" if ENV["SIDEKIQ_METRICS_BETA"]
@@ -231,7 +231,7 @@ module Sidekiq
231
231
  entry["enqueued_at"] = now
232
232
  Sidekiq.dump_json(entry)
233
233
  }
234
- conn.sadd("queues", queue)
234
+ conn.sadd("queues", [queue])
235
235
  conn.lpush("queue:#{queue}", to_push)
236
236
  end
237
237
  end
@@ -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