sidekiq 5.2.7 → 8.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. checksums.yaml +4 -4
  2. data/Changes.md +845 -8
  3. data/LICENSE.txt +9 -0
  4. data/README.md +54 -54
  5. data/bin/multi_queue_bench +271 -0
  6. data/bin/sidekiq +22 -3
  7. data/bin/sidekiqload +219 -112
  8. data/bin/sidekiqmon +11 -0
  9. data/bin/webload +69 -0
  10. data/lib/active_job/queue_adapters/sidekiq_adapter.rb +120 -0
  11. data/lib/generators/sidekiq/job_generator.rb +59 -0
  12. data/lib/generators/sidekiq/templates/{worker.rb.erb → job.rb.erb} +2 -2
  13. data/lib/generators/sidekiq/templates/{worker_spec.rb.erb → job_spec.rb.erb} +1 -1
  14. data/lib/generators/sidekiq/templates/{worker_test.rb.erb → job_test.rb.erb} +1 -1
  15. data/lib/sidekiq/api.rb +757 -373
  16. data/lib/sidekiq/capsule.rb +132 -0
  17. data/lib/sidekiq/cli.rb +210 -233
  18. data/lib/sidekiq/client.rb +145 -103
  19. data/lib/sidekiq/component.rb +128 -0
  20. data/lib/sidekiq/config.rb +315 -0
  21. data/lib/sidekiq/deploy.rb +64 -0
  22. data/lib/sidekiq/embedded.rb +64 -0
  23. data/lib/sidekiq/fetch.rb +49 -42
  24. data/lib/sidekiq/iterable_job.rb +56 -0
  25. data/lib/sidekiq/job/interrupt_handler.rb +24 -0
  26. data/lib/sidekiq/job/iterable/active_record_enumerator.rb +53 -0
  27. data/lib/sidekiq/job/iterable/csv_enumerator.rb +47 -0
  28. data/lib/sidekiq/job/iterable/enumerators.rb +135 -0
  29. data/lib/sidekiq/job/iterable.rb +306 -0
  30. data/lib/sidekiq/job.rb +385 -0
  31. data/lib/sidekiq/job_logger.rb +34 -7
  32. data/lib/sidekiq/job_retry.rb +164 -109
  33. data/lib/sidekiq/job_util.rb +113 -0
  34. data/lib/sidekiq/launcher.rb +208 -107
  35. data/lib/sidekiq/logger.rb +80 -0
  36. data/lib/sidekiq/manager.rb +42 -46
  37. data/lib/sidekiq/metrics/query.rb +184 -0
  38. data/lib/sidekiq/metrics/shared.rb +109 -0
  39. data/lib/sidekiq/metrics/tracking.rb +150 -0
  40. data/lib/sidekiq/middleware/chain.rb +113 -56
  41. data/lib/sidekiq/middleware/current_attributes.rb +119 -0
  42. data/lib/sidekiq/middleware/i18n.rb +7 -7
  43. data/lib/sidekiq/middleware/modules.rb +23 -0
  44. data/lib/sidekiq/monitor.rb +147 -0
  45. data/lib/sidekiq/paginator.rb +41 -16
  46. data/lib/sidekiq/processor.rb +146 -127
  47. data/lib/sidekiq/profiler.rb +72 -0
  48. data/lib/sidekiq/rails.rb +46 -43
  49. data/lib/sidekiq/redis_client_adapter.rb +113 -0
  50. data/lib/sidekiq/redis_connection.rb +79 -108
  51. data/lib/sidekiq/ring_buffer.rb +31 -0
  52. data/lib/sidekiq/scheduled.rb +112 -50
  53. data/lib/sidekiq/sd_notify.rb +149 -0
  54. data/lib/sidekiq/systemd.rb +26 -0
  55. data/lib/sidekiq/testing/inline.rb +6 -5
  56. data/lib/sidekiq/testing.rb +91 -90
  57. data/lib/sidekiq/transaction_aware_client.rb +51 -0
  58. data/lib/sidekiq/version.rb +7 -1
  59. data/lib/sidekiq/web/action.rb +125 -60
  60. data/lib/sidekiq/web/application.rb +363 -259
  61. data/lib/sidekiq/web/config.rb +120 -0
  62. data/lib/sidekiq/web/csrf_protection.rb +183 -0
  63. data/lib/sidekiq/web/helpers.rb +241 -120
  64. data/lib/sidekiq/web/router.rb +62 -71
  65. data/lib/sidekiq/web.rb +69 -161
  66. data/lib/sidekiq/worker_compatibility_alias.rb +13 -0
  67. data/lib/sidekiq.rb +94 -182
  68. data/sidekiq.gemspec +26 -16
  69. data/web/assets/images/apple-touch-icon.png +0 -0
  70. data/web/assets/javascripts/application.js +150 -61
  71. data/web/assets/javascripts/base-charts.js +120 -0
  72. data/web/assets/javascripts/chart.min.js +13 -0
  73. data/web/assets/javascripts/chartjs-adapter-date-fns.min.js +7 -0
  74. data/web/assets/javascripts/chartjs-plugin-annotation.min.js +7 -0
  75. data/web/assets/javascripts/dashboard-charts.js +194 -0
  76. data/web/assets/javascripts/dashboard.js +41 -293
  77. data/web/assets/javascripts/metrics.js +280 -0
  78. data/web/assets/stylesheets/style.css +766 -0
  79. data/web/locales/ar.yml +72 -65
  80. data/web/locales/cs.yml +63 -62
  81. data/web/locales/da.yml +61 -53
  82. data/web/locales/de.yml +66 -53
  83. data/web/locales/el.yml +44 -24
  84. data/web/locales/en.yml +94 -66
  85. data/web/locales/es.yml +92 -54
  86. data/web/locales/fa.yml +66 -65
  87. data/web/locales/fr.yml +83 -62
  88. data/web/locales/gd.yml +99 -0
  89. data/web/locales/he.yml +66 -64
  90. data/web/locales/hi.yml +60 -59
  91. data/web/locales/it.yml +93 -54
  92. data/web/locales/ja.yml +75 -64
  93. data/web/locales/ko.yml +53 -52
  94. data/web/locales/lt.yml +84 -0
  95. data/web/locales/nb.yml +62 -61
  96. data/web/locales/nl.yml +53 -52
  97. data/web/locales/pl.yml +46 -45
  98. data/web/locales/{pt-br.yml → pt-BR.yml} +84 -56
  99. data/web/locales/pt.yml +52 -51
  100. data/web/locales/ru.yml +69 -63
  101. data/web/locales/sv.yml +54 -53
  102. data/web/locales/ta.yml +61 -60
  103. data/web/locales/tr.yml +101 -0
  104. data/web/locales/uk.yml +86 -61
  105. data/web/locales/ur.yml +65 -64
  106. data/web/locales/vi.yml +84 -0
  107. data/web/locales/zh-CN.yml +106 -0
  108. data/web/locales/{zh-tw.yml → zh-TW.yml} +43 -9
  109. data/web/views/_footer.erb +31 -19
  110. data/web/views/_job_info.erb +94 -75
  111. data/web/views/_metrics_period_select.erb +15 -0
  112. data/web/views/_nav.erb +14 -21
  113. data/web/views/_paging.erb +23 -19
  114. data/web/views/_poll_link.erb +3 -6
  115. data/web/views/_summary.erb +23 -23
  116. data/web/views/busy.erb +139 -87
  117. data/web/views/dashboard.erb +82 -53
  118. data/web/views/dead.erb +31 -27
  119. data/web/views/filtering.erb +6 -0
  120. data/web/views/layout.erb +15 -29
  121. data/web/views/metrics.erb +84 -0
  122. data/web/views/metrics_for_job.erb +58 -0
  123. data/web/views/morgue.erb +60 -70
  124. data/web/views/profiles.erb +43 -0
  125. data/web/views/queue.erb +50 -39
  126. data/web/views/queues.erb +45 -29
  127. data/web/views/retries.erb +65 -75
  128. data/web/views/retry.erb +32 -27
  129. data/web/views/scheduled.erb +58 -52
  130. data/web/views/scheduled_job_info.erb +1 -1
  131. metadata +96 -76
  132. data/.circleci/config.yml +0 -61
  133. data/.github/contributing.md +0 -32
  134. data/.github/issue_template.md +0 -11
  135. data/.gitignore +0 -15
  136. data/.travis.yml +0 -11
  137. data/3.0-Upgrade.md +0 -70
  138. data/4.0-Upgrade.md +0 -53
  139. data/5.0-Upgrade.md +0 -56
  140. data/COMM-LICENSE +0 -97
  141. data/Ent-Changes.md +0 -238
  142. data/Gemfile +0 -23
  143. data/LICENSE +0 -9
  144. data/Pro-2.0-Upgrade.md +0 -138
  145. data/Pro-3.0-Upgrade.md +0 -44
  146. data/Pro-4.0-Upgrade.md +0 -35
  147. data/Pro-Changes.md +0 -759
  148. data/Rakefile +0 -9
  149. data/bin/sidekiqctl +0 -20
  150. data/code_of_conduct.md +0 -50
  151. data/lib/generators/sidekiq/worker_generator.rb +0 -49
  152. data/lib/sidekiq/core_ext.rb +0 -1
  153. data/lib/sidekiq/ctl.rb +0 -221
  154. data/lib/sidekiq/delay.rb +0 -42
  155. data/lib/sidekiq/exception_handler.rb +0 -29
  156. data/lib/sidekiq/extensions/action_mailer.rb +0 -57
  157. data/lib/sidekiq/extensions/active_record.rb +0 -40
  158. data/lib/sidekiq/extensions/class_methods.rb +0 -40
  159. data/lib/sidekiq/extensions/generic_proxy.rb +0 -31
  160. data/lib/sidekiq/logging.rb +0 -122
  161. data/lib/sidekiq/middleware/server/active_record.rb +0 -23
  162. data/lib/sidekiq/util.rb +0 -66
  163. data/lib/sidekiq/worker.rb +0 -220
  164. data/web/assets/stylesheets/application-rtl.css +0 -246
  165. data/web/assets/stylesheets/application.css +0 -1144
  166. data/web/assets/stylesheets/bootstrap-rtl.min.css +0 -9
  167. data/web/assets/stylesheets/bootstrap.css +0 -5
  168. data/web/locales/zh-cn.yml +0 -68
  169. data/web/views/_status.erb +0 -4
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,108 +2,108 @@ 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://circleci.com/gh/mperham/sidekiq/tree/master.svg?style=svg)](https://circleci.com/gh/mperham/sidekiq/tree/master)
7
- [![Gitter Chat](https://badges.gitter.im/mperham/sidekiq.svg)](https://gitter.im/mperham/sidekiq)
5
+ ![Build](https://github.com/sidekiq/sidekiq/workflows/CI/badge.svg)
8
6
 
9
-
10
- Simple, efficient background processing for Ruby.
7
+ Simple, efficient background jobs for Ruby.
11
8
 
12
9
  Sidekiq uses threads to handle many jobs at the same time in the
13
- same process. It does not require Rails but will integrate tightly with
14
- Rails to make background processing dead simple.
15
-
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
10
+ same process. Sidekiq can be used by any Ruby application.
30
11
 
31
- <small>This benchmark can be found in `bin/sidekiqload`.</small>
32
12
 
33
13
  Requirements
34
14
  -----------------
35
15
 
36
- Sidekiq supports CRuby 2.2.2+ and JRuby 9k.
16
+ - Redis: Redis 7.0+, Valkey 7.2+ or Dragonfly 1.27+
17
+ - Ruby: MRI 3.2+ or JRuby 9.4+.
37
18
 
38
- All Rails releases >= 4.0 are officially supported.
39
-
40
- Redis 2.8 or greater is required. 3.0.3+ is recommended for large
41
- installations with thousands of worker threads.
19
+ Sidekiq 8.0 supports Rails and Active Job 7.0+.
42
20
 
21
+ Sidekiq supports [Valkey](https://valkey.io) and [Dragonfly](https://www.dragonflydb.io) as Redis alternatives.
22
+ Redis 7.2.4 is considered to be the canonical implementation.
23
+ Incompatibilities with that version are considered bugs.
43
24
 
44
25
  Installation
45
26
  -----------------
46
27
 
47
- gem install sidekiq
28
+ bundle add sidekiq
48
29
 
49
30
 
50
31
  Getting Started
51
32
  -----------------
52
33
 
53
- See the [Getting Started wiki page](https://github.com/mperham/sidekiq/wiki/Getting-Started) and follow the simple setup process.
54
- You can watch [this Youtube playlist](https://www.youtube.com/playlist?list=PLjeHh2LSCFrWGT5uVjUuFKAcrcj5kSai1) to learn all about
34
+ See the [Getting Started wiki page](https://github.com/sidekiq/sidekiq/wiki/Getting-Started) and follow the simple setup process.
35
+ You can watch [this YouTube playlist](https://www.youtube.com/playlist?list=PLjeHh2LSCFrWGT5uVjUuFKAcrcj5kSai1) to learn all about
55
36
  Sidekiq and see its features in action. Here's the Web UI:
56
37
 
57
- ![Web UI](https://github.com/mperham/sidekiq/raw/master/examples/web-ui.png)
38
+ ![Web UI](https://github.com/sidekiq/sidekiq/raw/main/examples/web-ui.png)
58
39
 
40
+ Performance
41
+ ---------------
42
+
43
+ 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.
44
+ This requires a lot of Redis network I/O and JSON parsing.
45
+ This benchmark is IO-bound so we increase the concurrency to 25.
46
+ 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.
47
+ Real world applications will rarely if ever need to use concurrency greater than 10.
48
+
49
+ Version | Time to process 500k jobs | Throughput (jobs/sec) | Ruby | Concurrency | Job Type
50
+ -----------------|------|---------|---------|------------------------|---
51
+ Sidekiq 7.0.3 | 21.3 sec| 23,500 | 3.2.0+yjit | 30 | Sidekiq::Job
52
+ Sidekiq 7.0.3 | 33.8 sec| 14,700 | 3.2.0+yjit | 30 | ActiveJob 7.0.4
53
+ Sidekiq 7.0.3 | 23.5 sec| 21,300 | 3.2.0 | 30 | Sidekiq::Job
54
+ Sidekiq 7.0.3 | 46.5 sec| 10,700 | 3.2.0 | 30 | ActiveJob 7.0.4
55
+ Sidekiq 7.0.3 | 23.0 sec| 21,700 | 2.7.5 | 30 | Sidekiq::Job
56
+ Sidekiq 7.0.3 | 46.5 sec| 10,850 | 2.7.5 | 30 | ActiveJob 7.0.4
57
+
58
+ Most of Sidekiq's overhead is Redis network I/O.
59
+ ActiveJob adds a notable amount of CPU overhead due to argument deserialization and callbacks.
60
+ Concurrency of 30 was determined experimentally to maximize one CPU without saturating it.
59
61
 
60
62
  Want to Upgrade?
61
63
  -------------------
62
64
 
63
- I also sell Sidekiq Pro and Sidekiq Enterprise, extensions to Sidekiq which provide more
65
+ Use `bundle up sidekiq` to upgrade Sidekiq and all its dependencies.
66
+ Upgrade notes between each major version can be found in the `docs/` directory.
67
+
68
+ I also sell [Sidekiq Pro](https://billing.contribsys.com/spro/) and [Sidekiq Enterprise](https://billing.contribsys.com/sent/new.cgi), extensions to Sidekiq which provide more
64
69
  features, a commercial-friendly license and allow you to support high
65
70
  quality open source development all at the same time. Please see the
66
- [Sidekiq](http://sidekiq.org/) homepage for more detail.
67
-
68
- Subscribe to the **[quarterly newsletter](https://tinyletter.com/sidekiq)** to stay informed about the latest
69
- features and changes to Sidekiq and its bigger siblings.
71
+ [Sidekiq](https://sidekiq.org/) homepage for more detail.
70
72
 
71
73
 
72
74
  Problems?
73
75
  -----------------
74
76
 
75
- **Please do not directly email any Sidekiq committers with questions or problems.** A community is best served when discussions are held in public.
77
+ **Do not directly email any Sidekiq committers with questions or problems.**
78
+ A community is best served when discussions are held in public.
76
79
 
77
- 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.
78
- Searching the [issues](https://github.com/mperham/sidekiq/issues) for your problem is also a good idea.
80
+ 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.
81
+ Searching the [issues](https://github.com/sidekiq/sidekiq/issues) for your problem is also a good idea.
79
82
 
80
- Sidekiq Pro and Sidekiq Enterprise customers get private email support. You can purchase at http://sidekiq.org; email support@contribsys.com for help.
83
+ Sidekiq Pro and Sidekiq Enterprise customers get private email support.
84
+ You can purchase at https://sidekiq.org; email support@contribsys.com for help.
81
85
 
82
86
  Useful resources:
83
87
 
84
- * Product documentation is in the [wiki](https://github.com/mperham/sidekiq/wiki).
85
- * Release announcements are made to the [@sidekiq](https://twitter.com/sidekiq) Twitter account.
88
+ * Product documentation is in the [wiki](https://github.com/sidekiq/sidekiq/wiki).
89
+ * Occasional announcements are made to the [@sidekiq](https://ruby.social/@sidekiq) Mastodon account.
86
90
  * The [Sidekiq tag](https://stackoverflow.com/questions/tagged/sidekiq) on Stack Overflow has lots of useful Q &amp; A.
87
91
 
88
- **No support via Twitter**
92
+ Every Thursday morning is Sidekiq Office Hour: I video chat and answer questions.
93
+ See the [Sidekiq support page](https://sidekiq.org/support.html) for details.
89
94
 
90
- Every Friday morning is Sidekiq happy hour: I video chat and answer questions.
91
- See the [Sidekiq support page](http://sidekiq.org/support.html) for details.
92
-
93
- Thanks
95
+ Contributing
94
96
  -----------------
95
97
 
96
- Sidekiq stays fast by using the [JProfiler java profiler](http://www.ej-technologies.com/products/jprofiler/overview.html) to find and fix
97
- performance problems on JRuby. Unfortunately MRI does not have good multithreaded profiling tools.
98
-
98
+ See [the contributing guidelines](https://github.com/sidekiq/sidekiq/blob/main/.github/contributing.md).
99
99
 
100
100
  License
101
101
  -----------------
102
102
 
103
- Please see [LICENSE](https://github.com/mperham/sidekiq/blob/master/LICENSE) for licensing details.
104
-
103
+ See [LICENSE.txt](https://github.com/sidekiq/sidekiq/blob/main/LICENSE.txt) for licensing details.
104
+ 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).
105
105
 
106
106
  Author
107
107
  -----------------
108
108
 
109
- 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)
109
+ Mike Perham, [mastodon](https://ruby.social/@getajobmike), [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