sidekiq 6.5.0 → 6.5.3
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 +22 -2
- data/lib/sidekiq/api.rb +146 -27
- data/lib/sidekiq/cli.rb +2 -1
- data/lib/sidekiq/client.rb +1 -1
- data/lib/sidekiq/component.rb +3 -2
- data/lib/sidekiq/delay.rb +1 -1
- data/lib/sidekiq/fetch.rb +1 -1
- data/lib/sidekiq/job_retry.rb +46 -31
- data/lib/sidekiq/launcher.rb +4 -2
- data/lib/sidekiq/metrics/deploy.rb +47 -0
- data/lib/sidekiq/metrics/query.rb +124 -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/middleware/modules.rb +2 -0
- data/lib/sidekiq/processor.rb +1 -1
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web/application.rb +13 -0
- data/lib/sidekiq/web/helpers.rb +24 -1
- data/lib/sidekiq/web.rb +4 -0
- data/lib/sidekiq.rb +9 -1
- data/sidekiq.gemspec +1 -1
- data/web/assets/javascripts/application.js +1 -1
- data/web/assets/javascripts/dashboard.js +0 -17
- data/web/assets/javascripts/graph.js +16 -0
- data/web/locales/en.yml +4 -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 +59 -0
- data/web/views/metrics_for_job.erb +92 -0
- data/web/views/queue.erb +5 -1
- metadata +11 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 46b428cecc373a6b11d27e12622dcfc8661b138e244c16575ad49362c672a60e
|
4
|
+
data.tar.gz: 64fc302563e615eec63e8701b581949cb90738c799714257d98bbd6f359cff45
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b62cefbc386b0113ffe47ca4e10b6752cfd86d973c0a8143e116ad45e2e6c680f0de686c9e2750760c14c71f17e3c13375145ae16a98f6cceab96908ca4cf61
|
7
|
+
data.tar.gz: 0dfc564242453b670e13e656098a3294e0c9831efa9520e025b08d3c265ef6cb148fb4519af78406a43d9972b9e83db1c9d8271ee7288f57401a5e7bb30d401e
|
data/Changes.md
CHANGED
@@ -2,12 +2,32 @@
|
|
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.3
|
6
|
+
----------
|
7
|
+
|
8
|
+
- Don't require metrics code without explicit opt-in [#5456]
|
9
|
+
|
10
|
+
6.5.2
|
11
|
+
----------
|
12
|
+
|
13
|
+
- [Job Metrics are under active development, help wanted!](https://github.com/mperham/sidekiq/wiki/Metrics#contributing) **BETA**
|
14
|
+
- Add `Context` column on queue page which shows any CurrentAttributes [#5450]
|
15
|
+
- `sidekiq_retry_in` may now return `:discard` or `:kill` to dynamically stop job retries [#5406]
|
16
|
+
- Smarter sorting of processes in /busy Web UI [#5398]
|
17
|
+
- Fix broken hamburger menu in mobile UI [#5428]
|
18
|
+
- Require redis-rb 4.5.0. Note that Sidekiq will break if you use the
|
19
|
+
[`Redis.exists_returns_integer = false`](https://github.com/redis/redis-rb/blob/master/CHANGELOG.md#450) flag. [#5394]
|
20
|
+
|
21
|
+
6.5.1
|
22
|
+
----------
|
23
|
+
|
24
|
+
- Fix `push_bulk` breakage [#5387]
|
25
|
+
|
5
26
|
6.5.0
|
6
27
|
---------
|
7
28
|
|
8
29
|
- Substantial refactoring of Sidekiq server internals, part of a larger effort
|
9
|
-
to reduce Sidekiq's internal usage of global methods and data, see [docs/
|
10
|
-
[docs/global_to_local.md](docs/global_to_local.md) and [docs/middleware.md](docs/middleware.md).
|
30
|
+
to reduce Sidekiq's internal usage of global methods and data, see [docs/global_to_local.md](docs/global_to_local.md) and [docs/middleware.md](docs/middleware.md).
|
11
31
|
- **Add beta support for the `redis-client` gem**. This will become the default Redis driver in Sidekiq 7.0. [#5298]
|
12
32
|
Read more: https://github.com/mperham/sidekiq/wiki/Using-redis-client
|
13
33
|
- **Add beta support for DB transaction-aware client** [#5291]
|
data/lib/sidekiq/api.rb
CHANGED
@@ -3,9 +3,17 @@
|
|
3
3
|
require "sidekiq"
|
4
4
|
|
5
5
|
require "zlib"
|
6
|
+
require "set"
|
6
7
|
require "base64"
|
8
|
+
require "sidekiq/metrics/deploy"
|
9
|
+
require "sidekiq/metrics/query"
|
7
10
|
|
8
11
|
module Sidekiq
|
12
|
+
# Retrieve runtime statistics from Redis regarding
|
13
|
+
# this Sidekiq cluster.
|
14
|
+
#
|
15
|
+
# stat = Sidekiq::Stats.new
|
16
|
+
# stat.processed
|
9
17
|
class Stats
|
10
18
|
def initialize
|
11
19
|
fetch_stats_fast!
|
@@ -52,6 +60,7 @@ module Sidekiq
|
|
52
60
|
end
|
53
61
|
|
54
62
|
# O(1) redis calls
|
63
|
+
# @api private
|
55
64
|
def fetch_stats_fast!
|
56
65
|
pipe1_res = Sidekiq.redis { |conn|
|
57
66
|
conn.pipelined do |pipeline|
|
@@ -91,6 +100,7 @@ module Sidekiq
|
|
91
100
|
end
|
92
101
|
|
93
102
|
# O(number of processes + number of queues) redis calls
|
103
|
+
# @api private
|
94
104
|
def fetch_stats_slow!
|
95
105
|
processes = Sidekiq.redis { |conn|
|
96
106
|
conn.sscan_each("processes").to_a
|
@@ -116,11 +126,13 @@ module Sidekiq
|
|
116
126
|
@stats
|
117
127
|
end
|
118
128
|
|
129
|
+
# @api private
|
119
130
|
def fetch_stats!
|
120
131
|
fetch_stats_fast!
|
121
132
|
fetch_stats_slow!
|
122
133
|
end
|
123
134
|
|
135
|
+
# @api private
|
124
136
|
def reset(*stats)
|
125
137
|
all = %w[failed processed]
|
126
138
|
stats = stats.empty? ? all : all & stats.flatten.compact.map(&:to_s)
|
@@ -202,9 +214,10 @@ module Sidekiq
|
|
202
214
|
end
|
203
215
|
|
204
216
|
##
|
205
|
-
#
|
217
|
+
# Represents a queue within Sidekiq.
|
206
218
|
# Allows enumeration of all jobs within the queue
|
207
|
-
# and deletion of jobs.
|
219
|
+
# and deletion of jobs. NB: this queue data is real-time
|
220
|
+
# and is changing within Redis moment by moment.
|
208
221
|
#
|
209
222
|
# queue = Sidekiq::Queue.new("mailer")
|
210
223
|
# queue.each do |job|
|
@@ -212,29 +225,34 @@ module Sidekiq
|
|
212
225
|
# job.args # => [1, 2, 3]
|
213
226
|
# job.delete if job.jid == 'abcdef1234567890'
|
214
227
|
# end
|
215
|
-
#
|
216
228
|
class Queue
|
217
229
|
include Enumerable
|
218
230
|
|
219
231
|
##
|
220
|
-
#
|
232
|
+
# Fetch all known queues within Redis.
|
221
233
|
#
|
234
|
+
# @return [Array<Sidekiq::Queue>]
|
222
235
|
def self.all
|
223
236
|
Sidekiq.redis { |c| c.sscan_each("queues").to_a }.sort.map { |q| Sidekiq::Queue.new(q) }
|
224
237
|
end
|
225
238
|
|
226
239
|
attr_reader :name
|
227
240
|
|
241
|
+
# @param name [String] the name of the queue
|
228
242
|
def initialize(name = "default")
|
229
243
|
@name = name.to_s
|
230
244
|
@rname = "queue:#{name}"
|
231
245
|
end
|
232
246
|
|
247
|
+
# The current size of the queue within Redis.
|
248
|
+
# This value is real-time and can change between calls.
|
249
|
+
#
|
250
|
+
# @return [Integer] the size
|
233
251
|
def size
|
234
252
|
Sidekiq.redis { |con| con.llen(@rname) }
|
235
253
|
end
|
236
254
|
|
237
|
-
#
|
255
|
+
# @return [Boolean] if the queue is currently paused
|
238
256
|
def paused?
|
239
257
|
false
|
240
258
|
end
|
@@ -243,7 +261,7 @@ module Sidekiq
|
|
243
261
|
# Calculates this queue's latency, the difference in seconds since the oldest
|
244
262
|
# job in the queue was enqueued.
|
245
263
|
#
|
246
|
-
# @return Float
|
264
|
+
# @return [Float] in seconds
|
247
265
|
def latency
|
248
266
|
entry = Sidekiq.redis { |conn|
|
249
267
|
conn.lrange(@rname, -1, -1)
|
@@ -279,12 +297,18 @@ module Sidekiq
|
|
279
297
|
##
|
280
298
|
# Find the job with the given JID within this queue.
|
281
299
|
#
|
282
|
-
# This is a slow, inefficient operation. Do not use under
|
300
|
+
# This is a *slow, inefficient* operation. Do not use under
|
283
301
|
# normal conditions.
|
302
|
+
#
|
303
|
+
# @param jid [String] the job_id to look for
|
304
|
+
# @return [Sidekiq::JobRecord]
|
305
|
+
# @return [nil] if not found
|
284
306
|
def find_job(jid)
|
285
307
|
detect { |j| j.jid == jid }
|
286
308
|
end
|
287
309
|
|
310
|
+
# delete all jobs within this queue
|
311
|
+
# @return [Boolean] true
|
288
312
|
def clear
|
289
313
|
Sidekiq.redis do |conn|
|
290
314
|
conn.multi do |transaction|
|
@@ -292,25 +316,35 @@ module Sidekiq
|
|
292
316
|
transaction.srem("queues", name)
|
293
317
|
end
|
294
318
|
end
|
319
|
+
true
|
295
320
|
end
|
296
321
|
alias_method :💣, :clear
|
297
322
|
|
298
|
-
|
323
|
+
# :nodoc:
|
324
|
+
# @api private
|
325
|
+
def as_json(options = nil)
|
299
326
|
{name: name} # 5336
|
300
327
|
end
|
301
328
|
end
|
302
329
|
|
303
330
|
##
|
304
|
-
#
|
305
|
-
# sorted set.
|
331
|
+
# Represents a pending job within a Sidekiq queue.
|
306
332
|
#
|
307
333
|
# The job should be considered immutable but may be
|
308
334
|
# removed from the queue via JobRecord#delete.
|
309
|
-
#
|
310
335
|
class JobRecord
|
336
|
+
# the parsed Hash of job data
|
337
|
+
# @!attribute [r] Item
|
311
338
|
attr_reader :item
|
339
|
+
# the underlying String in Redis
|
340
|
+
# @!attribute [r] Value
|
312
341
|
attr_reader :value
|
342
|
+
# the queue associated with this job
|
343
|
+
# @!attribute [r] Queue
|
344
|
+
attr_reader :queue
|
313
345
|
|
346
|
+
# :nodoc:
|
347
|
+
# @api private
|
314
348
|
def initialize(item, queue_name = nil)
|
315
349
|
@args = nil
|
316
350
|
@value = item
|
@@ -318,6 +352,8 @@ module Sidekiq
|
|
318
352
|
@queue = queue_name || @item["queue"]
|
319
353
|
end
|
320
354
|
|
355
|
+
# :nodoc:
|
356
|
+
# @api private
|
321
357
|
def parse(item)
|
322
358
|
Sidekiq.load_json(item)
|
323
359
|
rescue JSON::ParserError
|
@@ -329,6 +365,8 @@ module Sidekiq
|
|
329
365
|
{}
|
330
366
|
end
|
331
367
|
|
368
|
+
# This is the job class which Sidekiq will execute. If using ActiveJob,
|
369
|
+
# this class will be the ActiveJob adapter class rather than a specific job.
|
332
370
|
def klass
|
333
371
|
self["class"]
|
334
372
|
end
|
@@ -416,15 +454,12 @@ module Sidekiq
|
|
416
454
|
end
|
417
455
|
end
|
418
456
|
|
419
|
-
attr_reader :queue
|
420
|
-
|
421
457
|
def latency
|
422
458
|
now = Time.now.to_f
|
423
459
|
now - (@item["enqueued_at"] || @item["created_at"] || now)
|
424
460
|
end
|
425
461
|
|
426
|
-
|
427
|
-
# Remove this job from the queue.
|
462
|
+
# Remove this job from the queue
|
428
463
|
def delete
|
429
464
|
count = Sidekiq.redis { |conn|
|
430
465
|
conn.lrem("queue:#{@queue}", 1, @value)
|
@@ -432,6 +467,7 @@ module Sidekiq
|
|
432
467
|
count != 0
|
433
468
|
end
|
434
469
|
|
470
|
+
# Access arbitrary attributes within the job hash
|
435
471
|
def [](name)
|
436
472
|
# nil will happen if the JSON fails to parse.
|
437
473
|
# We don't guarantee Sidekiq will work with bad job JSON but we should
|
@@ -469,20 +505,28 @@ module Sidekiq
|
|
469
505
|
end
|
470
506
|
end
|
471
507
|
|
508
|
+
# Represents a job within a Redis sorted set where the score
|
509
|
+
# represents a timestamp associated with the job. This timestamp
|
510
|
+
# could be the scheduled time for it to run (e.g. scheduled set),
|
511
|
+
# or the expiration date after which the entry should be deleted (e.g. dead set).
|
472
512
|
class SortedEntry < JobRecord
|
473
513
|
attr_reader :score
|
474
514
|
attr_reader :parent
|
475
515
|
|
516
|
+
# :nodoc:
|
517
|
+
# @api private
|
476
518
|
def initialize(parent, score, item)
|
477
519
|
super(item)
|
478
520
|
@score = Float(score)
|
479
521
|
@parent = parent
|
480
522
|
end
|
481
523
|
|
524
|
+
# The timestamp associated with this entry
|
482
525
|
def at
|
483
526
|
Time.at(score).utc
|
484
527
|
end
|
485
528
|
|
529
|
+
# remove this entry from the sorted set
|
486
530
|
def delete
|
487
531
|
if @value
|
488
532
|
@parent.delete_by_value(@parent.name, @value)
|
@@ -491,12 +535,17 @@ module Sidekiq
|
|
491
535
|
end
|
492
536
|
end
|
493
537
|
|
538
|
+
# Change the scheduled time for this job.
|
539
|
+
#
|
540
|
+
# @param at [Time] the new timestamp for this job
|
494
541
|
def reschedule(at)
|
495
542
|
Sidekiq.redis do |conn|
|
496
543
|
conn.zincrby(@parent.name, at.to_f - @score, Sidekiq.dump_json(@item))
|
497
544
|
end
|
498
545
|
end
|
499
546
|
|
547
|
+
# Enqueue this job from the scheduled or dead set so it will
|
548
|
+
# be executed at some point in the near future.
|
500
549
|
def add_to_queue
|
501
550
|
remove_job do |message|
|
502
551
|
msg = Sidekiq.load_json(message)
|
@@ -504,6 +553,8 @@ module Sidekiq
|
|
504
553
|
end
|
505
554
|
end
|
506
555
|
|
556
|
+
# enqueue this job from the retry set so it will be executed
|
557
|
+
# at some point in the near future.
|
507
558
|
def retry
|
508
559
|
remove_job do |message|
|
509
560
|
msg = Sidekiq.load_json(message)
|
@@ -512,8 +563,7 @@ module Sidekiq
|
|
512
563
|
end
|
513
564
|
end
|
514
565
|
|
515
|
-
|
516
|
-
# Place job in the dead set
|
566
|
+
# Move this job from its current set into the Dead set.
|
517
567
|
def kill
|
518
568
|
remove_job do |message|
|
519
569
|
DeadSet.new.kill(message)
|
@@ -561,20 +611,32 @@ module Sidekiq
|
|
561
611
|
end
|
562
612
|
end
|
563
613
|
|
614
|
+
# Base class for all sorted sets within Sidekiq.
|
564
615
|
class SortedSet
|
565
616
|
include Enumerable
|
566
617
|
|
618
|
+
# Redis key of the set
|
619
|
+
# @!attribute [r] Name
|
567
620
|
attr_reader :name
|
568
621
|
|
622
|
+
# :nodoc:
|
623
|
+
# @api private
|
569
624
|
def initialize(name)
|
570
625
|
@name = name
|
571
626
|
@_size = size
|
572
627
|
end
|
573
628
|
|
629
|
+
# real-time size of the set, will change
|
574
630
|
def size
|
575
631
|
Sidekiq.redis { |c| c.zcard(name) }
|
576
632
|
end
|
577
633
|
|
634
|
+
# Scan through each element of the sorted set, yielding each to the supplied block.
|
635
|
+
# Please see Redis's <a href="https://redis.io/commands/scan/">SCAN documentation</a> for implementation details.
|
636
|
+
#
|
637
|
+
# @param match [String] a snippet or regexp to filter matches.
|
638
|
+
# @param count [Integer] number of elements to retrieve at a time, default 100
|
639
|
+
# @yieldparam [Sidekiq::SortedEntry] each entry
|
578
640
|
def scan(match, count = 100)
|
579
641
|
return to_enum(:scan, match, count) unless block_given?
|
580
642
|
|
@@ -586,22 +648,32 @@ module Sidekiq
|
|
586
648
|
end
|
587
649
|
end
|
588
650
|
|
651
|
+
# @return [Boolean] always true
|
589
652
|
def clear
|
590
653
|
Sidekiq.redis do |conn|
|
591
654
|
conn.unlink(name)
|
592
655
|
end
|
656
|
+
true
|
593
657
|
end
|
594
658
|
alias_method :💣, :clear
|
595
659
|
|
596
|
-
|
660
|
+
# :nodoc:
|
661
|
+
# @api private
|
662
|
+
def as_json(options = nil)
|
597
663
|
{name: name} # 5336
|
598
664
|
end
|
599
665
|
end
|
600
666
|
|
667
|
+
# Base class for all sorted sets which contain jobs, e.g. scheduled, retry and dead.
|
668
|
+
# Sidekiq Pro and Enterprise add additional sorted sets which do not contain job data,
|
669
|
+
# e.g. Batches.
|
601
670
|
class JobSet < SortedSet
|
602
|
-
|
671
|
+
# Add a job with the associated timestamp to this set.
|
672
|
+
# @param timestamp [Time] the score for the job
|
673
|
+
# @param job [Hash] the job data
|
674
|
+
def schedule(timestamp, job)
|
603
675
|
Sidekiq.redis do |conn|
|
604
|
-
conn.zadd(name, timestamp.to_f.to_s, Sidekiq.dump_json(
|
676
|
+
conn.zadd(name, timestamp.to_f.to_s, Sidekiq.dump_json(job))
|
605
677
|
end
|
606
678
|
end
|
607
679
|
|
@@ -629,6 +701,10 @@ module Sidekiq
|
|
629
701
|
##
|
630
702
|
# Fetch jobs that match a given time or Range. Job ID is an
|
631
703
|
# optional second argument.
|
704
|
+
#
|
705
|
+
# @param score [Time,Range] a specific timestamp or range
|
706
|
+
# @param jid [String, optional] find a specific JID within the score
|
707
|
+
# @return [Array<SortedEntry>] any results found, can be empty
|
632
708
|
def fetch(score, jid = nil)
|
633
709
|
begin_score, end_score =
|
634
710
|
if score.is_a?(Range)
|
@@ -650,7 +726,10 @@ module Sidekiq
|
|
650
726
|
|
651
727
|
##
|
652
728
|
# Find the job with the given JID within this sorted set.
|
653
|
-
# This is a
|
729
|
+
# *This is a slow O(n) operation*. Do not use for app logic.
|
730
|
+
#
|
731
|
+
# @param jid [String] the job identifier
|
732
|
+
# @return [SortedEntry] the record or nil
|
654
733
|
def find_job(jid)
|
655
734
|
Sidekiq.redis do |conn|
|
656
735
|
conn.zscan_each(name, match: "*#{jid}*", count: 100) do |entry, score|
|
@@ -662,6 +741,8 @@ module Sidekiq
|
|
662
741
|
nil
|
663
742
|
end
|
664
743
|
|
744
|
+
# :nodoc:
|
745
|
+
# @api private
|
665
746
|
def delete_by_value(name, value)
|
666
747
|
Sidekiq.redis do |conn|
|
667
748
|
ret = conn.zrem(name, value)
|
@@ -670,6 +751,8 @@ module Sidekiq
|
|
670
751
|
end
|
671
752
|
end
|
672
753
|
|
754
|
+
# :nodoc:
|
755
|
+
# @api private
|
673
756
|
def delete_by_jid(score, jid)
|
674
757
|
Sidekiq.redis do |conn|
|
675
758
|
elements = conn.zrangebyscore(name, score, score)
|
@@ -690,10 +773,10 @@ module Sidekiq
|
|
690
773
|
end
|
691
774
|
|
692
775
|
##
|
693
|
-
#
|
776
|
+
# The set of scheduled jobs within Sidekiq.
|
694
777
|
# Based on this, you can search/filter for jobs. Here's an
|
695
|
-
# example where I'm selecting
|
696
|
-
# and deleting them from the
|
778
|
+
# example where I'm selecting jobs based on some complex logic
|
779
|
+
# and deleting them from the scheduled set.
|
697
780
|
#
|
698
781
|
# r = Sidekiq::ScheduledSet.new
|
699
782
|
# r.select do |scheduled|
|
@@ -708,7 +791,7 @@ module Sidekiq
|
|
708
791
|
end
|
709
792
|
|
710
793
|
##
|
711
|
-
#
|
794
|
+
# The set of retries within Sidekiq.
|
712
795
|
# Based on this, you can search/filter for jobs. Here's an
|
713
796
|
# example where I'm selecting all jobs of a certain type
|
714
797
|
# and deleting them from the retry queue.
|
@@ -724,23 +807,29 @@ module Sidekiq
|
|
724
807
|
super "retry"
|
725
808
|
end
|
726
809
|
|
810
|
+
# Enqueues all jobs pending within the retry set.
|
727
811
|
def retry_all
|
728
812
|
each(&:retry) while size > 0
|
729
813
|
end
|
730
814
|
|
815
|
+
# Kills all jobs pending within the retry set.
|
731
816
|
def kill_all
|
732
817
|
each(&:kill) while size > 0
|
733
818
|
end
|
734
819
|
end
|
735
820
|
|
736
821
|
##
|
737
|
-
#
|
822
|
+
# The set of dead jobs within Sidekiq. Dead jobs have failed all of
|
823
|
+
# their retries and are helding in this set pending some sort of manual
|
824
|
+
# fix. They will be removed after 6 months (dead_timeout) if not.
|
738
825
|
#
|
739
826
|
class DeadSet < JobSet
|
740
827
|
def initialize
|
741
828
|
super "dead"
|
742
829
|
end
|
743
830
|
|
831
|
+
# Add the given job to the Dead set.
|
832
|
+
# @param message [String] the job data as JSON
|
744
833
|
def kill(message, opts = {})
|
745
834
|
now = Time.now.to_f
|
746
835
|
Sidekiq.redis do |conn|
|
@@ -762,14 +851,19 @@ module Sidekiq
|
|
762
851
|
true
|
763
852
|
end
|
764
853
|
|
854
|
+
# Enqueue all dead jobs
|
765
855
|
def retry_all
|
766
856
|
each(&:retry) while size > 0
|
767
857
|
end
|
768
858
|
|
859
|
+
# The maximum size of the Dead set. Older entries will be trimmed
|
860
|
+
# to stay within this limit. Default value is 10,000.
|
769
861
|
def self.max_jobs
|
770
862
|
Sidekiq[:dead_max_jobs]
|
771
863
|
end
|
772
864
|
|
865
|
+
# The time limit for entries within the Dead set. Older entries will be thrown away.
|
866
|
+
# Default value is six months.
|
773
867
|
def self.timeout
|
774
868
|
Sidekiq[:dead_timeout_in_seconds]
|
775
869
|
end
|
@@ -780,18 +874,23 @@ module Sidekiq
|
|
780
874
|
# right now. Each process sends a heartbeat to Redis every 5 seconds
|
781
875
|
# so this set should be relatively accurate, barring network partitions.
|
782
876
|
#
|
783
|
-
#
|
877
|
+
# @yieldparam [Sidekiq::Process]
|
784
878
|
#
|
785
879
|
class ProcessSet
|
786
880
|
include Enumerable
|
787
881
|
|
882
|
+
# :nodoc:
|
883
|
+
# @api private
|
788
884
|
def initialize(clean_plz = true)
|
789
885
|
cleanup if clean_plz
|
790
886
|
end
|
791
887
|
|
792
888
|
# Cleans up dead processes recorded in Redis.
|
793
889
|
# Returns the number of processes cleaned.
|
890
|
+
# :nodoc:
|
891
|
+
# @api private
|
794
892
|
def cleanup
|
893
|
+
return 0 unless Sidekiq.redis { |conn| conn.set("process_cleanup", "1", nx: true, ex: 60) }
|
795
894
|
count = 0
|
796
895
|
Sidekiq.redis do |conn|
|
797
896
|
procs = conn.sscan_each("processes").to_a.sort
|
@@ -845,6 +944,7 @@ module Sidekiq
|
|
845
944
|
# based on current heartbeat. #each does that and ensures the set only
|
846
945
|
# contains Sidekiq processes which have sent a heartbeat within the last
|
847
946
|
# 60 seconds.
|
947
|
+
# @return [Integer] current number of registered Sidekiq processes
|
848
948
|
def size
|
849
949
|
Sidekiq.redis { |conn| conn.scard("processes") }
|
850
950
|
end
|
@@ -852,10 +952,12 @@ module Sidekiq
|
|
852
952
|
# Total number of threads available to execute jobs.
|
853
953
|
# For Sidekiq Enterprise customers this number (in production) must be
|
854
954
|
# less than or equal to your licensed concurrency.
|
955
|
+
# @return [Integer] the sum of process concurrency
|
855
956
|
def total_concurrency
|
856
957
|
sum { |x| x["concurrency"].to_i }
|
857
958
|
end
|
858
959
|
|
960
|
+
# @return [Integer] total amount of RSS memory consumed by Sidekiq processes
|
859
961
|
def total_rss_in_kb
|
860
962
|
sum { |x| x["rss"].to_i }
|
861
963
|
end
|
@@ -864,6 +966,8 @@ module Sidekiq
|
|
864
966
|
# Returns the identity of the current cluster leader or "" if no leader.
|
865
967
|
# This is a Sidekiq Enterprise feature, will always return "" in Sidekiq
|
866
968
|
# or Sidekiq Pro.
|
969
|
+
# @return [String] Identity of cluster leader
|
970
|
+
# @return [String] empty string if no leader
|
867
971
|
def leader
|
868
972
|
@leader ||= begin
|
869
973
|
x = Sidekiq.redis { |c| c.get("dear-leader") }
|
@@ -890,6 +994,8 @@ module Sidekiq
|
|
890
994
|
# 'identity' => <unique string identifying the process>,
|
891
995
|
# }
|
892
996
|
class Process
|
997
|
+
# :nodoc:
|
998
|
+
# @api private
|
893
999
|
def initialize(hash)
|
894
1000
|
@attribs = hash
|
895
1001
|
end
|
@@ -914,18 +1020,31 @@ module Sidekiq
|
|
914
1020
|
self["queues"]
|
915
1021
|
end
|
916
1022
|
|
1023
|
+
# Signal this process to stop processing new jobs.
|
1024
|
+
# It will continue to execute jobs it has already fetched.
|
1025
|
+
# This method is *asynchronous* and it can take 5-10
|
1026
|
+
# seconds for the process to quiet.
|
917
1027
|
def quiet!
|
918
1028
|
signal("TSTP")
|
919
1029
|
end
|
920
1030
|
|
1031
|
+
# Signal this process to shutdown.
|
1032
|
+
# It will shutdown within its configured :timeout value, default 25 seconds.
|
1033
|
+
# This method is *asynchronous* and it can take 5-10
|
1034
|
+
# seconds for the process to start shutting down.
|
921
1035
|
def stop!
|
922
1036
|
signal("TERM")
|
923
1037
|
end
|
924
1038
|
|
1039
|
+
# Signal this process to log backtraces for all threads.
|
1040
|
+
# Useful if you have a frozen or deadlocked process which is
|
1041
|
+
# still sending a heartbeat.
|
1042
|
+
# This method is *asynchronous* and it can take 5-10 seconds.
|
925
1043
|
def dump_threads
|
926
1044
|
signal("TTIN")
|
927
1045
|
end
|
928
1046
|
|
1047
|
+
# @return [Boolean] true if this process is quiet or shutting down
|
929
1048
|
def stopping?
|
930
1049
|
self["quiet"] == "true"
|
931
1050
|
end
|
data/lib/sidekiq/cli.rb
CHANGED
@@ -12,7 +12,7 @@ require "sidekiq"
|
|
12
12
|
require "sidekiq/component"
|
13
13
|
require "sidekiq/launcher"
|
14
14
|
|
15
|
-
module Sidekiq
|
15
|
+
module Sidekiq # :nodoc:
|
16
16
|
class CLI
|
17
17
|
include Sidekiq::Component
|
18
18
|
include Singleton unless $TESTING
|
@@ -426,3 +426,4 @@ module Sidekiq
|
|
426
426
|
end
|
427
427
|
|
428
428
|
require "sidekiq/systemd"
|
429
|
+
require "sidekiq/metrics/tracking" if ENV["SIDEKIQ_METRICS_BETA"]
|
data/lib/sidekiq/client.rb
CHANGED
@@ -220,7 +220,7 @@ module Sidekiq
|
|
220
220
|
|
221
221
|
def atomic_push(conn, payloads)
|
222
222
|
if payloads.first.key?("at")
|
223
|
-
conn.zadd("schedule",
|
223
|
+
conn.zadd("schedule", payloads.flat_map { |hash|
|
224
224
|
at = hash.delete("at").to_s
|
225
225
|
[at, Sidekiq.dump_json(hash)]
|
226
226
|
})
|
data/lib/sidekiq/component.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Sidekiq
|
2
2
|
##
|
3
3
|
# Sidekiq::Component assumes a config instance is available at @config
|
4
|
-
module Component
|
4
|
+
module Component # :nodoc:
|
5
5
|
attr_reader :config
|
6
6
|
|
7
7
|
def watchdog(last_words)
|
@@ -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/delay.rb
CHANGED