sidekiq 6.2.2 → 8.1.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 (181) hide show
  1. checksums.yaml +4 -4
  2. data/Changes.md +726 -11
  3. data/LICENSE.txt +9 -0
  4. data/README.md +70 -39
  5. data/bin/kiq +17 -0
  6. data/bin/lint-herb +13 -0
  7. data/bin/multi_queue_bench +271 -0
  8. data/bin/sidekiq +4 -9
  9. data/bin/sidekiqload +214 -115
  10. data/bin/sidekiqmon +4 -1
  11. data/bin/webload +69 -0
  12. data/lib/active_job/queue_adapters/sidekiq_adapter.rb +124 -0
  13. data/lib/generators/sidekiq/job_generator.rb +71 -0
  14. data/lib/generators/sidekiq/templates/{worker.rb.erb → job.rb.erb} +3 -3
  15. data/lib/generators/sidekiq/templates/{worker_spec.rb.erb → job_spec.rb.erb} +1 -1
  16. data/lib/generators/sidekiq/templates/{worker_test.rb.erb → job_test.rb.erb} +1 -1
  17. data/lib/sidekiq/api.rb +729 -264
  18. data/lib/sidekiq/capsule.rb +135 -0
  19. data/lib/sidekiq/cli.rb +124 -100
  20. data/lib/sidekiq/client.rb +153 -106
  21. data/lib/sidekiq/component.rb +132 -0
  22. data/lib/sidekiq/config.rb +320 -0
  23. data/lib/sidekiq/deploy.rb +64 -0
  24. data/lib/sidekiq/embedded.rb +64 -0
  25. data/lib/sidekiq/fetch.rb +27 -26
  26. data/lib/sidekiq/iterable_job.rb +56 -0
  27. data/lib/sidekiq/job/interrupt_handler.rb +24 -0
  28. data/lib/sidekiq/job/iterable/active_record_enumerator.rb +53 -0
  29. data/lib/sidekiq/job/iterable/csv_enumerator.rb +47 -0
  30. data/lib/sidekiq/job/iterable/enumerators.rb +135 -0
  31. data/lib/sidekiq/job/iterable.rb +322 -0
  32. data/lib/sidekiq/job.rb +397 -5
  33. data/lib/sidekiq/job_logger.rb +23 -32
  34. data/lib/sidekiq/job_retry.rb +141 -68
  35. data/lib/sidekiq/job_util.rb +113 -0
  36. data/lib/sidekiq/launcher.rb +122 -98
  37. data/lib/sidekiq/loader.rb +57 -0
  38. data/lib/sidekiq/logger.rb +27 -106
  39. data/lib/sidekiq/manager.rb +41 -43
  40. data/lib/sidekiq/metrics/query.rb +184 -0
  41. data/lib/sidekiq/metrics/shared.rb +109 -0
  42. data/lib/sidekiq/metrics/tracking.rb +153 -0
  43. data/lib/sidekiq/middleware/chain.rb +96 -51
  44. data/lib/sidekiq/middleware/current_attributes.rb +120 -0
  45. data/lib/sidekiq/middleware/i18n.rb +8 -4
  46. data/lib/sidekiq/middleware/modules.rb +23 -0
  47. data/lib/sidekiq/monitor.rb +16 -6
  48. data/lib/sidekiq/paginator.rb +37 -10
  49. data/lib/sidekiq/processor.rb +105 -87
  50. data/lib/sidekiq/profiler.rb +73 -0
  51. data/lib/sidekiq/rails.rb +49 -36
  52. data/lib/sidekiq/redis_client_adapter.rb +117 -0
  53. data/lib/sidekiq/redis_connection.rb +55 -86
  54. data/lib/sidekiq/ring_buffer.rb +32 -0
  55. data/lib/sidekiq/scheduled.rb +106 -50
  56. data/lib/sidekiq/systemd.rb +2 -0
  57. data/lib/sidekiq/test_api.rb +331 -0
  58. data/lib/sidekiq/testing/inline.rb +2 -30
  59. data/lib/sidekiq/testing.rb +2 -342
  60. data/lib/sidekiq/transaction_aware_client.rb +59 -0
  61. data/lib/sidekiq/tui/controls.rb +53 -0
  62. data/lib/sidekiq/tui/filtering.rb +53 -0
  63. data/lib/sidekiq/tui/tabs/base_tab.rb +204 -0
  64. data/lib/sidekiq/tui/tabs/busy.rb +118 -0
  65. data/lib/sidekiq/tui/tabs/dead.rb +19 -0
  66. data/lib/sidekiq/tui/tabs/home.rb +144 -0
  67. data/lib/sidekiq/tui/tabs/metrics.rb +131 -0
  68. data/lib/sidekiq/tui/tabs/queues.rb +95 -0
  69. data/lib/sidekiq/tui/tabs/retries.rb +19 -0
  70. data/lib/sidekiq/tui/tabs/scheduled.rb +19 -0
  71. data/lib/sidekiq/tui/tabs/set_tab.rb +96 -0
  72. data/lib/sidekiq/tui/tabs.rb +15 -0
  73. data/lib/sidekiq/tui.rb +382 -0
  74. data/lib/sidekiq/version.rb +6 -1
  75. data/lib/sidekiq/web/action.rb +149 -64
  76. data/lib/sidekiq/web/application.rb +376 -268
  77. data/lib/sidekiq/web/config.rb +117 -0
  78. data/lib/sidekiq/web/helpers.rb +213 -87
  79. data/lib/sidekiq/web/router.rb +61 -74
  80. data/lib/sidekiq/web.rb +71 -100
  81. data/lib/sidekiq/worker_compatibility_alias.rb +13 -0
  82. data/lib/sidekiq.rb +95 -196
  83. data/sidekiq.gemspec +14 -11
  84. data/web/assets/images/logo.png +0 -0
  85. data/web/assets/images/status.png +0 -0
  86. data/web/assets/javascripts/application.js +171 -57
  87. data/web/assets/javascripts/base-charts.js +120 -0
  88. data/web/assets/javascripts/chart.min.js +13 -0
  89. data/web/assets/javascripts/chartjs-adapter-date-fns.min.js +7 -0
  90. data/web/assets/javascripts/chartjs-plugin-annotation.min.js +7 -0
  91. data/web/assets/javascripts/dashboard-charts.js +194 -0
  92. data/web/assets/javascripts/dashboard.js +41 -274
  93. data/web/assets/javascripts/metrics.js +280 -0
  94. data/web/assets/stylesheets/style.css +776 -0
  95. data/web/locales/ar.yml +72 -70
  96. data/web/locales/cs.yml +64 -62
  97. data/web/locales/da.yml +62 -53
  98. data/web/locales/de.yml +67 -65
  99. data/web/locales/el.yml +45 -24
  100. data/web/locales/en.yml +93 -69
  101. data/web/locales/es.yml +91 -68
  102. data/web/locales/fa.yml +67 -65
  103. data/web/locales/fr.yml +82 -67
  104. data/web/locales/gd.yml +110 -0
  105. data/web/locales/he.yml +67 -64
  106. data/web/locales/hi.yml +61 -59
  107. data/web/locales/it.yml +94 -54
  108. data/web/locales/ja.yml +74 -68
  109. data/web/locales/ko.yml +54 -52
  110. data/web/locales/lt.yml +68 -66
  111. data/web/locales/nb.yml +63 -61
  112. data/web/locales/nl.yml +54 -52
  113. data/web/locales/pl.yml +47 -45
  114. data/web/locales/{pt-br.yml → pt-BR.yml} +85 -56
  115. data/web/locales/pt.yml +53 -51
  116. data/web/locales/ru.yml +69 -66
  117. data/web/locales/sv.yml +55 -53
  118. data/web/locales/ta.yml +62 -60
  119. data/web/locales/tr.yml +102 -0
  120. data/web/locales/uk.yml +87 -61
  121. data/web/locales/ur.yml +66 -64
  122. data/web/locales/vi.yml +69 -67
  123. data/web/locales/zh-CN.yml +107 -0
  124. data/web/locales/{zh-tw.yml → zh-TW.yml} +44 -9
  125. data/web/views/_footer.html.erb +32 -0
  126. data/web/views/_job_info.html.erb +115 -0
  127. data/web/views/_metrics_period_select.html.erb +15 -0
  128. data/web/views/_nav.html.erb +45 -0
  129. data/web/views/_paging.html.erb +26 -0
  130. data/web/views/_poll_link.html.erb +4 -0
  131. data/web/views/_summary.html.erb +40 -0
  132. data/web/views/busy.html.erb +151 -0
  133. data/web/views/dashboard.html.erb +104 -0
  134. data/web/views/dead.html.erb +38 -0
  135. data/web/views/filtering.html.erb +6 -0
  136. data/web/views/layout.html.erb +26 -0
  137. data/web/views/metrics.html.erb +85 -0
  138. data/web/views/metrics_for_job.html.erb +58 -0
  139. data/web/views/morgue.html.erb +69 -0
  140. data/web/views/profiles.html.erb +43 -0
  141. data/web/views/queue.html.erb +57 -0
  142. data/web/views/queues.html.erb +46 -0
  143. data/web/views/retries.html.erb +77 -0
  144. data/web/views/retry.html.erb +39 -0
  145. data/web/views/scheduled.html.erb +64 -0
  146. data/web/views/{scheduled_job_info.erb → scheduled_job_info.html.erb} +3 -3
  147. metadata +130 -61
  148. data/LICENSE +0 -9
  149. data/lib/generators/sidekiq/worker_generator.rb +0 -57
  150. data/lib/sidekiq/delay.rb +0 -41
  151. data/lib/sidekiq/exception_handler.rb +0 -27
  152. data/lib/sidekiq/extensions/action_mailer.rb +0 -48
  153. data/lib/sidekiq/extensions/active_record.rb +0 -43
  154. data/lib/sidekiq/extensions/class_methods.rb +0 -43
  155. data/lib/sidekiq/extensions/generic_proxy.rb +0 -33
  156. data/lib/sidekiq/util.rb +0 -95
  157. data/lib/sidekiq/web/csrf_protection.rb +0 -180
  158. data/lib/sidekiq/worker.rb +0 -244
  159. data/web/assets/stylesheets/application-dark.css +0 -147
  160. data/web/assets/stylesheets/application-rtl.css +0 -246
  161. data/web/assets/stylesheets/application.css +0 -1053
  162. data/web/assets/stylesheets/bootstrap-rtl.min.css +0 -9
  163. data/web/assets/stylesheets/bootstrap.css +0 -5
  164. data/web/locales/zh-cn.yml +0 -68
  165. data/web/views/_footer.erb +0 -20
  166. data/web/views/_job_info.erb +0 -89
  167. data/web/views/_nav.erb +0 -52
  168. data/web/views/_paging.erb +0 -23
  169. data/web/views/_poll_link.erb +0 -7
  170. data/web/views/_status.erb +0 -4
  171. data/web/views/_summary.erb +0 -40
  172. data/web/views/busy.erb +0 -132
  173. data/web/views/dashboard.erb +0 -83
  174. data/web/views/dead.erb +0 -34
  175. data/web/views/layout.erb +0 -42
  176. data/web/views/morgue.erb +0 -78
  177. data/web/views/queue.erb +0 -55
  178. data/web/views/queues.erb +0 -38
  179. data/web/views/retries.erb +0 -83
  180. data/web/views/retry.erb +0 -34
  181. data/web/views/scheduled.erb +0 -57
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,92 +2,123 @@ Sidekiq
2
2
  ==============
3
3
 
4
4
  [![Gem Version](https://badge.fury.io/rb/sidekiq.svg)](https://rubygems.org/gems/sidekiq)
5
- ![Build](https://github.com/mperham/sidekiq/workflows/CI/badge.svg)
5
+ ![Build](https://github.com/sidekiq/sidekiq/workflows/CI/badge.svg)
6
6
 
7
- Simple, efficient background processing for Ruby.
7
+ Simple, efficient background jobs for Ruby.
8
8
 
9
9
  Sidekiq uses threads to handle many jobs at the same time in the
10
- same process. It does not require Rails but will integrate tightly with
11
- Rails to make background processing dead simple.
10
+ same process. Sidekiq can be used by any Ruby application.
12
11
 
13
- Performance
14
- ---------------
15
-
16
- Version | Latency | Garbage created for 10k jobs | Time to process 100k jobs | Throughput | Ruby
17
- -----------------|------|---------|---------|------------------------|-----
18
- Sidekiq 6.0.2 | 3 ms | 156 MB | 14.0 sec| **7100 jobs/sec** | MRI 2.6.3
19
- Sidekiq 6.0.0 | 3 ms | 156 MB | 19 sec | 5200 jobs/sec | MRI 2.6.3
20
- Sidekiq 4.0.0 | 10 ms | 151 MB | 22 sec | 4500 jobs/sec |
21
- Sidekiq 3.5.1 | 22 ms | 1257 MB | 125 sec | 800 jobs/sec |
22
- Resque 1.25.2 | - | - | 420 sec | 240 jobs/sec |
23
- DelayedJob 4.1.1 | - | - | 465 sec | 215 jobs/sec |
24
-
25
- This benchmark can be found in `bin/sidekiqload` and assumes a Redis network latency of 1ms.
26
12
 
27
13
  Requirements
28
14
  -----------------
29
15
 
30
- - Redis: 4.0+
31
- - Ruby: MRI 2.5+ or JRuby 9.2+.
16
+ - Redis: Redis 7.0+, Valkey 7.2+ or Dragonfly 1.27+
17
+ - Ruby: MRI 3.2+ or JRuby 9.4+.
32
18
 
33
- Sidekiq 6.0 supports Rails 5.0+ but does not require it.
19
+ Sidekiq 8.0 supports Rails and Active Job 7.0+.
34
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.
35
24
 
36
25
  Installation
37
26
  -----------------
38
27
 
39
- gem install sidekiq
28
+ bundle add sidekiq
40
29
 
41
30
 
42
31
  Getting Started
43
32
  -----------------
44
33
 
45
- See the [Getting Started wiki page](https://github.com/mperham/sidekiq/wiki/Getting-Started) and follow the simple setup process.
46
- 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
47
36
  Sidekiq and see its features in action. Here's the Web UI:
48
37
 
49
- ![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)
50
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.
51
61
 
52
62
  Want to Upgrade?
53
63
  -------------------
54
64
 
55
- 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
56
69
  features, a commercial-friendly license and allow you to support high
57
70
  quality open source development all at the same time. Please see the
58
71
  [Sidekiq](https://sidekiq.org/) homepage for more detail.
59
72
 
60
- Subscribe to the **[quarterly newsletter](https://tinyletter.com/sidekiq)** to stay informed about the latest
61
- features and changes to Sidekiq and its bigger siblings.
62
-
63
73
 
64
74
  Problems?
65
75
  -----------------
66
76
 
67
- **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.
68
79
 
69
- 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.
70
- 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.
71
82
 
72
- Sidekiq Pro and Sidekiq Enterprise customers get private email support. You can purchase at https://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.
73
85
 
74
86
  Useful resources:
75
87
 
76
- * Product documentation is in the [wiki](https://github.com/mperham/sidekiq/wiki).
77
- * Occasional 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.
78
90
  * The [Sidekiq tag](https://stackoverflow.com/questions/tagged/sidekiq) on Stack Overflow has lots of useful Q &amp; A.
79
91
 
80
- Every Friday morning is Sidekiq happy hour: I video chat and answer questions.
81
- See the [Sidekiq support page](https://sidekiq.org/support.html) for details.
92
+ Every Thursday morning is Sidekiq Office Hour: I video chat and answer questions.
93
+ See the [Sidekiq support page](https://sidekiq.org/support/) for details.
94
+
95
+ Contributing
96
+ -----------------
97
+
98
+ See [the contributing guidelines](https://github.com/sidekiq/sidekiq/blob/main/.github/contributing.md).
82
99
 
100
+ ### ERB Linting with HERB
101
+
102
+ This project uses [HERB](https://herb-tools.dev/) for ERB file linting and formatting. All ERB files have been renamed to use the `.html.erb` extension for better tooling support.
103
+
104
+ **Local Development:**
105
+ ```bash
106
+ # Run HERB linting
107
+ bundle exec rake lint:herb
108
+ # or
109
+ bin/lint-herb
110
+ ```
111
+
112
+ **CI Integration:**
113
+ HERB linting is automatically run in CI to ensure all ERB files are properly formatted and free of parse errors.
83
114
 
84
115
  License
85
116
  -----------------
86
117
 
87
- Please see [LICENSE](https://github.com/mperham/sidekiq/blob/master/LICENSE) for licensing details.
88
-
118
+ See [LICENSE.txt](https://github.com/sidekiq/sidekiq/blob/main/LICENSE.txt) for licensing details.
119
+ 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).
89
120
 
90
121
  Author
91
122
  -----------------
92
123
 
93
- Mike Perham, [@getajobmike](https://twitter.com/getajobmike) / [@sidekiq](https://twitter.com/sidekiq), [https://www.mikeperham.com](https://www.mikeperham.com) / [https://www.contribsys.com](https://www.contribsys.com)
124
+ Mike Perham, [mastodon](https://ruby.social/@getajobmike), [https://www.mikeperham.com](https://www.mikeperham.com) / [https://www.contribsys.com](https://www.contribsys.com)
data/bin/kiq ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # This requires the default gemset so Sidekiq Pro
4
+ # and Sidekiq Enterprise can load any code extensions.
5
+ Bundler.require(:default, :tui)
6
+
7
+ require_relative "../lib/sidekiq/tui"
8
+
9
+ # Run any load hooks registered during Bundler.require
10
+ Sidekiq.loader.run_load_hooks(:tui)
11
+
12
+ tt = Sidekiq::TUI.new(Sidekiq.default_configuration)
13
+
14
+ RatatuiRuby.run do |tui|
15
+ tt.prepare(tui)
16
+ tt.run_loop
17
+ end
data/bin/lint-herb ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # HERB Linting Script
5
+ # Run this script to lint all ERB files in the project
6
+ # Usage: bin/lint-herb
7
+
8
+ require "bundler/setup"
9
+
10
+ puts "🔍 Running HERB linting on ERB files..."
11
+ puts
12
+
13
+ exec("bundle exec herb analyze web/views -n --no-log-file")
@@ -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,13 +4,13 @@
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
8
 
9
9
  def integrate_with_systemd
10
10
  return unless ENV["NOTIFY_SOCKET"]
11
11
 
12
12
  Sidekiq.configure_server do |config|
13
- Sidekiq.logger.info "Enabling systemd notification integration"
13
+ config.logger.info "Enabling systemd notification integration"
14
14
  require "sidekiq/sd_notify"
15
15
  config.on(:startup) do
16
16
  Sidekiq::SdNotify.ready
@@ -31,12 +31,7 @@ begin
31
31
  cli.run
32
32
  rescue => e
33
33
  raise e if $DEBUG
34
- if Sidekiq.error_handlers.length == 0
35
- STDERR.puts e.message
36
- STDERR.puts e.backtrace.join("\n")
37
- else
38
- cli.handle_exception e
39
- end
40
-
34
+ warn e.message
35
+ warn e.backtrace.join("\n")
41
36
  exit 1
42
37
  end