sidekiq 5.2.10 → 6.5.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/Changes.md +422 -1
  3. data/LICENSE +3 -3
  4. data/README.md +24 -35
  5. data/bin/sidekiq +27 -3
  6. data/bin/sidekiqload +79 -67
  7. data/bin/sidekiqmon +8 -0
  8. data/lib/generators/sidekiq/job_generator.rb +57 -0
  9. data/lib/generators/sidekiq/templates/{worker.rb.erb → job.rb.erb} +2 -2
  10. data/lib/generators/sidekiq/templates/{worker_spec.rb.erb → job_spec.rb.erb} +1 -1
  11. data/lib/generators/sidekiq/templates/{worker_test.rb.erb → job_test.rb.erb} +1 -1
  12. data/lib/sidekiq/api.rb +527 -310
  13. data/lib/sidekiq/cli.rb +204 -208
  14. data/lib/sidekiq/client.rb +78 -82
  15. data/lib/sidekiq/component.rb +65 -0
  16. data/lib/sidekiq/delay.rb +8 -7
  17. data/lib/sidekiq/extensions/action_mailer.rb +13 -22
  18. data/lib/sidekiq/extensions/active_record.rb +13 -10
  19. data/lib/sidekiq/extensions/class_methods.rb +14 -11
  20. data/lib/sidekiq/extensions/generic_proxy.rb +7 -5
  21. data/lib/sidekiq/fetch.rb +50 -40
  22. data/lib/sidekiq/job.rb +13 -0
  23. data/lib/sidekiq/job_logger.rb +33 -7
  24. data/lib/sidekiq/job_retry.rb +126 -106
  25. data/lib/sidekiq/job_util.rb +71 -0
  26. data/lib/sidekiq/launcher.rb +177 -83
  27. data/lib/sidekiq/logger.rb +156 -0
  28. data/lib/sidekiq/manager.rb +40 -41
  29. data/lib/sidekiq/metrics/deploy.rb +47 -0
  30. data/lib/sidekiq/metrics/query.rb +153 -0
  31. data/lib/sidekiq/metrics/shared.rb +94 -0
  32. data/lib/sidekiq/metrics/tracking.rb +134 -0
  33. data/lib/sidekiq/middleware/chain.rb +102 -46
  34. data/lib/sidekiq/middleware/current_attributes.rb +63 -0
  35. data/lib/sidekiq/middleware/i18n.rb +7 -7
  36. data/lib/sidekiq/middleware/modules.rb +21 -0
  37. data/lib/sidekiq/monitor.rb +133 -0
  38. data/lib/sidekiq/paginator.rb +28 -16
  39. data/lib/sidekiq/processor.rb +104 -97
  40. data/lib/sidekiq/rails.rb +46 -37
  41. data/lib/sidekiq/redis_client_adapter.rb +154 -0
  42. data/lib/sidekiq/redis_connection.rb +108 -77
  43. data/lib/sidekiq/ring_buffer.rb +29 -0
  44. data/lib/sidekiq/scheduled.rb +105 -42
  45. data/lib/sidekiq/sd_notify.rb +149 -0
  46. data/lib/sidekiq/systemd.rb +24 -0
  47. data/lib/sidekiq/testing/inline.rb +6 -5
  48. data/lib/sidekiq/testing.rb +68 -58
  49. data/lib/sidekiq/transaction_aware_client.rb +45 -0
  50. data/lib/sidekiq/version.rb +2 -1
  51. data/lib/sidekiq/web/action.rb +15 -11
  52. data/lib/sidekiq/web/application.rb +103 -77
  53. data/lib/sidekiq/web/csrf_protection.rb +180 -0
  54. data/lib/sidekiq/web/helpers.rb +125 -95
  55. data/lib/sidekiq/web/router.rb +23 -19
  56. data/lib/sidekiq/web.rb +65 -105
  57. data/lib/sidekiq/worker.rb +259 -109
  58. data/lib/sidekiq.rb +170 -62
  59. data/sidekiq.gemspec +23 -16
  60. data/web/assets/images/apple-touch-icon.png +0 -0
  61. data/web/assets/javascripts/application.js +113 -61
  62. data/web/assets/javascripts/chart.min.js +13 -0
  63. data/web/assets/javascripts/chartjs-plugin-annotation.min.js +7 -0
  64. data/web/assets/javascripts/dashboard.js +53 -89
  65. data/web/assets/javascripts/graph.js +16 -0
  66. data/web/assets/javascripts/metrics.js +262 -0
  67. data/web/assets/stylesheets/application-dark.css +143 -0
  68. data/web/assets/stylesheets/application-rtl.css +0 -4
  69. data/web/assets/stylesheets/application.css +88 -233
  70. data/web/locales/ar.yml +8 -2
  71. data/web/locales/de.yml +14 -2
  72. data/web/locales/el.yml +43 -19
  73. data/web/locales/en.yml +13 -1
  74. data/web/locales/es.yml +18 -2
  75. data/web/locales/fr.yml +10 -3
  76. data/web/locales/ja.yml +14 -1
  77. data/web/locales/lt.yml +83 -0
  78. data/web/locales/pl.yml +4 -4
  79. data/web/locales/pt-br.yml +27 -9
  80. data/web/locales/ru.yml +4 -0
  81. data/web/locales/vi.yml +83 -0
  82. data/web/locales/zh-cn.yml +36 -11
  83. data/web/locales/zh-tw.yml +32 -7
  84. data/web/views/_footer.erb +1 -1
  85. data/web/views/_job_info.erb +3 -2
  86. data/web/views/_nav.erb +1 -1
  87. data/web/views/_poll_link.erb +2 -5
  88. data/web/views/_summary.erb +7 -7
  89. data/web/views/busy.erb +61 -22
  90. data/web/views/dashboard.erb +23 -14
  91. data/web/views/dead.erb +3 -3
  92. data/web/views/layout.erb +3 -1
  93. data/web/views/metrics.erb +69 -0
  94. data/web/views/metrics_for_job.erb +87 -0
  95. data/web/views/morgue.erb +9 -6
  96. data/web/views/queue.erb +23 -10
  97. data/web/views/queues.erb +10 -2
  98. data/web/views/retries.erb +11 -8
  99. data/web/views/retry.erb +3 -3
  100. data/web/views/scheduled.erb +5 -2
  101. metadata +58 -63
  102. data/.circleci/config.yml +0 -61
  103. data/.github/contributing.md +0 -32
  104. data/.github/issue_template.md +0 -11
  105. data/.gitignore +0 -15
  106. data/.travis.yml +0 -11
  107. data/3.0-Upgrade.md +0 -70
  108. data/4.0-Upgrade.md +0 -53
  109. data/5.0-Upgrade.md +0 -56
  110. data/COMM-LICENSE +0 -97
  111. data/Ent-Changes.md +0 -238
  112. data/Gemfile +0 -19
  113. data/Pro-2.0-Upgrade.md +0 -138
  114. data/Pro-3.0-Upgrade.md +0 -44
  115. data/Pro-4.0-Upgrade.md +0 -35
  116. data/Pro-Changes.md +0 -759
  117. data/Rakefile +0 -9
  118. data/bin/sidekiqctl +0 -20
  119. data/code_of_conduct.md +0 -50
  120. data/lib/generators/sidekiq/worker_generator.rb +0 -49
  121. data/lib/sidekiq/core_ext.rb +0 -1
  122. data/lib/sidekiq/ctl.rb +0 -221
  123. data/lib/sidekiq/exception_handler.rb +0 -29
  124. data/lib/sidekiq/logging.rb +0 -122
  125. data/lib/sidekiq/middleware/server/active_record.rb +0 -23
  126. data/lib/sidekiq/util.rb +0 -66
data/bin/sidekiqload CHANGED
@@ -4,18 +4,22 @@
4
4
  # RUBYOPT=-w bundle exec sidekiq
5
5
  $TESTING = false
6
6
 
7
- #require 'ruby-prof'
8
- Bundler.require(:default)
7
+ # require "ruby-prof"
8
+ require "bundler/setup"
9
+ Bundler.require(:default, :load_test)
9
10
 
10
- require_relative '../lib/sidekiq/cli'
11
- require_relative '../lib/sidekiq/launcher'
11
+ require_relative "../lib/sidekiq/cli"
12
+ require_relative "../lib/sidekiq/launcher"
12
13
 
13
- include Sidekiq::Util
14
+ if ENV["SIDEKIQ_REDIS_CLIENT"]
15
+ Sidekiq::RedisConnection.adapter = :redis_client
16
+ end
14
17
 
15
18
  Sidekiq.configure_server do |config|
16
- #config.options[:concurrency] = 1
17
- config.redis = { db: 13 }
18
- config.options[:queues] << 'default'
19
+ config.options[:concurrency] = 10
20
+ config.redis = {db: 13, port: 6380}
21
+ # config.redis = { db: 13, port: 6380, driver: :hiredis}
22
+ config.options[:queues] << "default"
19
23
  config.logger.level = Logger::ERROR
20
24
  config.average_scheduled_poll_interval = 2
21
25
  config.reliable! if defined?(Sidekiq::Pro)
@@ -28,51 +32,50 @@ class LoadWorker
28
32
  1
29
33
  end
30
34
 
31
- def perform(idx)
32
- #raise idx.to_s if idx % 100 == 1
35
+ def perform(idx, ts = nil)
36
+ puts(Time.now.to_f - ts) if !ts.nil?
37
+ # raise idx.to_s if idx % 100 == 1
33
38
  end
34
39
  end
35
40
 
36
41
  # brew tap shopify/shopify
37
42
  # brew install toxiproxy
38
- # gem install toxiproxy
39
- #require 'toxiproxy'
43
+ # run `toxiproxy-server` in a separate terminal window.
44
+ require "toxiproxy"
40
45
  # simulate a non-localhost network for realer-world conditions.
41
46
  # 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
+ Toxiproxy.populate([{
48
+ name: "redis",
49
+ listen: "127.0.0.1:6380",
50
+ upstream: "127.0.0.1:6379"
51
+ }])
47
52
 
48
53
  self_read, self_write = IO.pipe
49
- %w(INT TERM TSTP TTIN).each do |sig|
50
- begin
51
- trap sig do
52
- self_write.puts(sig)
53
- end
54
- rescue ArgumentError
55
- puts "Signal #{sig} not supported"
54
+ %w[INT TERM TSTP TTIN].each do |sig|
55
+ trap sig do
56
+ self_write.puts(sig)
56
57
  end
58
+ rescue ArgumentError
59
+ puts "Signal #{sig} not supported"
57
60
  end
58
61
 
59
- Sidekiq.redis {|c| c.flushdb}
62
+ Sidekiq.redis { |c| c.flushdb }
60
63
  def handle_signal(launcher, sig)
61
64
  Sidekiq.logger.debug "Got #{sig} signal"
62
65
  case sig
63
- when 'INT'
66
+ when "INT"
64
67
  # Handle Ctrl-C in JRuby like MRI
65
68
  # http://jira.codehaus.org/browse/JRUBY-4637
66
69
  raise Interrupt
67
- when 'TERM'
70
+ when "TERM"
68
71
  # Heroku sends TERM and then waits 30 seconds for process to exit.
69
72
  raise Interrupt
70
- when 'TSTP'
73
+ when "TSTP"
71
74
  Sidekiq.logger.info "Received TSTP, no longer accepting new work"
72
75
  launcher.quiet
73
- when 'TTIN'
76
+ when "TTIN"
74
77
  Thread.list.each do |thread|
75
- Sidekiq.logger.warn "Thread TID-#{(thread.object_id ^ ::Process.pid).to_s(36)} #{thread['label']}"
78
+ Sidekiq.logger.warn "Thread TID-#{(thread.object_id ^ ::Process.pid).to_s(36)} #{thread["label"]}"
76
79
  if thread.backtrace
77
80
  Sidekiq.logger.warn thread.backtrace.join("\n")
78
81
  else
@@ -90,60 +93,69 @@ iter = 10
90
93
  count = 10_000
91
94
 
92
95
  iter.times do
93
- arr = Array.new(count) do
94
- []
95
- end
96
- count.times do |idx|
97
- arr[idx][0] = idx
98
- end
99
- Sidekiq::Client.push_bulk('class' => LoadWorker, 'args' => arr)
96
+ arr = Array.new(count) { |idx| [idx] }
97
+ Sidekiq::Client.push_bulk("class" => LoadWorker, "args" => arr)
100
98
  end
101
- Sidekiq.logger.error "Created #{count*iter} jobs"
99
+ Sidekiq.logger.error "Created #{count * iter} jobs"
100
+
101
+ start = Time.now
102
102
 
103
103
  Monitoring = Thread.new do
104
- watchdog("monitor thread") do
105
- while true
106
- sleep 1
107
- qsize, retries = Sidekiq.redis do |conn|
108
- conn.pipelined do
109
- conn.llen "queue:default"
110
- conn.zcard "retry"
111
- end
112
- end.map(&:to_i)
113
- total = qsize + retries
114
- #GC.start
115
- Sidekiq.logger.error("RSS: #{Process.rss} Pending: #{total}")
116
- if total == 0
117
- Sidekiq.logger.error("Done")
118
- exit(0)
119
- end
104
+ while true
105
+ sleep 0.2
106
+ qsize = Sidekiq.redis do |conn|
107
+ conn.llen "queue:default"
108
+ end
109
+ total = qsize
110
+ # Sidekiq.logger.error("RSS: #{Process.rss} Pending: #{total}")
111
+ if total == 0
112
+ Sidekiq.logger.error("Done, #{iter * count} jobs in #{Time.now - start} sec")
113
+ Sidekiq.logger.error("Now here's the latency for three jobs")
114
+
115
+ LoadWorker.perform_async(1, Time.now.to_f)
116
+ LoadWorker.perform_async(2, Time.now.to_f)
117
+ LoadWorker.perform_async(3, Time.now.to_f)
118
+
119
+ sleep 0.2
120
+ exit(0)
120
121
  end
121
122
  end
122
123
  end
123
124
 
125
+ def with_latency(latency, &block)
126
+ Sidekiq.logger.error "Simulating #{latency}ms of latency between Sidekiq and redis"
127
+ if latency > 0
128
+ Toxiproxy[:redis].downstream(:latency, latency: latency).apply(&block)
129
+ else
130
+ yield
131
+ end
132
+ end
133
+
124
134
  begin
125
- #RubyProf::exclude_threads = [ Monitoring ]
126
- #RubyProf.start
127
- fire_event(:startup)
128
- #Sidekiq.logger.error "Simulating 1ms of latency between Sidekiq and redis"
129
- #Toxiproxy[:redis].downstream(:latency, latency: 1).apply do
130
- launcher = Sidekiq::Launcher.new(Sidekiq.options)
135
+ # RubyProf::exclude_threads = [ Monitoring ]
136
+ # RubyProf.start
137
+ events = Sidekiq.options[:lifecycle_events][:startup]
138
+ events.each(&:call)
139
+ events.clear
140
+
141
+ with_latency(Integer(ENV.fetch("LATENCY", "1"))) do
142
+ launcher = Sidekiq::Launcher.new(Sidekiq)
131
143
  launcher.run
132
144
 
133
145
  while readable_io = IO.select([self_read])
134
146
  signal = readable_io.first[0].gets.strip
135
147
  handle_signal(launcher, signal)
136
148
  end
137
- #end
149
+ end
138
150
  rescue SystemExit => e
139
- #Sidekiq.logger.error("Profiling...")
140
- #result = RubyProf.stop
141
- #printer = RubyProf::GraphHtmlPrinter.new(result)
142
- #printer.print(File.new("output.html", "w"), :min_percent => 1)
151
+ # Sidekiq.logger.error("Profiling...")
152
+ # result = RubyProf.stop
153
+ # printer = RubyProf::GraphHtmlPrinter.new(result)
154
+ # printer.print(File.new("output.html", "w"), :min_percent => 1)
143
155
  # normal
144
156
  rescue => e
145
157
  raise e if $DEBUG
146
- STDERR.puts e.message
147
- STDERR.puts e.backtrace.join("\n")
158
+ warn e.message
159
+ warn e.backtrace.join("\n")
148
160
  exit 1
149
161
  end
data/bin/sidekiqmon ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "sidekiq/monitor"
4
+
5
+ section = "all"
6
+ section = ARGV[0] if ARGV.size == 1
7
+
8
+ Sidekiq::Monitor::Status.new.display(section)
@@ -0,0 +1,57 @@
1
+ require "rails/generators/named_base"
2
+
3
+ module Sidekiq
4
+ module Generators # :nodoc:
5
+ class JobGenerator < ::Rails::Generators::NamedBase # :nodoc:
6
+ desc "This generator creates a Sidekiq Job in app/sidekiq and a corresponding test"
7
+
8
+ check_class_collision suffix: "Job"
9
+
10
+ def self.default_generator_root
11
+ File.dirname(__FILE__)
12
+ end
13
+
14
+ def create_job_file
15
+ template "job.rb.erb", File.join("app/sidekiq", class_path, "#{file_name}_job.rb")
16
+ end
17
+
18
+ def create_test_file
19
+ return unless test_framework
20
+
21
+ if test_framework == :rspec
22
+ create_job_spec
23
+ else
24
+ create_job_test
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def create_job_spec
31
+ template_file = File.join(
32
+ "spec/sidekiq",
33
+ class_path,
34
+ "#{file_name}_job_spec.rb"
35
+ )
36
+ template "job_spec.rb.erb", template_file
37
+ end
38
+
39
+ def create_job_test
40
+ template_file = File.join(
41
+ "test/sidekiq",
42
+ class_path,
43
+ "#{file_name}_job_test.rb"
44
+ )
45
+ template "job_test.rb.erb", template_file
46
+ end
47
+
48
+ def file_name
49
+ @_file_name ||= super.sub(/_?job\z/i, "")
50
+ end
51
+
52
+ def test_framework
53
+ ::Rails.application.config.generators.options[:rails][:test_framework]
54
+ end
55
+ end
56
+ end
57
+ 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
@@ -1,6 +1,6 @@
1
1
  require 'rails_helper'
2
2
  <% module_namespacing do -%>
3
- RSpec.describe <%= class_name %>Worker, type: :worker do
3
+ RSpec.describe <%= class_name %>Job, type: :job do
4
4
  pending "add some examples to (or delete) #{__FILE__}"
5
5
  end
6
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