sidekiq 4.2.10 → 7.3.10

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 (159) hide show
  1. checksums.yaml +5 -5
  2. data/Changes.md +932 -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 +218 -116
  8. data/bin/sidekiqmon +11 -0
  9. data/lib/active_job/queue_adapters/sidekiq_adapter.rb +75 -0
  10. data/lib/generators/sidekiq/job_generator.rb +59 -0
  11. data/lib/generators/sidekiq/templates/{worker.rb.erb → job.rb.erb} +2 -2
  12. data/lib/generators/sidekiq/templates/job_spec.rb.erb +6 -0
  13. data/lib/generators/sidekiq/templates/{worker_test.rb.erb → job_test.rb.erb} +1 -1
  14. data/lib/sidekiq/api.rb +710 -322
  15. data/lib/sidekiq/capsule.rb +132 -0
  16. data/lib/sidekiq/cli.rb +268 -248
  17. data/lib/sidekiq/client.rb +153 -101
  18. data/lib/sidekiq/component.rb +90 -0
  19. data/lib/sidekiq/config.rb +311 -0
  20. data/lib/sidekiq/deploy.rb +64 -0
  21. data/lib/sidekiq/embedded.rb +63 -0
  22. data/lib/sidekiq/fetch.rb +50 -42
  23. data/lib/sidekiq/iterable_job.rb +55 -0
  24. data/lib/sidekiq/job/interrupt_handler.rb +24 -0
  25. data/lib/sidekiq/job/iterable/active_record_enumerator.rb +53 -0
  26. data/lib/sidekiq/job/iterable/csv_enumerator.rb +47 -0
  27. data/lib/sidekiq/job/iterable/enumerators.rb +135 -0
  28. data/lib/sidekiq/job/iterable.rb +294 -0
  29. data/lib/sidekiq/job.rb +385 -0
  30. data/lib/sidekiq/job_logger.rb +52 -0
  31. data/lib/sidekiq/job_retry.rb +305 -0
  32. data/lib/sidekiq/job_util.rb +109 -0
  33. data/lib/sidekiq/launcher.rb +208 -108
  34. data/lib/sidekiq/logger.rb +131 -0
  35. data/lib/sidekiq/manager.rb +43 -47
  36. data/lib/sidekiq/metrics/query.rb +158 -0
  37. data/lib/sidekiq/metrics/shared.rb +106 -0
  38. data/lib/sidekiq/metrics/tracking.rb +148 -0
  39. data/lib/sidekiq/middleware/chain.rb +113 -56
  40. data/lib/sidekiq/middleware/current_attributes.rb +128 -0
  41. data/lib/sidekiq/middleware/i18n.rb +9 -7
  42. data/lib/sidekiq/middleware/modules.rb +23 -0
  43. data/lib/sidekiq/monitor.rb +147 -0
  44. data/lib/sidekiq/paginator.rb +33 -15
  45. data/lib/sidekiq/processor.rb +188 -98
  46. data/lib/sidekiq/rails.rb +53 -92
  47. data/lib/sidekiq/redis_client_adapter.rb +114 -0
  48. data/lib/sidekiq/redis_connection.rb +86 -77
  49. data/lib/sidekiq/ring_buffer.rb +32 -0
  50. data/lib/sidekiq/scheduled.rb +140 -51
  51. data/lib/sidekiq/sd_notify.rb +149 -0
  52. data/lib/sidekiq/systemd.rb +26 -0
  53. data/lib/sidekiq/testing/inline.rb +6 -5
  54. data/lib/sidekiq/testing.rb +95 -85
  55. data/lib/sidekiq/transaction_aware_client.rb +59 -0
  56. data/lib/sidekiq/version.rb +7 -1
  57. data/lib/sidekiq/web/action.rb +40 -18
  58. data/lib/sidekiq/web/application.rb +189 -89
  59. data/lib/sidekiq/web/csrf_protection.rb +183 -0
  60. data/lib/sidekiq/web/helpers.rb +239 -101
  61. data/lib/sidekiq/web/router.rb +28 -21
  62. data/lib/sidekiq/web.rb +123 -110
  63. data/lib/sidekiq/worker_compatibility_alias.rb +13 -0
  64. data/lib/sidekiq.rb +97 -185
  65. data/sidekiq.gemspec +26 -27
  66. data/web/assets/images/apple-touch-icon.png +0 -0
  67. data/web/assets/javascripts/application.js +157 -61
  68. data/web/assets/javascripts/base-charts.js +106 -0
  69. data/web/assets/javascripts/chart.min.js +13 -0
  70. data/web/assets/javascripts/chartjs-plugin-annotation.min.js +7 -0
  71. data/web/assets/javascripts/dashboard-charts.js +194 -0
  72. data/web/assets/javascripts/dashboard.js +43 -280
  73. data/web/assets/javascripts/metrics.js +298 -0
  74. data/web/assets/stylesheets/application-dark.css +147 -0
  75. data/web/assets/stylesheets/application-rtl.css +163 -0
  76. data/web/assets/stylesheets/application.css +176 -196
  77. data/web/assets/stylesheets/bootstrap-rtl.min.css +9 -0
  78. data/web/assets/stylesheets/bootstrap.css +2 -2
  79. data/web/locales/ar.yml +87 -0
  80. data/web/locales/cs.yml +62 -62
  81. data/web/locales/da.yml +60 -53
  82. data/web/locales/de.yml +65 -53
  83. data/web/locales/el.yml +43 -24
  84. data/web/locales/en.yml +88 -64
  85. data/web/locales/es.yml +70 -53
  86. data/web/locales/fa.yml +65 -64
  87. data/web/locales/fr.yml +82 -62
  88. data/web/locales/gd.yml +98 -0
  89. data/web/locales/he.yml +80 -0
  90. data/web/locales/hi.yml +59 -59
  91. data/web/locales/it.yml +85 -54
  92. data/web/locales/ja.yml +74 -62
  93. data/web/locales/ko.yml +52 -52
  94. data/web/locales/lt.yml +83 -0
  95. data/web/locales/nb.yml +61 -61
  96. data/web/locales/nl.yml +52 -52
  97. data/web/locales/pl.yml +45 -45
  98. data/web/locales/pt-br.yml +82 -55
  99. data/web/locales/pt.yml +51 -51
  100. data/web/locales/ru.yml +68 -63
  101. data/web/locales/sv.yml +53 -53
  102. data/web/locales/ta.yml +60 -60
  103. data/web/locales/tr.yml +100 -0
  104. data/web/locales/uk.yml +85 -61
  105. data/web/locales/ur.yml +80 -0
  106. data/web/locales/vi.yml +83 -0
  107. data/web/locales/zh-cn.yml +42 -16
  108. data/web/locales/zh-tw.yml +41 -8
  109. data/web/views/_footer.erb +20 -3
  110. data/web/views/_job_info.erb +21 -4
  111. data/web/views/_metrics_period_select.erb +12 -0
  112. data/web/views/_nav.erb +5 -19
  113. data/web/views/_paging.erb +3 -1
  114. data/web/views/_poll_link.erb +3 -6
  115. data/web/views/_summary.erb +7 -7
  116. data/web/views/busy.erb +85 -31
  117. data/web/views/dashboard.erb +53 -20
  118. data/web/views/dead.erb +3 -3
  119. data/web/views/filtering.erb +6 -0
  120. data/web/views/layout.erb +17 -6
  121. data/web/views/metrics.erb +90 -0
  122. data/web/views/metrics_for_job.erb +59 -0
  123. data/web/views/morgue.erb +15 -16
  124. data/web/views/queue.erb +35 -25
  125. data/web/views/queues.erb +20 -4
  126. data/web/views/retries.erb +19 -16
  127. data/web/views/retry.erb +3 -3
  128. data/web/views/scheduled.erb +19 -17
  129. metadata +103 -194
  130. data/.github/contributing.md +0 -32
  131. data/.github/issue_template.md +0 -9
  132. data/.gitignore +0 -12
  133. data/.travis.yml +0 -18
  134. data/3.0-Upgrade.md +0 -70
  135. data/4.0-Upgrade.md +0 -53
  136. data/COMM-LICENSE +0 -95
  137. data/Ent-Changes.md +0 -173
  138. data/Gemfile +0 -29
  139. data/LICENSE +0 -9
  140. data/Pro-2.0-Upgrade.md +0 -138
  141. data/Pro-3.0-Upgrade.md +0 -44
  142. data/Pro-Changes.md +0 -628
  143. data/Rakefile +0 -12
  144. data/bin/sidekiqctl +0 -99
  145. data/code_of_conduct.md +0 -50
  146. data/lib/generators/sidekiq/templates/worker_spec.rb.erb +0 -6
  147. data/lib/generators/sidekiq/worker_generator.rb +0 -49
  148. data/lib/sidekiq/core_ext.rb +0 -119
  149. data/lib/sidekiq/exception_handler.rb +0 -31
  150. data/lib/sidekiq/extensions/action_mailer.rb +0 -57
  151. data/lib/sidekiq/extensions/active_record.rb +0 -40
  152. data/lib/sidekiq/extensions/class_methods.rb +0 -40
  153. data/lib/sidekiq/extensions/generic_proxy.rb +0 -25
  154. data/lib/sidekiq/logging.rb +0 -106
  155. data/lib/sidekiq/middleware/server/active_record.rb +0 -13
  156. data/lib/sidekiq/middleware/server/logging.rb +0 -31
  157. data/lib/sidekiq/middleware/server/retry_jobs.rb +0 -205
  158. data/lib/sidekiq/util.rb +0 -63
  159. data/lib/sidekiq/worker.rb +0 -121
data/bin/sidekiqload CHANGED
@@ -1,154 +1,256 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ #
4
+ # bin/sidekiqload is a helpful script to load test and
5
+ # performance tune Sidekiq's core. It creates 500,000 no-op
6
+ # jobs and executes them as fast as possible.
7
+ # Example Usage:
8
+ #
9
+ # > RUBY_YJIT_ENABLE=1 LATENCY=0 THREADS=10 bin/sidekiqload
10
+ # Result: Done, 500000 jobs in 20.264945 sec, 24673 jobs/sec
11
+ #
12
+ # Use LATENCY=1 to get a more real world network setup
13
+ # but you'll need to setup and start toxiproxy as noted below.
14
+ #
15
+ # Use AJ=1 to test ActiveJob instead of plain old Sidekiq::Jobs so
16
+ # you can see the runtime performance difference between the two APIs.
17
+ #
18
+ # None of this script is considered a public API and may change over time.
19
+ #
20
+
3
21
  # Quiet some warnings we see when running in warning mode:
4
22
  # RUBYOPT=-w bundle exec sidekiq
5
23
  $TESTING = false
24
+ puts RUBY_DESCRIPTION
25
+ puts(%w[THREADS LATENCY AJ PROFILE].map { |x| "#{x}: #{ENV[x] || "nil"}" }.join(", "))
6
26
 
7
- #require 'ruby-prof'
8
- Bundler.require(:default)
27
+ require "ruby-prof" if ENV["PROFILE"]
28
+ require "bundler/setup"
29
+ Bundler.require(:default, :load_test)
9
30
 
10
- require_relative '../lib/sidekiq/cli'
11
- require_relative '../lib/sidekiq/launcher'
31
+ latency = Integer(ENV["LATENCY"] || 1)
32
+ if latency > 0
33
+ # brew tap shopify/shopify
34
+ # brew install toxiproxy
35
+ # run `toxiproxy-server` in a separate terminal window.
36
+ require "toxiproxy"
37
+ # simulate a non-localhost network for realer-world conditions.
38
+ # adding 1ms of network latency has an ENORMOUS impact on benchmarks
39
+ Toxiproxy.populate([{
40
+ name: "redis",
41
+ listen: "127.0.0.1:6380",
42
+ upstream: "127.0.0.1:6379"
43
+ }])
44
+ end
12
45
 
13
- include Sidekiq::Util
46
+ if ENV["AJ"]
47
+ require "active_job"
48
+ puts "Using ActiveJob #{ActiveJob::VERSION::STRING}"
49
+ ActiveJob::Base.queue_adapter = :sidekiq
50
+ ActiveJob::Base.logger.level = Logger::WARN
14
51
 
15
- Sidekiq.configure_server do |config|
16
- #config.options[:concurrency] = 1
17
- config.redis = { db: 13 }
18
- config.options[:queues] << 'default'
19
- config.logger.level = Logger::ERROR
20
- config.average_scheduled_poll_interval = 2
21
- config.reliable! if defined?(Sidekiq::Pro)
52
+ class LoadJob < ActiveJob::Base
53
+ def perform(string, idx, hash, ts = nil)
54
+ puts(Time.now.to_f - ts) if !ts.nil?
55
+ end
56
+ end
22
57
  end
23
58
 
24
59
  class LoadWorker
25
- include Sidekiq::Worker
60
+ include Sidekiq::Job
61
+ $count = 0
62
+ $lock = Mutex.new
63
+
26
64
  sidekiq_options retry: 1
27
65
  sidekiq_retry_in do |x|
28
66
  1
29
67
  end
30
68
 
31
- def perform(idx)
32
- #raise idx.to_s if idx % 100 == 1
69
+ def perform(string, idx, hash, ts = nil)
70
+ $lock.synchronize do
71
+ $count += 1
72
+ if $count % 100_000 == 0
73
+ logger.warn("#{Time.now} Done #{$count}")
74
+ end
75
+ end
76
+ puts(Time.now.to_f - ts) if !ts.nil?
77
+ # raise idx.to_s if idx % 100 == 1
33
78
  end
34
79
  end
35
80
 
36
- # brew tap shopify/shopify
37
- # brew install toxiproxy
38
- # gem install toxiproxy
39
- #require 'toxiproxy'
40
- # simulate a non-localhost network for realer-world conditions.
41
- # adding 1ms of network latency has an ENORMOUS impact on benchmarks
42
- #Toxiproxy.populate([{
43
- #"name": "redis",
44
- #"listen": "127.0.0.1:6380",
45
- #"upstream": "127.0.0.1:6379"
46
- #}])
47
-
48
- self_read, self_write = IO.pipe
49
- %w(INT TERM USR1 USR2 TTIN).each do |sig|
50
- begin
51
- trap sig do
52
- self_write.puts(sig)
81
+ def Process.rss
82
+ `ps -o rss= -p #{Process.pid}`.chomp.to_i
83
+ end
84
+
85
+ class Loader
86
+ def initialize
87
+ @iter = ENV["GC"] ? 10 : 500
88
+ @count = Integer(ENV["COUNT"] || 1_000)
89
+ @latency = Integer(ENV["LATENCY"] || 1)
90
+ end
91
+
92
+ def configure
93
+ @x = Sidekiq.configure_embed do |config|
94
+ config.redis = {db: 13, port: ((@latency > 0) ? 6380 : 6379)}
95
+ config.concurrency = Integer(ENV.fetch("THREADS", "10"))
96
+ # config.redis = { db: 13, port: 6380, driver: :hiredis}
97
+ config.queues = %w[default]
98
+ config.logger.level = Logger::WARN
99
+ config.average_scheduled_poll_interval = 2
100
+ config.reliable! if defined?(Sidekiq::Pro)
101
+ end
102
+
103
+ @self_read, @self_write = IO.pipe
104
+ %w[INT TERM TSTP TTIN].each do |sig|
105
+ trap sig do
106
+ @self_write.puts(sig)
107
+ end
108
+ rescue ArgumentError
109
+ puts "Signal #{sig} not supported"
53
110
  end
54
- rescue ArgumentError
55
- puts "Signal #{sig} not supported"
56
111
  end
57
- end
58
112
 
59
- Sidekiq.redis {|c| c.flushdb}
60
- def handle_signal(launcher, sig)
61
- Sidekiq.logger.debug "Got #{sig} signal"
62
- case sig
63
- when 'INT'
64
- # Handle Ctrl-C in JRuby like MRI
65
- # http://jira.codehaus.org/browse/JRUBY-4637
66
- raise Interrupt
67
- when 'TERM'
68
- # Heroku sends TERM and then waits 10 seconds for process to exit.
69
- raise Interrupt
70
- when 'USR1'
71
- Sidekiq.logger.info "Received USR1, no longer accepting new work"
72
- launcher.quiet
73
- when 'USR2'
74
- if Sidekiq.options[:logfile]
75
- Sidekiq.logger.info "Received USR2, reopening log file"
76
- Sidekiq::Logging.reopen_logs
113
+ def handle_signal(sig)
114
+ launcher = @x
115
+ Sidekiq.logger.debug "Got #{sig} signal"
116
+ case sig
117
+ when "INT"
118
+ # Handle Ctrl-C in JRuby like MRI
119
+ # http://jira.codehaus.org/browse/JRUBY-4637
120
+ raise Interrupt
121
+ when "TERM"
122
+ # Heroku sends TERM and then waits 30 seconds for process to exit.
123
+ raise Interrupt
124
+ when "TSTP"
125
+ Sidekiq.logger.info "Received TSTP, no longer accepting new work"
126
+ launcher.quiet
127
+ when "TTIN"
128
+ Thread.list.each do |thread|
129
+ Sidekiq.logger.warn "Thread TID-#{(thread.object_id ^ ::Process.pid).to_s(36)} #{thread["label"]}"
130
+ if thread.backtrace
131
+ Sidekiq.logger.warn thread.backtrace.join("\n")
132
+ else
133
+ Sidekiq.logger.warn "<no backtrace available>"
134
+ end
135
+ end
77
136
  end
78
- when 'TTIN'
79
- Thread.list.each do |thread|
80
- Sidekiq.logger.warn "Thread TID-#{thread.object_id.to_s(36)} #{thread['label']}"
81
- if thread.backtrace
82
- Sidekiq.logger.warn thread.backtrace.join("\n")
83
- else
84
- Sidekiq.logger.warn "<no backtrace available>"
137
+ end
138
+
139
+ def setup
140
+ Sidekiq.logger.error("Setup RSS: #{Process.rss}")
141
+ Sidekiq.redis { |c| c.flushdb }
142
+ start = Time.now
143
+ if ENV["AJ"]
144
+ @iter.times do
145
+ ActiveJob.perform_all_later(@count.times.map do |idx|
146
+ LoadJob.new("mike", idx, {mike: "bob"})
147
+ end)
148
+ end
149
+ else
150
+ @iter.times do
151
+ arr = Array.new(@count) { |idx| ["string", idx, {"mike" => "bob"}] }
152
+ Sidekiq::Client.push_bulk("class" => LoadWorker, "args" => arr)
85
153
  end
86
154
  end
155
+ Sidekiq.logger.warn "Created #{@count * @iter} jobs in #{Time.now - start} sec"
87
156
  end
88
- end
89
157
 
90
- def Process.rss
91
- `ps -o rss= -p #{Process.pid}`.chomp.to_i
92
- end
158
+ def monitor
159
+ @monitor = Thread.new do
160
+ GC.start
161
+ loop do
162
+ sleep 0.2
163
+ qsize = Sidekiq.redis do |conn|
164
+ conn.llen "queue:default"
165
+ end
166
+ total = qsize
167
+ if total == 0
168
+ ending = Time.now - @start
169
+ size = @iter * @count
170
+ Sidekiq.logger.error("Done, #{size} jobs in #{ending} sec, #{(size / ending).to_i} jobs/sec")
171
+ Sidekiq.logger.error("Ending RSS: #{Process.rss}")
172
+ Sidekiq.logger.error("Now here's the latency for three jobs")
93
173
 
94
- iter = 10
95
- count = 10_000
174
+ if ENV["AJ"]
175
+ LoadJob.perform_later("", 1, {}, Time.now.to_f)
176
+ LoadJob.perform_later("", 2, {}, Time.now.to_f)
177
+ LoadJob.perform_later("", 3, {}, Time.now.to_f)
178
+ else
179
+ LoadWorker.perform_async("", 1, {}, Time.now.to_f)
180
+ LoadWorker.perform_async("", 2, {}, Time.now.to_f)
181
+ LoadWorker.perform_async("", 3, {}, Time.now.to_f)
182
+ end
96
183
 
97
- iter.times do
98
- arr = Array.new(count) do
99
- []
184
+ sleep 0.1
185
+ @x.stop
186
+ Process.kill("INT", $$)
187
+ break
188
+ end
189
+ end
190
+ end
100
191
  end
101
- count.times do |idx|
102
- arr[idx][0] = idx
192
+
193
+ def with_latency(latency, &block)
194
+ Sidekiq.logger.error "Simulating #{latency}ms of latency between Sidekiq and redis"
195
+ if latency > 0
196
+ Toxiproxy[:redis].downstream(:latency, latency: latency).apply(&block)
197
+ else
198
+ yield
199
+ end
103
200
  end
104
- Sidekiq::Client.push_bulk('class' => LoadWorker, 'args' => arr)
105
- end
106
- Sidekiq.logger.error "Created #{count*iter} jobs"
107
-
108
- Monitoring = Thread.new do
109
- watchdog("monitor thread") do
110
- while true
111
- sleep 1
112
- qsize, retries = Sidekiq.redis do |conn|
113
- conn.pipelined do
114
- conn.llen "queue:default"
115
- conn.zcard "retry"
116
- end
117
- end.map(&:to_i)
118
- total = qsize + retries
119
- #GC.start
120
- Sidekiq.logger.error("RSS: #{Process.rss} Pending: #{total}")
121
- if total == 0
122
- Sidekiq.logger.error("Done")
123
- exit(0)
201
+
202
+ def run(name)
203
+ Sidekiq.logger.warn("Starting #{name}")
204
+ monitor
205
+
206
+ if ENV["PROFILE"]
207
+ RubyProf.exclude_threads = [@monitor]
208
+ RubyProf.start
209
+ elsif ENV["GC"]
210
+ GC.start
211
+ GC.compact
212
+ GC.disable
213
+ Sidekiq.logger.error("GC Start RSS: #{Process.rss}")
214
+ end
215
+ @start = Time.now
216
+ with_latency(@latency) do
217
+ @x.run
218
+
219
+ while (readable_io = IO.select([@self_read]))
220
+ signal = readable_io.first[0].gets.strip
221
+ handle_signal(signal)
124
222
  end
125
223
  end
224
+ # normal
225
+ rescue Interrupt
226
+ rescue => e
227
+ raise e if $DEBUG
228
+ warn e.message
229
+ warn e.backtrace.join("\n")
230
+ exit 1
231
+ ensure
232
+ @x.stop
126
233
  end
127
- end
128
234
 
129
- begin
130
- #RubyProf::exclude_threads = [ Monitoring ]
131
- #RubyProf.start
132
- fire_event(:startup)
133
- #Sidekiq.logger.error "Simulating 1ms of latency between Sidekiq and redis"
134
- #Toxiproxy[:redis].downstream(:latency, latency: 1).apply do
135
- launcher = Sidekiq::Launcher.new(Sidekiq.options)
136
- launcher.run
137
-
138
- while readable_io = IO.select([self_read])
139
- signal = readable_io.first[0].gets.strip
140
- handle_signal(launcher, signal)
235
+ def done
236
+ Sidekiq.logger.error("GC End RSS: #{Process.rss}") if ENV["GC"]
237
+ if ENV["PROFILE"]
238
+ Sidekiq.logger.error("Profiling...")
239
+ result = RubyProf.stop
240
+ printer = RubyProf::GraphHtmlPrinter.new(result)
241
+ printer.print(File.new("output.html", "w"), min_percent: 1)
141
242
  end
142
- #end
143
- rescue SystemExit => e
144
- #Sidekiq.logger.error("Profiling...")
145
- #result = RubyProf.stop
146
- #printer = RubyProf::GraphHtmlPrinter.new(result)
147
- #printer.print(File.new("output.html", "w"), :min_percent => 1)
148
- # normal
149
- rescue => e
150
- raise e if $DEBUG
151
- STDERR.puts e.message
152
- STDERR.puts e.backtrace.join("\n")
153
- exit 1
243
+ end
154
244
  end
245
+
246
+ ll = Loader.new
247
+ ll.configure
248
+
249
+ if ENV["WARM"]
250
+ ll.setup
251
+ ll.run("warmup")
252
+ end
253
+
254
+ ll.setup
255
+ ll.run("load")
256
+ ll.done
data/bin/sidekiqmon ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "sidekiq/monitor"
4
+
5
+ # disable the Redis connection pool logging
6
+ Sidekiq.default_configuration.logger.level = :warn
7
+
8
+ section = "all"
9
+ section = ARGV[0] if ARGV.size == 1
10
+
11
+ Sidekiq::Monitor::Status.new.display(section)
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveJob
4
+ module QueueAdapters
5
+ # Explicitly remove the implementation existing in older rails'.
6
+ remove_const(:SidekiqAdapter) if const_defined?(:SidekiqAdapter)
7
+
8
+ # Sidekiq adapter for Active Job
9
+ #
10
+ # To use Sidekiq set the queue_adapter config to +:sidekiq+.
11
+ #
12
+ # Rails.application.config.active_job.queue_adapter = :sidekiq
13
+ class SidekiqAdapter
14
+ # Defines whether enqueuing should happen implicitly to after commit when called
15
+ # from inside a transaction.
16
+ # @api private
17
+ def enqueue_after_transaction_commit?
18
+ true
19
+ end
20
+
21
+ # @api private
22
+ def enqueue(job)
23
+ job.provider_job_id = JobWrapper.set(
24
+ wrapped: job.class,
25
+ queue: job.queue_name
26
+ ).perform_async(job.serialize)
27
+ end
28
+
29
+ # @api private
30
+ def enqueue_at(job, timestamp)
31
+ job.provider_job_id = JobWrapper.set(
32
+ wrapped: job.class,
33
+ queue: job.queue_name
34
+ ).perform_at(timestamp, job.serialize)
35
+ end
36
+
37
+ # @api private
38
+ def enqueue_all(jobs)
39
+ enqueued_count = 0
40
+ jobs.group_by(&:class).each do |job_class, same_class_jobs|
41
+ same_class_jobs.group_by(&:queue_name).each do |queue, same_class_and_queue_jobs|
42
+ immediate_jobs, scheduled_jobs = same_class_and_queue_jobs.partition { |job| job.scheduled_at.nil? }
43
+
44
+ if immediate_jobs.any?
45
+ jids = Sidekiq::Client.push_bulk(
46
+ "class" => JobWrapper,
47
+ "wrapped" => job_class,
48
+ "queue" => queue,
49
+ "args" => immediate_jobs.map { |job| [job.serialize] }
50
+ )
51
+ enqueued_count += jids.compact.size
52
+ end
53
+
54
+ if scheduled_jobs.any?
55
+ jids = Sidekiq::Client.push_bulk(
56
+ "class" => JobWrapper,
57
+ "wrapped" => job_class,
58
+ "queue" => queue,
59
+ "args" => scheduled_jobs.map { |job| [job.serialize] },
60
+ "at" => scheduled_jobs.map { |job| job.scheduled_at&.to_f }
61
+ )
62
+ enqueued_count += jids.compact.size
63
+ end
64
+ end
65
+ end
66
+ enqueued_count
67
+ end
68
+
69
+ # Defines a class alias for backwards compatibility with enqueued Active Job jobs.
70
+ # @api private
71
+ class JobWrapper < Sidekiq::ActiveJob::Wrapper
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators/named_base"
4
+
5
+ module Sidekiq
6
+ module Generators # :nodoc:
7
+ class JobGenerator < ::Rails::Generators::NamedBase # :nodoc:
8
+ desc "This generator creates a Sidekiq Job in app/sidekiq and a corresponding test"
9
+
10
+ check_class_collision suffix: "Job"
11
+
12
+ def self.default_generator_root
13
+ File.dirname(__FILE__)
14
+ end
15
+
16
+ def create_job_file
17
+ template "job.rb.erb", File.join("app/sidekiq", class_path, "#{file_name}_job.rb")
18
+ end
19
+
20
+ def create_test_file
21
+ return unless test_framework
22
+
23
+ if test_framework == :rspec
24
+ create_job_spec
25
+ else
26
+ create_job_test
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def create_job_spec
33
+ template_file = File.join(
34
+ "spec/sidekiq",
35
+ class_path,
36
+ "#{file_name}_job_spec.rb"
37
+ )
38
+ template "job_spec.rb.erb", template_file
39
+ end
40
+
41
+ def create_job_test
42
+ template_file = File.join(
43
+ "test/sidekiq",
44
+ class_path,
45
+ "#{file_name}_job_test.rb"
46
+ )
47
+ template "job_test.rb.erb", template_file
48
+ end
49
+
50
+ def file_name
51
+ @_file_name ||= super.sub(/_?job\z/i, "")
52
+ end
53
+
54
+ def test_framework
55
+ ::Rails.application.config.generators.options[:rails][:test_framework]
56
+ end
57
+ end
58
+ end
59
+ end
@@ -1,6 +1,6 @@
1
1
  <% module_namespacing do -%>
2
- class <%= class_name %>Worker
3
- include Sidekiq::Worker
2
+ class <%= class_name %>Job
3
+ include Sidekiq::Job
4
4
 
5
5
  def perform(*args)
6
6
  # Do something
@@ -0,0 +1,6 @@
1
+ require 'rails_helper'
2
+ <% module_namespacing do -%>
3
+ RSpec.describe <%= class_name %>Job, type: :job do
4
+ pending "add some examples to (or delete) #{__FILE__}"
5
+ end
6
+ <% end -%>
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
  <% module_namespacing do -%>
3
- class <%= class_name %>WorkerTest < <% if defined? Minitest::Test %>Minitest::Test<% else %>MiniTest::Unit::TestCase<% end %>
3
+ class <%= class_name %>JobTest < Minitest::Test
4
4
  def test_example
5
5
  skip "add some examples to (or delete) #{__FILE__}"
6
6
  end