sidekiq 4.2.10 → 7.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (158) hide show
  1. checksums.yaml +5 -5
  2. data/Changes.md +859 -7
  3. data/LICENSE.txt +9 -0
  4. data/README.md +49 -50
  5. data/bin/multi_queue_bench +271 -0
  6. data/bin/sidekiq +22 -3
  7. data/bin/sidekiqload +212 -119
  8. data/bin/sidekiqmon +11 -0
  9. data/lib/generators/sidekiq/job_generator.rb +59 -0
  10. data/lib/generators/sidekiq/templates/{worker.rb.erb → job.rb.erb} +2 -2
  11. data/lib/generators/sidekiq/templates/job_spec.rb.erb +6 -0
  12. data/lib/generators/sidekiq/templates/{worker_test.rb.erb → job_test.rb.erb} +1 -1
  13. data/lib/sidekiq/api.rb +680 -315
  14. data/lib/sidekiq/capsule.rb +132 -0
  15. data/lib/sidekiq/cli.rb +268 -248
  16. data/lib/sidekiq/client.rb +136 -101
  17. data/lib/sidekiq/component.rb +68 -0
  18. data/lib/sidekiq/config.rb +293 -0
  19. data/lib/sidekiq/deploy.rb +64 -0
  20. data/lib/sidekiq/embedded.rb +63 -0
  21. data/lib/sidekiq/fetch.rb +49 -42
  22. data/lib/sidekiq/iterable_job.rb +55 -0
  23. data/lib/sidekiq/job/interrupt_handler.rb +24 -0
  24. data/lib/sidekiq/job/iterable/active_record_enumerator.rb +53 -0
  25. data/lib/sidekiq/job/iterable/csv_enumerator.rb +47 -0
  26. data/lib/sidekiq/job/iterable/enumerators.rb +135 -0
  27. data/lib/sidekiq/job/iterable.rb +231 -0
  28. data/lib/sidekiq/job.rb +385 -0
  29. data/lib/sidekiq/job_logger.rb +62 -0
  30. data/lib/sidekiq/job_retry.rb +305 -0
  31. data/lib/sidekiq/job_util.rb +109 -0
  32. data/lib/sidekiq/launcher.rb +208 -108
  33. data/lib/sidekiq/logger.rb +131 -0
  34. data/lib/sidekiq/manager.rb +43 -47
  35. data/lib/sidekiq/metrics/query.rb +158 -0
  36. data/lib/sidekiq/metrics/shared.rb +97 -0
  37. data/lib/sidekiq/metrics/tracking.rb +148 -0
  38. data/lib/sidekiq/middleware/chain.rb +113 -56
  39. data/lib/sidekiq/middleware/current_attributes.rb +113 -0
  40. data/lib/sidekiq/middleware/i18n.rb +7 -7
  41. data/lib/sidekiq/middleware/modules.rb +23 -0
  42. data/lib/sidekiq/monitor.rb +147 -0
  43. data/lib/sidekiq/paginator.rb +28 -16
  44. data/lib/sidekiq/processor.rb +188 -98
  45. data/lib/sidekiq/rails.rb +46 -97
  46. data/lib/sidekiq/redis_client_adapter.rb +114 -0
  47. data/lib/sidekiq/redis_connection.rb +71 -73
  48. data/lib/sidekiq/ring_buffer.rb +31 -0
  49. data/lib/sidekiq/scheduled.rb +140 -51
  50. data/lib/sidekiq/sd_notify.rb +149 -0
  51. data/lib/sidekiq/systemd.rb +26 -0
  52. data/lib/sidekiq/testing/inline.rb +6 -5
  53. data/lib/sidekiq/testing.rb +95 -85
  54. data/lib/sidekiq/transaction_aware_client.rb +51 -0
  55. data/lib/sidekiq/version.rb +3 -1
  56. data/lib/sidekiq/web/action.rb +22 -16
  57. data/lib/sidekiq/web/application.rb +230 -86
  58. data/lib/sidekiq/web/csrf_protection.rb +183 -0
  59. data/lib/sidekiq/web/helpers.rb +241 -104
  60. data/lib/sidekiq/web/router.rb +23 -19
  61. data/lib/sidekiq/web.rb +118 -110
  62. data/lib/sidekiq/worker_compatibility_alias.rb +13 -0
  63. data/lib/sidekiq.rb +96 -185
  64. data/sidekiq.gemspec +26 -27
  65. data/web/assets/images/apple-touch-icon.png +0 -0
  66. data/web/assets/javascripts/application.js +157 -61
  67. data/web/assets/javascripts/base-charts.js +106 -0
  68. data/web/assets/javascripts/chart.min.js +13 -0
  69. data/web/assets/javascripts/chartjs-plugin-annotation.min.js +7 -0
  70. data/web/assets/javascripts/dashboard-charts.js +192 -0
  71. data/web/assets/javascripts/dashboard.js +37 -280
  72. data/web/assets/javascripts/metrics.js +298 -0
  73. data/web/assets/stylesheets/application-dark.css +147 -0
  74. data/web/assets/stylesheets/application-rtl.css +163 -0
  75. data/web/assets/stylesheets/application.css +173 -198
  76. data/web/assets/stylesheets/bootstrap-rtl.min.css +9 -0
  77. data/web/assets/stylesheets/bootstrap.css +2 -2
  78. data/web/locales/ar.yml +87 -0
  79. data/web/locales/cs.yml +62 -62
  80. data/web/locales/da.yml +60 -53
  81. data/web/locales/de.yml +65 -53
  82. data/web/locales/el.yml +43 -24
  83. data/web/locales/en.yml +86 -64
  84. data/web/locales/es.yml +70 -53
  85. data/web/locales/fa.yml +65 -64
  86. data/web/locales/fr.yml +83 -62
  87. data/web/locales/gd.yml +99 -0
  88. data/web/locales/he.yml +80 -0
  89. data/web/locales/hi.yml +59 -59
  90. data/web/locales/it.yml +53 -53
  91. data/web/locales/ja.yml +75 -62
  92. data/web/locales/ko.yml +52 -52
  93. data/web/locales/lt.yml +83 -0
  94. data/web/locales/nb.yml +61 -61
  95. data/web/locales/nl.yml +52 -52
  96. data/web/locales/pl.yml +45 -45
  97. data/web/locales/pt-br.yml +83 -55
  98. data/web/locales/pt.yml +51 -51
  99. data/web/locales/ru.yml +68 -63
  100. data/web/locales/sv.yml +53 -53
  101. data/web/locales/ta.yml +60 -60
  102. data/web/locales/tr.yml +101 -0
  103. data/web/locales/uk.yml +62 -61
  104. data/web/locales/ur.yml +80 -0
  105. data/web/locales/vi.yml +83 -0
  106. data/web/locales/zh-cn.yml +43 -16
  107. data/web/locales/zh-tw.yml +42 -8
  108. data/web/views/_footer.erb +21 -3
  109. data/web/views/_job_info.erb +21 -4
  110. data/web/views/_metrics_period_select.erb +12 -0
  111. data/web/views/_nav.erb +5 -19
  112. data/web/views/_paging.erb +3 -1
  113. data/web/views/_poll_link.erb +3 -6
  114. data/web/views/_summary.erb +7 -7
  115. data/web/views/busy.erb +85 -31
  116. data/web/views/dashboard.erb +50 -20
  117. data/web/views/dead.erb +3 -3
  118. data/web/views/filtering.erb +7 -0
  119. data/web/views/layout.erb +17 -6
  120. data/web/views/metrics.erb +91 -0
  121. data/web/views/metrics_for_job.erb +59 -0
  122. data/web/views/morgue.erb +14 -15
  123. data/web/views/queue.erb +34 -24
  124. data/web/views/queues.erb +20 -4
  125. data/web/views/retries.erb +19 -16
  126. data/web/views/retry.erb +3 -3
  127. data/web/views/scheduled.erb +19 -17
  128. metadata +91 -198
  129. data/.github/contributing.md +0 -32
  130. data/.github/issue_template.md +0 -9
  131. data/.gitignore +0 -12
  132. data/.travis.yml +0 -18
  133. data/3.0-Upgrade.md +0 -70
  134. data/4.0-Upgrade.md +0 -53
  135. data/COMM-LICENSE +0 -95
  136. data/Ent-Changes.md +0 -173
  137. data/Gemfile +0 -29
  138. data/LICENSE +0 -9
  139. data/Pro-2.0-Upgrade.md +0 -138
  140. data/Pro-3.0-Upgrade.md +0 -44
  141. data/Pro-Changes.md +0 -628
  142. data/Rakefile +0 -12
  143. data/bin/sidekiqctl +0 -99
  144. data/code_of_conduct.md +0 -50
  145. data/lib/generators/sidekiq/templates/worker_spec.rb.erb +0 -6
  146. data/lib/generators/sidekiq/worker_generator.rb +0 -49
  147. data/lib/sidekiq/core_ext.rb +0 -119
  148. data/lib/sidekiq/exception_handler.rb +0 -31
  149. data/lib/sidekiq/extensions/action_mailer.rb +0 -57
  150. data/lib/sidekiq/extensions/active_record.rb +0 -40
  151. data/lib/sidekiq/extensions/class_methods.rb +0 -40
  152. data/lib/sidekiq/extensions/generic_proxy.rb +0 -25
  153. data/lib/sidekiq/logging.rb +0 -106
  154. data/lib/sidekiq/middleware/server/active_record.rb +0 -13
  155. data/lib/sidekiq/middleware/server/logging.rb +0 -31
  156. data/lib/sidekiq/middleware/server/retry_jobs.rb +0 -205
  157. data/lib/sidekiq/util.rb +0 -63
  158. data/lib/sidekiq/worker.rb +0 -121
data/LICENSE.txt ADDED
@@ -0,0 +1,9 @@
1
+ Copyright (c) Contributed Systems LLC
2
+
3
+ Sidekiq is an Open Source project licensed under the terms of
4
+ the LGPLv3 license. Please see <http://www.gnu.org/licenses/lgpl-3.0.html>
5
+ for license text.
6
+
7
+ Sidekiq Pro and Sidekiq Enterprise have a commercial-friendly license.
8
+ You can find the commercial license in COMM-LICENSE.txt.
9
+ Please see https://sidekiq.org for purchasing options.
data/README.md CHANGED
@@ -2,10 +2,7 @@ Sidekiq
2
2
  ==============
3
3
 
4
4
  [![Gem Version](https://badge.fury.io/rb/sidekiq.svg)](https://rubygems.org/gems/sidekiq)
5
- [![Code Climate](https://codeclimate.com/github/mperham/sidekiq.svg)](https://codeclimate.com/github/mperham/sidekiq)
6
- [![Build Status](https://travis-ci.org/mperham/sidekiq.svg)](https://travis-ci.org/mperham/sidekiq)
7
- [![Gitter Chat](https://badges.gitter.im/mperham/sidekiq.svg)](https://gitter.im/mperham/sidekiq)
8
-
5
+ ![Build](https://github.com/sidekiq/sidekiq/workflows/CI/badge.svg)
9
6
 
10
7
  Simple, efficient background processing for Ruby.
11
8
 
@@ -13,95 +10,97 @@ Sidekiq uses threads to handle many jobs at the same time in the
13
10
  same process. It does not require Rails but will integrate tightly with
14
11
  Rails to make background processing dead simple.
15
12
 
16
- Sidekiq is compatible with Resque. It uses the exact same
17
- message format as Resque so it can integrate into an existing Resque processing farm.
18
- You can have Sidekiq and Resque run side-by-side at the same time and
19
- use the Resque client to enqueue jobs in Redis to be processed by Sidekiq.
20
-
21
- Performance
22
- ---------------
23
-
24
- Version | Latency | Garbage created for 10,000 jobs | Time to process 100,000 jobs | Throughput
25
- -----------------|------|---------|---------|------------------------
26
- Sidekiq 4.0.0 | 10ms | 151 MB | 22 sec | **4500 jobs/sec**
27
- Sidekiq 3.5.1 | 22ms | 1257 MB | 125 sec | 800 jobs/sec
28
- Resque 1.25.2 | - | - | 420 sec | 240 jobs/sec
29
- DelayedJob 4.1.1 | - | - | 465 sec | 215 jobs/sec
30
-
31
13
 
32
14
  Requirements
33
15
  -----------------
34
16
 
35
- Sidekiq supports CRuby 2.0+ and JRuby 9k.
36
-
37
- All Rails releases >= 3.2 are officially supported.
38
-
39
- Redis 2.8 or greater is required. 3.0.3+ is recommended for large
40
- installations with thousands of worker threads.
17
+ - Redis: Redis 6.2+ or Dragonfly 1.13+
18
+ - Ruby: MRI 2.7+ or JRuby 9.3+.
41
19
 
20
+ Sidekiq 7.0 supports Rails 6.0+ but does not require it.
21
+ As of 7.2, Sidekiq supports Dragonfly as an alternative to Redis for data storage.
42
22
 
43
23
  Installation
44
24
  -----------------
45
25
 
46
- gem install sidekiq
26
+ bundle add sidekiq
47
27
 
48
28
 
49
29
  Getting Started
50
30
  -----------------
51
31
 
52
- See the [Getting Started wiki page](https://github.com/mperham/sidekiq/wiki/Getting-Started) and follow the simple setup process.
53
- You can watch [this Youtube playlist](https://www.youtube.com/playlist?list=PLjeHh2LSCFrWGT5uVjUuFKAcrcj5kSai1) to learn all about
32
+ See the [Getting Started wiki page](https://github.com/sidekiq/sidekiq/wiki/Getting-Started) and follow the simple setup process.
33
+ You can watch [this YouTube playlist](https://www.youtube.com/playlist?list=PLjeHh2LSCFrWGT5uVjUuFKAcrcj5kSai1) to learn all about
54
34
  Sidekiq and see its features in action. Here's the Web UI:
55
35
 
56
- ![Web UI](https://github.com/mperham/sidekiq/raw/master/examples/web-ui.png)
36
+ ![Web UI](https://github.com/sidekiq/sidekiq/raw/main/examples/web-ui.png)
57
37
 
38
+ Performance
39
+ ---------------
40
+
41
+ The benchmark in `bin/sidekiqload` creates 500,000 no-op jobs and drains them as fast as possible, assuming a fixed Redis network latency of 1ms.
42
+ This requires a lot of Redis network I/O and JSON parsing.
43
+ This benchmark is IO-bound so we increase the concurrency to 25.
44
+ If your application is sending lots of emails or performing other network-intensive work, you could see a similar benefit but be careful not to saturate the CPU.
45
+
46
+ Version | Time to process 500k jobs | Throughput (jobs/sec) | Ruby | Concurrency | Job Type
47
+ -----------------|------|---------|---------|------------------------|---
48
+ Sidekiq 7.0.3 | 21.3 sec| 23,500 | 3.2.0+yjit | 30 | Sidekiq::Job
49
+ Sidekiq 7.0.3 | 33.8 sec| 14,700 | 3.2.0+yjit | 30 | ActiveJob 7.0.4
50
+ Sidekiq 7.0.3 | 23.5 sec| 21,300 | 3.2.0 | 30 | Sidekiq::Job
51
+ Sidekiq 7.0.3 | 46.5 sec| 10,700 | 3.2.0 | 30 | ActiveJob 7.0.4
52
+ Sidekiq 7.0.3 | 23.0 sec| 21,700 | 2.7.5 | 30 | Sidekiq::Job
53
+ Sidekiq 7.0.3 | 46.5 sec| 10,850 | 2.7.5 | 30 | ActiveJob 7.0.4
54
+
55
+ Most of Sidekiq's overhead is Redis network I/O.
56
+ ActiveJob adds a notable amount of CPU overhead due to argument deserialization and callbacks.
57
+ Concurrency of 30 was determined experimentally to maximize one CPU without saturating it.
58
58
 
59
59
  Want to Upgrade?
60
60
  -------------------
61
61
 
62
+ Use `bundle up sidekiq` to upgrade Sidekiq and all its dependencies.
63
+ Upgrade notes between each major version can be found in the `docs/` directory.
64
+
62
65
  I also sell Sidekiq Pro and Sidekiq Enterprise, extensions to Sidekiq which provide more
63
66
  features, a commercial-friendly license and allow you to support high
64
67
  quality open source development all at the same time. Please see the
65
- [Sidekiq](http://sidekiq.org/) homepage for more detail.
66
-
67
- Subscribe to the **[quarterly newsletter](https://tinyletter.com/sidekiq)** to stay informed about the latest
68
- features and changes to Sidekiq and its bigger siblings.
68
+ [Sidekiq](https://sidekiq.org/) homepage for more detail.
69
69
 
70
70
 
71
71
  Problems?
72
72
  -----------------
73
73
 
74
- **Please do not directly email any Sidekiq committers with questions or problems.** A community is best served when discussions are held in public.
74
+ **Please do not directly email any Sidekiq committers with questions or problems.**
75
+ A community is best served when discussions are held in public.
75
76
 
76
- If you have a problem, please review the [FAQ](https://github.com/mperham/sidekiq/wiki/FAQ) and [Troubleshooting](https://github.com/mperham/sidekiq/wiki/Problems-and-Troubleshooting) wiki pages.
77
- Searching the [issues](https://github.com/mperham/sidekiq/issues) for your problem is also a good idea.
77
+ If you have a problem, please review the [FAQ](https://github.com/sidekiq/sidekiq/wiki/FAQ) and [Troubleshooting](https://github.com/sidekiq/sidekiq/wiki/Problems-and-Troubleshooting) wiki pages.
78
+ Searching the [issues](https://github.com/sidekiq/sidekiq/issues) for your problem is also a good idea.
79
+
80
+ Sidekiq Pro and Sidekiq Enterprise customers get private email support.
81
+ You can purchase at https://sidekiq.org; email support@contribsys.com for help.
78
82
 
79
83
  Useful resources:
80
84
 
81
- * Product documentation is in the [wiki](https://github.com/mperham/sidekiq/wiki).
82
- * Release announcements are made to the [@sidekiq](https://twitter.com/sidekiq) Twitter account.
83
- * Here's a [Reddit forum](https://reddit.com/r/sidekiq) dedicated to Sidekiq discussion
85
+ * Product documentation is in the [wiki](https://github.com/sidekiq/sidekiq/wiki).
86
+ * Occasional announcements are made to the [@sidekiq](https://ruby.social/@sidekiq) Mastodon account.
84
87
  * The [Sidekiq tag](https://stackoverflow.com/questions/tagged/sidekiq) on Stack Overflow has lots of useful Q &amp; A.
85
88
 
86
- **No support via Twitter, 140 characters is not enough.**
87
-
88
- Every Friday morning is Sidekiq happy hour: I video chat and answer questions.
89
- See the [Sidekiq support page](http://sidekiq.org/support) for details.
89
+ Every Thursday morning is Sidekiq office hour: I video chat and answer questions.
90
+ See the [Sidekiq support page](https://sidekiq.org/support.html) for details.
90
91
 
91
- Thanks
92
+ Contributing
92
93
  -----------------
93
94
 
94
- Sidekiq stays fast by using the [JProfiler java profiler](http://www.ej-technologies.com/products/jprofiler/overview.html) to find and fix
95
- performance problems on JRuby. Unfortunately MRI does not have good multithreaded profiling tools.
96
-
95
+ Please see [the contributing guidelines](https://github.com/sidekiq/sidekiq/blob/main/.github/contributing.md).
97
96
 
98
97
  License
99
98
  -----------------
100
99
 
101
- Please see [LICENSE](https://github.com/mperham/sidekiq/blob/master/LICENSE) for licensing details.
102
-
100
+ Please see [LICENSE.txt](https://github.com/sidekiq/sidekiq/blob/main/LICENSE.txt) for licensing details.
101
+ The license for Sidekiq Pro and Sidekiq Enterprise can be found in [COMM-LICENSE.txt](https://github.com/sidekiq/sidekiq/blob/main/COMM-LICENSE.txt).
103
102
 
104
103
  Author
105
104
  -----------------
106
105
 
107
- Mike Perham, [@mperham](https://twitter.com/mperham) / [@sidekiq](https://twitter.com/sidekiq), [http://www.mikeperham.com](http://www.mikeperham.com) / [http://www.contribsys.com](http://www.contribsys.com)
106
+ Mike Perham, [@getajobmike](https://ruby.social/@getajobmike) / [@sidekiq](https://ruby.social/@sidekiq), [https://www.mikeperham.com](https://www.mikeperham.com) / [https://www.contribsys.com](https://www.contribsys.com)
@@ -0,0 +1,271 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #
4
+ # bin/bench is a helpful script to load test and
5
+ # performance tune Sidekiq's core. It's a configurable script,
6
+ # which accepts the following parameters as ENV variables.
7
+ #
8
+ # QUEUES
9
+ # Number of queues to consume from. Default is 8
10
+ #
11
+ # PROCESSES
12
+ # The number of processes this benchmark will create. Each process, consumes
13
+ # from one of the available queues. When processes are more than the number of
14
+ # queues, they are distributed to processes in round robin. Default is 8
15
+ #
16
+ # ELEMENTS
17
+ # Number of jobs to push to each queue. Default is 1000
18
+ #
19
+ # ITERATIONS
20
+ # Each queue pushes ITERATIONS times ELEMENTS jobs. Default is 1000
21
+ #
22
+ # PORT
23
+ # The port of the Dragonfly instance. Default is 6379
24
+ #
25
+ # IP
26
+ # The ip of the Dragonfly instance. Default is 127.0.0.1
27
+ #
28
+ # Example Usage:
29
+ #
30
+ # > RUBY_YJIT_ENABLE=1 THREADS=10 PROCESSES=8 QUEUES=8 bin/multi_queue_bench
31
+ #
32
+ # None of this script is considered a public API and may change over time.
33
+ #
34
+
35
+ # Quiet some warnings we see when running in warning mode:
36
+ # RUBYOPT=-w bundle exec sidekiq
37
+ $TESTING = false
38
+ puts RUBY_DESCRIPTION
39
+
40
+ require "bundler/setup"
41
+ Bundler.require(:default, :load_test)
42
+
43
+ class LoadWorker
44
+ include Sidekiq::Job
45
+ sidekiq_options retry: 1
46
+ sidekiq_retry_in do |x|
47
+ 1
48
+ end
49
+
50
+ def perform(idx, ts = nil)
51
+ puts(Time.now.to_f - ts) if !ts.nil?
52
+ # raise idx.to_s if idx % 100 == 1
53
+ end
54
+ end
55
+
56
+ def Process.rss
57
+ `ps -o rss= -p #{Process.pid}`.chomp.to_i
58
+ end
59
+
60
+ $iterations = ENV["ITERATIONS"] ? Integer(ENV["ITERATIONS"]) : 1_000
61
+ $elements = ENV["ELEMENTS"] ? Integer(ENV["ELEMENTS"]) : 1_000
62
+ $port = ENV["PORT"] ? Integer(ENV["PORT"]) : 6379
63
+ $ip = ENV["IP"] ? String(ENV["IP"]) : "127.0.0.1"
64
+
65
+ class Loader
66
+ def initialize
67
+ @iter = $iterations
68
+ @count = $elements
69
+ end
70
+
71
+ def configure(queue)
72
+ @x = Sidekiq.configure_embed do |config|
73
+ config.redis = {db: 0, host: $ip, port: $port}
74
+ config.concurrency = Integer(ENV.fetch("THREADS", "30"))
75
+ config.queues = queue
76
+ config.logger.level = Logger::WARN
77
+ config.average_scheduled_poll_interval = 2
78
+ config.reliable! if defined?(Sidekiq::Pro)
79
+ end
80
+
81
+ @self_read, @self_write = IO.pipe
82
+ %w[INT TERM TSTP TTIN].each do |sig|
83
+ trap sig do
84
+ @self_write.puts(sig)
85
+ end
86
+ rescue ArgumentError
87
+ puts "Signal #{sig} not supported"
88
+ end
89
+ end
90
+
91
+ def handle_signal(sig)
92
+ launcher = @x
93
+ Sidekiq.logger.debug "Got #{sig} signal"
94
+ case sig
95
+ when "INT"
96
+ # Handle Ctrl-C in JRuby like MRI
97
+ # http://jira.codehaus.org/browse/JRUBY-4637
98
+ raise Interrupt
99
+ when "TERM"
100
+ # Heroku sends TERM and then waits 30 seconds for process to exit.
101
+ raise Interrupt
102
+ when "TSTP"
103
+ Sidekiq.logger.info "Received TSTP, no longer accepting new work"
104
+ launcher.quiet
105
+ when "TTIN"
106
+ Thread.list.each do |thread|
107
+ Sidekiq.logger.warn "Thread TID-#{(thread.object_id ^ ::Process.pid).to_s(36)} #{thread["label"]}"
108
+ if thread.backtrace
109
+ Sidekiq.logger.warn thread.backtrace.join("\n")
110
+ else
111
+ Sidekiq.logger.warn "<no backtrace available>"
112
+ end
113
+ end
114
+ end
115
+ end
116
+
117
+ def setup(queue)
118
+ Sidekiq.logger.error("Setup RSS: #{Process.rss}")
119
+ Sidekiq.logger.error("Pushing work to queue: #{queue}")
120
+ start = Time.now
121
+ @iter.times do
122
+ arr = Array.new(@count) { |idx| [idx] }
123
+ # Sidekiq always prepends "queue:" to the queue name,
124
+ # that's why we pass 'q1', 'q2', etc instead of 'queue:q1'
125
+ Sidekiq::Client.push_bulk("class" => LoadWorker, "args" => arr, "queue" => queue)
126
+ $stdout.write "."
127
+ end
128
+ puts "Done"
129
+ end
130
+
131
+ def monitor_single(queue)
132
+ q = "queue:#{queue}"
133
+ @monitor_single = Thread.new do
134
+ GC.start
135
+ loop do
136
+ sleep 0.2
137
+ total = Sidekiq.redis do |conn|
138
+ conn.llen q
139
+ end
140
+
141
+ if total == 0
142
+ sleep 0.1
143
+ @x.stop
144
+ Process.kill("INT", $$)
145
+ break
146
+ end
147
+
148
+ end
149
+ end
150
+ end
151
+
152
+ def monitor_all(queues)
153
+ @monitor_all = Thread.new do
154
+ GC.start
155
+ loop do
156
+ sleep 0.2
157
+ qsize = 0
158
+ queues.each do |q|
159
+ tmp = Sidekiq.redis do |conn|
160
+ conn.llen q
161
+ end
162
+ qsize = qsize + tmp
163
+ end
164
+ total = qsize
165
+
166
+ if total == 0
167
+ ending = Time.now - @start
168
+ size = @iter * @count * queues.length()
169
+ Sidekiq.logger.error("Done, #{size} jobs in #{ending} sec, #{(size / ending).to_i} jobs/sec")
170
+ Sidekiq.logger.error("Ending RSS: #{Process.rss}")
171
+
172
+ sleep 0.1
173
+ @x.stop
174
+ Process.kill("INT", $$)
175
+ break
176
+ end
177
+ end
178
+ end
179
+ end
180
+
181
+ def run(queues, queue, monitor_all_queues)
182
+ Sidekiq.logger.warn("Consuming from #{queue}")
183
+ if monitor_all_queues
184
+ monitor_all(queues)
185
+ else
186
+ monitor_single(queue)
187
+ end
188
+
189
+ @start = Time.now
190
+ @x.run
191
+
192
+ while (readable_io = IO.select([@self_read]))
193
+ signal = readable_io.first[0].gets.strip
194
+ handle_signal(signal)
195
+ end
196
+ # normal
197
+ rescue Interrupt
198
+ rescue => e
199
+ raise e if $DEBUG
200
+ warn e.message
201
+ warn e.backtrace.join("\n")
202
+ exit 1
203
+ ensure
204
+ @x.stop
205
+ end
206
+ end
207
+
208
+ def setup(queue)
209
+ ll = Loader.new
210
+ ll.configure(queue)
211
+ ll.setup(queue)
212
+ end
213
+
214
+ def consume(queues, queue, monitor_all_queues)
215
+ ll = Loader.new
216
+ ll.configure(queue)
217
+ ll.run(queues, queue, monitor_all_queues)
218
+ end
219
+
220
+ # We assign one queue to each sidekiq process
221
+ def run(number_of_processes, total_queues)
222
+ read_stream, write_stream = IO.pipe
223
+
224
+ queues = []
225
+ (0..total_queues-1).each do |idx|
226
+ queues.push("queue:q#{idx}")
227
+ end
228
+
229
+ Sidekiq.logger.info("Queues are: #{queues}")
230
+
231
+ # Produce
232
+ start = Time.now
233
+ (0..total_queues-1).each do |idx|
234
+ Process.fork do
235
+ queue_num = "q#{idx}"
236
+ setup(queue_num)
237
+ end
238
+ end
239
+
240
+ queue_sz = $iterations * $elements * total_queues
241
+ Process.waitall
242
+
243
+ ending = Time.now - start
244
+ #Sidekiq.logger.info("Pushed #{queue_sz} in #{ending} secs")
245
+
246
+ # Consume
247
+ (0..number_of_processes-1).each do |idx|
248
+ Process.fork do
249
+ # First process only consumes from it's own queue but monitors all queues.
250
+ # It works as a synchronization point. Once all processes finish
251
+ # (that is, when all queues are emptied) it prints the the stats.
252
+ if idx == 0
253
+ queue = "q#{idx}"
254
+ consume(queues, queue, true)
255
+ else
256
+ queue = "q#{idx % total_queues}"
257
+ consume(queues, queue, false)
258
+ end
259
+ end
260
+ end
261
+
262
+ Process.waitall
263
+ write_stream.close
264
+ results = read_stream.read
265
+ read_stream.close
266
+ end
267
+
268
+ $total_processes = ENV["PROCESSES"] ? Integer(ENV["PROCESSES"]) : 8;
269
+ $total_queues = ENV["QUEUES"] ? Integer(ENV["QUEUES"]) : 8;
270
+
271
+ run($total_processes, $total_queues)
data/bin/sidekiq CHANGED
@@ -4,15 +4,34 @@
4
4
  # RUBYOPT=-w bundle exec sidekiq
5
5
  $TESTING = false
6
6
 
7
- require_relative '../lib/sidekiq/cli'
7
+ require_relative "../lib/sidekiq/cli"
8
+
9
+ def integrate_with_systemd
10
+ return unless ENV["NOTIFY_SOCKET"]
11
+
12
+ Sidekiq.configure_server do |config|
13
+ config.logger.info "Enabling systemd notification integration"
14
+ require "sidekiq/sd_notify"
15
+ config.on(:startup) do
16
+ Sidekiq::SdNotify.ready
17
+ end
18
+ config.on(:shutdown) do
19
+ Sidekiq::SdNotify.stopping
20
+ end
21
+ Sidekiq.start_watchdog if Sidekiq::SdNotify.watchdog?
22
+ end
23
+ end
8
24
 
9
25
  begin
10
26
  cli = Sidekiq::CLI.instance
11
27
  cli.parse
28
+
29
+ integrate_with_systemd
30
+
12
31
  cli.run
13
32
  rescue => e
14
33
  raise e if $DEBUG
15
- STDERR.puts e.message
16
- STDERR.puts e.backtrace.join("\n")
34
+ warn e.message
35
+ warn e.backtrace.join("\n")
17
36
  exit 1
18
37
  end