sidekiq 5.1.1 → 6.5.9

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sidekiq might be problematic. Click here for more details.

Files changed (126) hide show
  1. checksums.yaml +5 -5
  2. data/Changes.md +507 -1
  3. data/LICENSE +3 -3
  4. data/README.md +24 -35
  5. data/bin/sidekiq +27 -3
  6. data/bin/sidekiqload +80 -68
  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 +537 -286
  13. data/lib/sidekiq/cli.rb +243 -240
  14. data/lib/sidekiq/client.rb +82 -85
  15. data/lib/sidekiq/component.rb +65 -0
  16. data/lib/sidekiq/delay.rb +9 -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 +36 -9
  24. data/lib/sidekiq/job_retry.rb +143 -97
  25. data/lib/sidekiq/job_util.rb +71 -0
  26. data/lib/sidekiq/launcher.rb +185 -85
  27. data/lib/sidekiq/logger.rb +156 -0
  28. data/lib/sidekiq/manager.rb +41 -43
  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 +156 -98
  40. data/lib/sidekiq/rails.rb +48 -42
  41. data/lib/sidekiq/redis_client_adapter.rb +154 -0
  42. data/lib/sidekiq/redis_connection.rb +109 -51
  43. data/lib/sidekiq/ring_buffer.rb +29 -0
  44. data/lib/sidekiq/scheduled.rb +133 -41
  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 +72 -62
  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 +127 -76
  53. data/lib/sidekiq/web/csrf_protection.rb +180 -0
  54. data/lib/sidekiq/web/helpers.rb +133 -96
  55. data/lib/sidekiq/web/router.rb +23 -19
  56. data/lib/sidekiq/web.rb +69 -109
  57. data/lib/sidekiq/worker.rb +268 -102
  58. data/lib/sidekiq.rb +175 -66
  59. data/sidekiq.gemspec +23 -23
  60. data/web/assets/images/apple-touch-icon.png +0 -0
  61. data/web/assets/javascripts/application.js +112 -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 +65 -91
  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 +120 -232
  70. data/web/assets/stylesheets/bootstrap.css +2 -2
  71. data/web/locales/ar.yml +9 -2
  72. data/web/locales/de.yml +14 -2
  73. data/web/locales/el.yml +43 -19
  74. data/web/locales/en.yml +14 -1
  75. data/web/locales/es.yml +21 -5
  76. data/web/locales/fr.yml +10 -3
  77. data/web/locales/ja.yml +14 -1
  78. data/web/locales/lt.yml +83 -0
  79. data/web/locales/pl.yml +4 -4
  80. data/web/locales/pt-br.yml +27 -9
  81. data/web/locales/ru.yml +4 -0
  82. data/web/locales/vi.yml +83 -0
  83. data/web/locales/zh-cn.yml +36 -11
  84. data/web/locales/zh-tw.yml +32 -7
  85. data/web/views/_footer.erb +4 -1
  86. data/web/views/_job_info.erb +3 -2
  87. data/web/views/_nav.erb +4 -18
  88. data/web/views/_poll_link.erb +2 -5
  89. data/web/views/_summary.erb +7 -7
  90. data/web/views/busy.erb +61 -22
  91. data/web/views/dashboard.erb +23 -14
  92. data/web/views/dead.erb +3 -3
  93. data/web/views/layout.erb +4 -2
  94. data/web/views/metrics.erb +69 -0
  95. data/web/views/metrics_for_job.erb +87 -0
  96. data/web/views/morgue.erb +9 -6
  97. data/web/views/queue.erb +24 -10
  98. data/web/views/queues.erb +11 -3
  99. data/web/views/retries.erb +14 -7
  100. data/web/views/retry.erb +3 -3
  101. data/web/views/scheduled.erb +5 -2
  102. metadata +62 -135
  103. data/.github/contributing.md +0 -32
  104. data/.github/issue_template.md +0 -11
  105. data/.gitignore +0 -13
  106. data/.travis.yml +0 -14
  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 -95
  111. data/Ent-Changes.md +0 -210
  112. data/Gemfile +0 -8
  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 -716
  117. data/Rakefile +0 -8
  118. data/bin/sidekiqctl +0 -99
  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/exception_handler.rb +0 -29
  123. data/lib/sidekiq/logging.rb +0 -122
  124. data/lib/sidekiq/middleware/server/active_record.rb +0 -22
  125. data/lib/sidekiq/middleware/server/active_record_cache.rb +0 -11
  126. data/lib/sidekiq/util.rb +0 -66
data/bin/sidekiqctl DELETED
@@ -1,99 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'fileutils'
4
-
5
- class Sidekiqctl
6
- DEFAULT_KILL_TIMEOUT = 10
7
-
8
- attr_reader :stage, :pidfile, :kill_timeout
9
-
10
- def self.print_usage
11
- puts "#{File.basename($0)} - stop a Sidekiq process from the command line."
12
- puts
13
- puts "Usage: #{File.basename($0)} <command> <pidfile> <kill_timeout>"
14
- puts " where <command> is either 'quiet' or 'stop'"
15
- puts " <pidfile> is path to a pidfile"
16
- puts " <kill_timeout> is number of seconds to wait until Sidekiq exits"
17
- puts " (default: #{Sidekiqctl::DEFAULT_KILL_TIMEOUT}), after which Sidekiq will be KILL'd"
18
- puts
19
- puts "Be sure to set the kill_timeout LONGER than Sidekiq's -t timeout. If you want"
20
- puts "to wait 60 seconds for jobs to finish, use `sidekiq -t 60` and `sidekiqctl stop"
21
- puts " path_to_pidfile 61`"
22
- puts
23
- end
24
-
25
- def initialize(stage, pidfile, timeout)
26
- @stage = stage
27
- @pidfile = pidfile
28
- @kill_timeout = timeout
29
-
30
- done('No pidfile given', :error) if !pidfile
31
- done("Pidfile #{pidfile} does not exist", :warn) if !File.exist?(pidfile)
32
- done('Invalid pidfile content', :error) if pid == 0
33
-
34
- fetch_process
35
-
36
- begin
37
- send(stage)
38
- rescue NoMethodError
39
- done "Invalid command: #{stage}", :error
40
- end
41
- end
42
-
43
- def fetch_process
44
- Process.kill(0, pid)
45
- rescue Errno::ESRCH
46
- done "Process doesn't exist", :error
47
- # We were not allowed to send a signal, but the process must have existed
48
- # when Process.kill() was called.
49
- rescue Errno::EPERM
50
- return pid
51
- end
52
-
53
- def done(msg, error = nil)
54
- puts msg
55
- exit(exit_signal(error))
56
- end
57
-
58
- def exit_signal(error)
59
- (error == :error) ? 1 : 0
60
- end
61
-
62
- def pid
63
- @pid ||= File.read(pidfile).to_i
64
- end
65
-
66
- def quiet
67
- `kill -TSTP #{pid}`
68
- end
69
-
70
- def stop
71
- `kill -TERM #{pid}`
72
- kill_timeout.times do
73
- begin
74
- Process.kill(0, pid)
75
- rescue Errno::ESRCH
76
- FileUtils.rm_f pidfile
77
- done 'Sidekiq shut down gracefully.'
78
- rescue Errno::EPERM
79
- done 'Not permitted to shut down Sidekiq.'
80
- end
81
- sleep 1
82
- end
83
- `kill -9 #{pid}`
84
- FileUtils.rm_f pidfile
85
- done 'Sidekiq shut down forcefully.'
86
- end
87
- alias_method :shutdown, :stop
88
- end
89
-
90
- if ARGV.length < 2
91
- Sidekiqctl.print_usage
92
- else
93
- stage = ARGV[0]
94
- pidfile = ARGV[1]
95
- timeout = ARGV[2].to_i
96
- timeout = Sidekiqctl::DEFAULT_KILL_TIMEOUT if timeout == 0
97
-
98
- Sidekiqctl.new(stage, pidfile, timeout)
99
- end
data/code_of_conduct.md DELETED
@@ -1,50 +0,0 @@
1
- # Contributor Code of Conduct
2
-
3
- As contributors and maintainers of this project, and in the interest of
4
- fostering an open and welcoming community, we pledge to respect all people who
5
- contribute through reporting issues, posting feature requests, updating
6
- documentation, submitting pull requests or patches, and other activities.
7
-
8
- We are committed to making participation in this project a harassment-free
9
- experience for everyone, regardless of level of experience, gender, gender
10
- identity and expression, sexual orientation, disability, personal appearance,
11
- body size, race, ethnicity, age, religion, or nationality.
12
-
13
- Examples of unacceptable behavior by participants include:
14
-
15
- * The use of sexualized language or imagery
16
- * Personal attacks
17
- * Trolling or insulting/derogatory comments
18
- * Public or private harassment
19
- * Publishing other's private information, such as physical or electronic
20
- addresses, without explicit permission
21
- * Other unethical or unprofessional conduct
22
-
23
- Project maintainers have the right and responsibility to remove, edit, or
24
- reject comments, commits, code, wiki edits, issues, and other contributions
25
- that are not aligned to this Code of Conduct, or to ban temporarily or
26
- permanently any contributor for other behaviors that they deem inappropriate,
27
- threatening, offensive, or harmful.
28
-
29
- By adopting this Code of Conduct, project maintainers commit themselves to
30
- fairly and consistently applying these principles to every aspect of managing
31
- this project. Project maintainers who do not follow or enforce the Code of
32
- Conduct may be permanently removed from the project team.
33
-
34
- This Code of Conduct applies both within project spaces and in public spaces
35
- when an individual is representing the project or its community.
36
-
37
- Instances of abusive, harassing, or otherwise unacceptable behavior may be
38
- reported by contacting the project maintainer at mperham AT gmail.com. All
39
- complaints will be reviewed and investigated and will result in a response that
40
- is deemed necessary and appropriate to the circumstances. Maintainers are
41
- obligated to maintain confidentiality with regard to the reporter of an
42
- incident.
43
-
44
-
45
- This Code of Conduct is adapted from the [Contributor Covenant][homepage],
46
- version 1.3.0, available at
47
- [http://contributor-covenant.org/version/1/3/0/][version]
48
-
49
- [homepage]: http://contributor-covenant.org
50
- [version]: http://contributor-covenant.org/version/1/3/0/
@@ -1,49 +0,0 @@
1
- require 'rails/generators/named_base'
2
-
3
- module Sidekiq
4
- module Generators # :nodoc:
5
- class WorkerGenerator < ::Rails::Generators::NamedBase # :nodoc:
6
- desc 'This generator creates a Sidekiq Worker in app/workers and a corresponding test'
7
-
8
- check_class_collision suffix: 'Worker'
9
-
10
- def self.default_generator_root
11
- File.dirname(__FILE__)
12
- end
13
-
14
- def create_worker_file
15
- template 'worker.rb.erb', File.join('app/workers', class_path, "#{file_name}_worker.rb")
16
- end
17
-
18
- def create_test_file
19
- if defined?(RSpec)
20
- create_worker_spec
21
- else
22
- create_worker_test
23
- end
24
- end
25
-
26
- private
27
-
28
- def create_worker_spec
29
- template_file = File.join(
30
- 'spec/workers',
31
- class_path,
32
- "#{file_name}_worker_spec.rb"
33
- )
34
- template 'worker_spec.rb.erb', template_file
35
- end
36
-
37
- def create_worker_test
38
- template_file = File.join(
39
- 'test/workers',
40
- class_path,
41
- "#{file_name}_worker_test.rb"
42
- )
43
- template 'worker_test.rb.erb', template_file
44
- end
45
-
46
-
47
- end
48
- end
49
- end
@@ -1 +0,0 @@
1
- raise "no longer used, will be removed in 5.1"
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'sidekiq'
3
-
4
- module Sidekiq
5
- module ExceptionHandler
6
-
7
- class Logger
8
- def call(ex, ctxHash)
9
- Sidekiq.logger.warn(Sidekiq.dump_json(ctxHash)) if !ctxHash.empty?
10
- Sidekiq.logger.warn("#{ex.class.name}: #{ex.message}")
11
- Sidekiq.logger.warn(ex.backtrace.join("\n")) unless ex.backtrace.nil?
12
- end
13
-
14
- Sidekiq.error_handlers << Sidekiq::ExceptionHandler::Logger.new
15
- end
16
-
17
- def handle_exception(ex, ctxHash={})
18
- Sidekiq.error_handlers.each do |handler|
19
- begin
20
- handler.call(ex, ctxHash)
21
- rescue => ex
22
- Sidekiq.logger.error "!!! ERROR HANDLER THREW AN ERROR !!!"
23
- Sidekiq.logger.error ex
24
- Sidekiq.logger.error ex.backtrace.join("\n") unless ex.backtrace.nil?
25
- end
26
- end
27
- end
28
- end
29
- end
@@ -1,122 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'time'
3
- require 'logger'
4
- require 'fcntl'
5
-
6
- module Sidekiq
7
- module Logging
8
-
9
- class Pretty < Logger::Formatter
10
- SPACE = " "
11
-
12
- # Provide a call() method that returns the formatted message.
13
- def call(severity, time, program_name, message)
14
- "#{time.utc.iso8601(3)} #{::Process.pid} TID-#{Sidekiq::Logging.tid}#{context} #{severity}: #{message}\n"
15
- end
16
-
17
- def context
18
- c = Thread.current[:sidekiq_context]
19
- " #{c.join(SPACE)}" if c && c.any?
20
- end
21
- end
22
-
23
- class WithoutTimestamp < Pretty
24
- def call(severity, time, program_name, message)
25
- "#{::Process.pid} TID-#{Sidekiq::Logging.tid}#{context} #{severity}: #{message}\n"
26
- end
27
- end
28
-
29
- def self.tid
30
- Thread.current['sidekiq_tid'] ||= (Thread.current.object_id ^ ::Process.pid).to_s(36)
31
- end
32
-
33
- def self.job_hash_context(job_hash)
34
- # If we're using a wrapper class, like ActiveJob, use the "wrapped"
35
- # attribute to expose the underlying thing.
36
- klass = job_hash['wrapped'.freeze] || job_hash["class".freeze]
37
- bid = job_hash['bid'.freeze]
38
- "#{klass} JID-#{job_hash['jid'.freeze]}#{" BID-#{bid}" if bid}"
39
- end
40
-
41
- def self.with_job_hash_context(job_hash, &block)
42
- with_context(job_hash_context(job_hash), &block)
43
- end
44
-
45
- def self.with_context(msg)
46
- Thread.current[:sidekiq_context] ||= []
47
- Thread.current[:sidekiq_context] << msg
48
- yield
49
- ensure
50
- Thread.current[:sidekiq_context].pop
51
- end
52
-
53
- def self.initialize_logger(log_target = STDOUT)
54
- oldlogger = defined?(@logger) ? @logger : nil
55
- @logger = Logger.new(log_target)
56
- @logger.level = Logger::INFO
57
- @logger.formatter = ENV['DYNO'] ? WithoutTimestamp.new : Pretty.new
58
- oldlogger.close if oldlogger && !$TESTING # don't want to close testing's STDOUT logging
59
- @logger
60
- end
61
-
62
- def self.logger
63
- defined?(@logger) ? @logger : initialize_logger
64
- end
65
-
66
- def self.logger=(log)
67
- @logger = (log ? log : Logger.new(File::NULL))
68
- end
69
-
70
- # This reopens ALL logfiles in the process that have been rotated
71
- # using logrotate(8) (without copytruncate) or similar tools.
72
- # A +File+ object is considered for reopening if it is:
73
- # 1) opened with the O_APPEND and O_WRONLY flags
74
- # 2) the current open file handle does not match its original open path
75
- # 3) unbuffered (as far as userspace buffering goes, not O_SYNC)
76
- # Returns the number of files reopened
77
- def self.reopen_logs
78
- to_reopen = []
79
- append_flags = File::WRONLY | File::APPEND
80
-
81
- ObjectSpace.each_object(File) do |fp|
82
- begin
83
- if !fp.closed? && fp.stat.file? && fp.sync && (fp.fcntl(Fcntl::F_GETFL) & append_flags) == append_flags
84
- to_reopen << fp
85
- end
86
- rescue IOError, Errno::EBADF
87
- end
88
- end
89
-
90
- nr = 0
91
- to_reopen.each do |fp|
92
- orig_st = begin
93
- fp.stat
94
- rescue IOError, Errno::EBADF
95
- next
96
- end
97
-
98
- begin
99
- b = File.stat(fp.path)
100
- next if orig_st.ino == b.ino && orig_st.dev == b.dev
101
- rescue Errno::ENOENT
102
- end
103
-
104
- begin
105
- File.open(fp.path, 'a') { |tmpfp| fp.reopen(tmpfp) }
106
- fp.sync = true
107
- nr += 1
108
- rescue IOError, Errno::EBADF
109
- # not much we can do...
110
- end
111
- end
112
- nr
113
- rescue RuntimeError => ex
114
- # RuntimeError: ObjectSpace is disabled; each_object will only work with Class, pass -X+O to enable
115
- puts "Unable to reopen logs: #{ex.message}"
116
- end
117
-
118
- def logger
119
- Sidekiq::Logging.logger
120
- end
121
- end
122
- end
@@ -1,22 +0,0 @@
1
- module Sidekiq
2
- module Middleware
3
- module Server
4
- class ActiveRecord
5
-
6
- def initialize
7
- # With Rails 5+ we must use the Reloader **always**.
8
- # The reloader handles code loading and db connection management.
9
- if ::Rails::VERSION::MAJOR >= 5
10
- raise ArgumentError, "Rails 5 no longer needs or uses the ActiveRecord middleware."
11
- end
12
- end
13
-
14
- def call(*args)
15
- yield
16
- ensure
17
- ::ActiveRecord::Base.clear_active_connections!
18
- end
19
- end
20
- end
21
- end
22
- end
@@ -1,11 +0,0 @@
1
- module Sidekiq
2
- module Middleware
3
- module Server
4
- class ActiveRecordCache
5
- def call(*args, &block)
6
- ::ActiveRecord::Base.cache(&block)
7
- end
8
- end
9
- end
10
- end
11
- end
data/lib/sidekiq/util.rb DELETED
@@ -1,66 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'socket'
3
- require 'securerandom'
4
- require 'sidekiq/exception_handler'
5
-
6
- module Sidekiq
7
- ##
8
- # This module is part of Sidekiq core and not intended for extensions.
9
- #
10
- module Util
11
- include ExceptionHandler
12
-
13
- EXPIRY = 60 * 60 * 24
14
-
15
- def watchdog(last_words)
16
- yield
17
- rescue Exception => ex
18
- handle_exception(ex, { context: last_words })
19
- raise ex
20
- end
21
-
22
- def safe_thread(name, &block)
23
- Thread.new do
24
- Thread.current['sidekiq_label'.freeze] = name
25
- watchdog(name, &block)
26
- end
27
- end
28
-
29
- def logger
30
- Sidekiq.logger
31
- end
32
-
33
- def redis(&block)
34
- Sidekiq.redis(&block)
35
- end
36
-
37
- def hostname
38
- ENV['DYNO'] || Socket.gethostname
39
- end
40
-
41
- def process_nonce
42
- @@process_nonce ||= SecureRandom.hex(6)
43
- end
44
-
45
- def identity
46
- @@identity ||= "#{hostname}:#{$$}:#{process_nonce}"
47
- end
48
-
49
- def fire_event(event, options={})
50
- reverse = options[:reverse]
51
- reraise = options[:reraise]
52
-
53
- arr = Sidekiq.options[:lifecycle_events][event]
54
- arr.reverse! if reverse
55
- arr.each do |block|
56
- begin
57
- block.call
58
- rescue => ex
59
- handle_exception(ex, { context: "Exception during Sidekiq lifecycle event.", event: event })
60
- raise ex if reraise
61
- end
62
- end
63
- arr.clear
64
- end
65
- end
66
- end