sidekiq 4.2.2 → 6.3.1

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 (138) hide show
  1. checksums.yaml +5 -5
  2. data/Changes.md +516 -0
  3. data/LICENSE +2 -2
  4. data/README.md +23 -36
  5. data/bin/sidekiq +26 -2
  6. data/bin/sidekiqload +28 -38
  7. data/bin/sidekiqmon +8 -0
  8. data/lib/generators/sidekiq/templates/worker_spec.rb.erb +1 -1
  9. data/lib/generators/sidekiq/templates/worker_test.rb.erb +2 -2
  10. data/lib/generators/sidekiq/worker_generator.rb +21 -13
  11. data/lib/sidekiq/api.rb +401 -243
  12. data/lib/sidekiq/cli.rb +228 -212
  13. data/lib/sidekiq/client.rb +76 -53
  14. data/lib/sidekiq/delay.rb +41 -0
  15. data/lib/sidekiq/exception_handler.rb +12 -16
  16. data/lib/sidekiq/extensions/action_mailer.rb +13 -22
  17. data/lib/sidekiq/extensions/active_record.rb +13 -10
  18. data/lib/sidekiq/extensions/class_methods.rb +14 -11
  19. data/lib/sidekiq/extensions/generic_proxy.rb +12 -4
  20. data/lib/sidekiq/fetch.rb +39 -31
  21. data/lib/sidekiq/job.rb +13 -0
  22. data/lib/sidekiq/job_logger.rb +63 -0
  23. data/lib/sidekiq/job_retry.rb +259 -0
  24. data/lib/sidekiq/launcher.rb +170 -71
  25. data/lib/sidekiq/logger.rb +166 -0
  26. data/lib/sidekiq/manager.rb +17 -20
  27. data/lib/sidekiq/middleware/chain.rb +20 -8
  28. data/lib/sidekiq/middleware/current_attributes.rb +52 -0
  29. data/lib/sidekiq/middleware/i18n.rb +5 -7
  30. data/lib/sidekiq/monitor.rb +133 -0
  31. data/lib/sidekiq/paginator.rb +18 -14
  32. data/lib/sidekiq/processor.rb +169 -78
  33. data/lib/sidekiq/rails.rb +41 -36
  34. data/lib/sidekiq/redis_connection.rb +65 -20
  35. data/lib/sidekiq/scheduled.rb +85 -34
  36. data/lib/sidekiq/sd_notify.rb +149 -0
  37. data/lib/sidekiq/systemd.rb +24 -0
  38. data/lib/sidekiq/testing/inline.rb +2 -1
  39. data/lib/sidekiq/testing.rb +52 -26
  40. data/lib/sidekiq/util.rb +48 -15
  41. data/lib/sidekiq/version.rb +2 -1
  42. data/lib/sidekiq/web/action.rb +15 -17
  43. data/lib/sidekiq/web/application.rb +114 -92
  44. data/lib/sidekiq/web/csrf_protection.rb +180 -0
  45. data/lib/sidekiq/web/helpers.rb +151 -83
  46. data/lib/sidekiq/web/router.rb +27 -19
  47. data/lib/sidekiq/web.rb +85 -76
  48. data/lib/sidekiq/worker.rb +233 -43
  49. data/lib/sidekiq.rb +88 -64
  50. data/sidekiq.gemspec +24 -22
  51. data/web/assets/images/apple-touch-icon.png +0 -0
  52. data/web/assets/javascripts/application.js +86 -59
  53. data/web/assets/javascripts/dashboard.js +81 -85
  54. data/web/assets/stylesheets/application-dark.css +147 -0
  55. data/web/assets/stylesheets/application-rtl.css +242 -0
  56. data/web/assets/stylesheets/application.css +319 -141
  57. data/web/assets/stylesheets/bootstrap-rtl.min.css +9 -0
  58. data/web/assets/stylesheets/bootstrap.css +2 -2
  59. data/web/locales/ar.yml +87 -0
  60. data/web/locales/de.yml +14 -2
  61. data/web/locales/en.yml +8 -1
  62. data/web/locales/es.yml +22 -5
  63. data/web/locales/fa.yml +80 -0
  64. data/web/locales/fr.yml +10 -3
  65. data/web/locales/he.yml +79 -0
  66. data/web/locales/ja.yml +12 -4
  67. data/web/locales/lt.yml +83 -0
  68. data/web/locales/pl.yml +4 -4
  69. data/web/locales/ru.yml +4 -0
  70. data/web/locales/ur.yml +80 -0
  71. data/web/locales/vi.yml +83 -0
  72. data/web/views/_footer.erb +5 -2
  73. data/web/views/_job_info.erb +4 -3
  74. data/web/views/_nav.erb +4 -18
  75. data/web/views/_paging.erb +1 -1
  76. data/web/views/_poll_link.erb +2 -5
  77. data/web/views/_summary.erb +7 -7
  78. data/web/views/busy.erb +60 -22
  79. data/web/views/dashboard.erb +23 -15
  80. data/web/views/dead.erb +3 -3
  81. data/web/views/layout.erb +14 -3
  82. data/web/views/morgue.erb +19 -12
  83. data/web/views/queue.erb +24 -14
  84. data/web/views/queues.erb +14 -4
  85. data/web/views/retries.erb +22 -13
  86. data/web/views/retry.erb +4 -4
  87. data/web/views/scheduled.erb +7 -4
  88. metadata +44 -194
  89. data/.github/contributing.md +0 -32
  90. data/.github/issue_template.md +0 -4
  91. data/.gitignore +0 -12
  92. data/.travis.yml +0 -12
  93. data/3.0-Upgrade.md +0 -70
  94. data/4.0-Upgrade.md +0 -53
  95. data/COMM-LICENSE +0 -95
  96. data/Ent-Changes.md +0 -146
  97. data/Gemfile +0 -29
  98. data/Pro-2.0-Upgrade.md +0 -138
  99. data/Pro-3.0-Upgrade.md +0 -44
  100. data/Pro-Changes.md +0 -570
  101. data/Rakefile +0 -9
  102. data/bin/sidekiqctl +0 -99
  103. data/code_of_conduct.md +0 -50
  104. data/lib/sidekiq/core_ext.rb +0 -106
  105. data/lib/sidekiq/logging.rb +0 -106
  106. data/lib/sidekiq/middleware/server/active_record.rb +0 -13
  107. data/lib/sidekiq/middleware/server/logging.rb +0 -40
  108. data/lib/sidekiq/middleware/server/retry_jobs.rb +0 -205
  109. data/test/config.yml +0 -9
  110. data/test/env_based_config.yml +0 -11
  111. data/test/fake_env.rb +0 -1
  112. data/test/fixtures/en.yml +0 -2
  113. data/test/helper.rb +0 -75
  114. data/test/test_actors.rb +0 -138
  115. data/test/test_api.rb +0 -528
  116. data/test/test_cli.rb +0 -418
  117. data/test/test_client.rb +0 -266
  118. data/test/test_exception_handler.rb +0 -56
  119. data/test/test_extensions.rb +0 -127
  120. data/test/test_fetch.rb +0 -50
  121. data/test/test_launcher.rb +0 -95
  122. data/test/test_logging.rb +0 -35
  123. data/test/test_manager.rb +0 -50
  124. data/test/test_middleware.rb +0 -158
  125. data/test/test_processor.rb +0 -201
  126. data/test/test_rails.rb +0 -22
  127. data/test/test_redis_connection.rb +0 -132
  128. data/test/test_retry.rb +0 -326
  129. data/test/test_retry_exhausted.rb +0 -149
  130. data/test/test_scheduled.rb +0 -115
  131. data/test/test_scheduling.rb +0 -50
  132. data/test/test_sidekiq.rb +0 -107
  133. data/test/test_testing.rb +0 -143
  134. data/test/test_testing_fake.rb +0 -357
  135. data/test/test_testing_inline.rb +0 -94
  136. data/test/test_util.rb +0 -13
  137. data/test/test_web.rb +0 -666
  138. data/test/test_web_helpers.rb +0 -54
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,106 +0,0 @@
1
- # frozen_string_literal: true
2
- begin
3
- require 'active_support/core_ext/class/attribute'
4
- rescue LoadError
5
-
6
- # A dumbed down version of ActiveSupport's
7
- # Class#class_attribute helper.
8
- class Class
9
- def class_attribute(*attrs)
10
- instance_writer = true
11
-
12
- attrs.each do |name|
13
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
14
- def self.#{name}() nil end
15
- def self.#{name}?() !!#{name} end
16
-
17
- def self.#{name}=(val)
18
- singleton_class.class_eval do
19
- define_method(:#{name}) { val }
20
- end
21
-
22
- if singleton_class?
23
- class_eval do
24
- def #{name}
25
- defined?(@#{name}) ? @#{name} : singleton_class.#{name}
26
- end
27
- end
28
- end
29
- val
30
- end
31
-
32
- def #{name}
33
- defined?(@#{name}) ? @#{name} : self.class.#{name}
34
- end
35
-
36
- def #{name}?
37
- !!#{name}
38
- end
39
- RUBY
40
-
41
- attr_writer name if instance_writer
42
- end
43
- end
44
-
45
- private
46
- def singleton_class?
47
- ancestors.first != self
48
- end
49
- end
50
- end
51
-
52
- begin
53
- require 'active_support/core_ext/hash/keys'
54
- require 'active_support/core_ext/hash/deep_merge'
55
- rescue LoadError
56
- class Hash
57
- def stringify_keys
58
- keys.each do |key|
59
- self[key.to_s] = delete(key)
60
- end
61
- self
62
- end if !{}.respond_to?(:stringify_keys)
63
-
64
- def symbolize_keys
65
- keys.each do |key|
66
- self[(key.to_sym rescue key) || key] = delete(key)
67
- end
68
- self
69
- end if !{}.respond_to?(:symbolize_keys)
70
-
71
- def deep_merge(other_hash, &block)
72
- dup.deep_merge!(other_hash, &block)
73
- end if !{}.respond_to?(:deep_merge)
74
-
75
- def deep_merge!(other_hash, &block)
76
- other_hash.each_pair do |k,v|
77
- tv = self[k]
78
- if tv.is_a?(Hash) && v.is_a?(Hash)
79
- self[k] = tv.deep_merge(v, &block)
80
- else
81
- self[k] = block && tv ? block.call(k, tv, v) : v
82
- end
83
- end
84
- self
85
- end if !{}.respond_to?(:deep_merge!)
86
- end
87
- end
88
-
89
- begin
90
- require 'active_support/core_ext/string/inflections'
91
- rescue LoadError
92
- class String
93
- def constantize
94
- names = self.split('::')
95
- names.shift if names.empty? || names.first.empty?
96
-
97
- constant = Object
98
- names.each do |name|
99
- constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
100
- end
101
- constant
102
- end
103
- end if !"".respond_to?(:constantize)
104
- end
105
-
106
-
@@ -1,106 +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-#{Thread.current.object_id.to_s(36)}#{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-#{Thread.current.object_id.to_s(36)}#{context} #{severity}: #{message}\n"
26
- end
27
- end
28
-
29
- def self.with_context(msg)
30
- Thread.current[:sidekiq_context] ||= []
31
- Thread.current[:sidekiq_context] << msg
32
- yield
33
- ensure
34
- Thread.current[:sidekiq_context].pop
35
- end
36
-
37
- def self.initialize_logger(log_target = STDOUT)
38
- oldlogger = defined?(@logger) ? @logger : nil
39
- @logger = Logger.new(log_target)
40
- @logger.level = Logger::INFO
41
- @logger.formatter = ENV['DYNO'] ? WithoutTimestamp.new : Pretty.new
42
- oldlogger.close if oldlogger && !$TESTING # don't want to close testing's STDOUT logging
43
- @logger
44
- end
45
-
46
- def self.logger
47
- defined?(@logger) ? @logger : initialize_logger
48
- end
49
-
50
- def self.logger=(log)
51
- @logger = (log ? log : Logger.new(File::NULL))
52
- end
53
-
54
- # This reopens ALL logfiles in the process that have been rotated
55
- # using logrotate(8) (without copytruncate) or similar tools.
56
- # A +File+ object is considered for reopening if it is:
57
- # 1) opened with the O_APPEND and O_WRONLY flags
58
- # 2) the current open file handle does not match its original open path
59
- # 3) unbuffered (as far as userspace buffering goes, not O_SYNC)
60
- # Returns the number of files reopened
61
- def self.reopen_logs
62
- to_reopen = []
63
- append_flags = File::WRONLY | File::APPEND
64
-
65
- ObjectSpace.each_object(File) do |fp|
66
- begin
67
- if !fp.closed? && fp.stat.file? && fp.sync && (fp.fcntl(Fcntl::F_GETFL) & append_flags) == append_flags
68
- to_reopen << fp
69
- end
70
- rescue IOError, Errno::EBADF
71
- end
72
- end
73
-
74
- nr = 0
75
- to_reopen.each do |fp|
76
- orig_st = begin
77
- fp.stat
78
- rescue IOError, Errno::EBADF
79
- next
80
- end
81
-
82
- begin
83
- b = File.stat(fp.path)
84
- next if orig_st.ino == b.ino && orig_st.dev == b.dev
85
- rescue Errno::ENOENT
86
- end
87
-
88
- begin
89
- File.open(fp.path, 'a') { |tmpfp| fp.reopen(tmpfp) }
90
- fp.sync = true
91
- nr += 1
92
- rescue IOError, Errno::EBADF
93
- # not much we can do...
94
- end
95
- end
96
- nr
97
- rescue RuntimeError => ex
98
- # RuntimeError: ObjectSpace is disabled; each_object will only work with Class, pass -X+O to enable
99
- puts "Unable to reopen logs: #{ex.message}"
100
- end
101
-
102
- def logger
103
- Sidekiq::Logging.logger
104
- end
105
- end
106
- end
@@ -1,13 +0,0 @@
1
- module Sidekiq
2
- module Middleware
3
- module Server
4
- class ActiveRecord
5
- def call(*args)
6
- yield
7
- ensure
8
- ::ActiveRecord::Base.clear_active_connections!
9
- end
10
- end
11
- end
12
- end
13
- end
@@ -1,40 +0,0 @@
1
- module Sidekiq
2
- module Middleware
3
- module Server
4
- class Logging
5
-
6
- def call(worker, item, queue)
7
- Sidekiq::Logging.with_context(log_context(worker, item)) do
8
- begin
9
- start = Time.now
10
- logger.info("start".freeze)
11
- yield
12
- logger.info("done: #{elapsed(start)} sec")
13
- rescue Exception
14
- logger.info("fail: #{elapsed(start)} sec")
15
- raise
16
- end
17
- end
18
- end
19
-
20
- private
21
-
22
- # If we're using a wrapper class, like ActiveJob, use the "wrapped"
23
- # attribute to expose the underlying thing.
24
- def log_context(worker, item)
25
- klass = item['wrapped'.freeze] || worker.class.to_s
26
- "#{klass} JID-#{item['jid'.freeze]}#{" BID-#{item['bid'.freeze]}" if item['bid'.freeze]}"
27
- end
28
-
29
- def elapsed(start)
30
- (Time.now - start).round(3)
31
- end
32
-
33
- def logger
34
- Sidekiq.logger
35
- end
36
- end
37
- end
38
- end
39
- end
40
-
@@ -1,205 +0,0 @@
1
- require 'sidekiq/scheduled'
2
- require 'sidekiq/api'
3
-
4
- module Sidekiq
5
- module Middleware
6
- module Server
7
- ##
8
- # Automatically retry jobs that fail in Sidekiq.
9
- # Sidekiq's retry support assumes a typical development lifecycle:
10
- #
11
- # 0. Push some code changes with a bug in it.
12
- # 1. Bug causes job processing to fail, Sidekiq's middleware captures
13
- # the job and pushes it onto a retry queue.
14
- # 2. Sidekiq retries jobs in the retry queue multiple times with
15
- # an exponential delay, the job continues to fail.
16
- # 3. After a few days, a developer deploys a fix. The job is
17
- # reprocessed successfully.
18
- # 4. Once retries are exhausted, Sidekiq will give up and move the
19
- # job to the Dead Job Queue (aka morgue) where it must be dealt with
20
- # manually in the Web UI.
21
- # 5. After 6 months on the DJQ, Sidekiq will discard the job.
22
- #
23
- # A job looks like:
24
- #
25
- # { 'class' => 'HardWorker', 'args' => [1, 2, 'foo'], 'retry' => true }
26
- #
27
- # The 'retry' option also accepts a number (in place of 'true'):
28
- #
29
- # { 'class' => 'HardWorker', 'args' => [1, 2, 'foo'], 'retry' => 5 }
30
- #
31
- # The job will be retried this number of times before giving up. (If simply
32
- # 'true', Sidekiq retries 25 times)
33
- #
34
- # We'll add a bit more data to the job to support retries:
35
- #
36
- # * 'queue' - the queue to use
37
- # * 'retry_count' - number of times we've retried so far.
38
- # * 'error_message' - the message from the exception
39
- # * 'error_class' - the exception class
40
- # * 'failed_at' - the first time it failed
41
- # * 'retried_at' - the last time it was retried
42
- # * 'backtrace' - the number of lines of error backtrace to store
43
- #
44
- # We don't store the backtrace by default as that can add a lot of overhead
45
- # to the job and everyone is using an error service, right?
46
- #
47
- # The default number of retry attempts is 25 which works out to about 3 weeks
48
- # of retries. You can pass a value for the max number of retry attempts when
49
- # adding the middleware using the options hash:
50
- #
51
- # Sidekiq.configure_server do |config|
52
- # config.server_middleware do |chain|
53
- # chain.add Sidekiq::Middleware::Server::RetryJobs, :max_retries => 7
54
- # end
55
- # end
56
- #
57
- # or limit the number of retries for a particular worker with:
58
- #
59
- # class MyWorker
60
- # include Sidekiq::Worker
61
- # sidekiq_options :retry => 10
62
- # end
63
- #
64
- class RetryJobs
65
- include Sidekiq::Util
66
-
67
- DEFAULT_MAX_RETRY_ATTEMPTS = 25
68
-
69
- def initialize(options = {})
70
- @max_retries = options.fetch(:max_retries, DEFAULT_MAX_RETRY_ATTEMPTS)
71
- end
72
-
73
- def call(worker, msg, queue)
74
- yield
75
- rescue Sidekiq::Shutdown
76
- # ignore, will be pushed back onto queue during hard_shutdown
77
- raise
78
- rescue Exception => e
79
- # ignore, will be pushed back onto queue during hard_shutdown
80
- raise Sidekiq::Shutdown if exception_caused_by_shutdown?(e)
81
-
82
- raise e unless msg['retry']
83
- attempt_retry(worker, msg, queue, e)
84
- end
85
-
86
- private
87
-
88
- def attempt_retry(worker, msg, queue, exception)
89
- max_retry_attempts = retry_attempts_from(msg['retry'], @max_retries)
90
-
91
- msg['queue'] = if msg['retry_queue']
92
- msg['retry_queue']
93
- else
94
- queue
95
- end
96
-
97
- # App code can stuff all sorts of crazy binary data into the error message
98
- # that won't convert to JSON.
99
- m = exception.message.to_s[0, 10_000]
100
- if m.respond_to?(:scrub!)
101
- m.force_encoding("utf-8")
102
- m.scrub!
103
- end
104
-
105
- msg['error_message'] = m
106
- msg['error_class'] = exception.class.name
107
- count = if msg['retry_count']
108
- msg['retried_at'] = Time.now.to_f
109
- msg['retry_count'] += 1
110
- else
111
- msg['failed_at'] = Time.now.to_f
112
- msg['retry_count'] = 0
113
- end
114
-
115
- if msg['backtrace'] == true
116
- msg['error_backtrace'] = exception.backtrace
117
- elsif !msg['backtrace']
118
- # do nothing
119
- elsif msg['backtrace'].to_i != 0
120
- msg['error_backtrace'] = exception.backtrace[0...msg['backtrace'].to_i]
121
- end
122
-
123
- if count < max_retry_attempts
124
- delay = delay_for(worker, count, exception)
125
- logger.debug { "Failure! Retry #{count} in #{delay} seconds" }
126
- retry_at = Time.now.to_f + delay
127
- payload = Sidekiq.dump_json(msg)
128
- Sidekiq.redis do |conn|
129
- conn.zadd('retry', retry_at.to_s, payload)
130
- end
131
- else
132
- # Goodbye dear message, you (re)tried your best I'm sure.
133
- retries_exhausted(worker, msg, exception)
134
- end
135
-
136
- raise exception
137
- end
138
-
139
- def retries_exhausted(worker, msg, exception)
140
- logger.debug { "Retries exhausted for job" }
141
- begin
142
- block = worker.sidekiq_retries_exhausted_block || Sidekiq.default_retries_exhausted
143
- block.call(msg, exception) if block
144
- rescue => e
145
- handle_exception(e, { context: "Error calling retries_exhausted for #{worker.class}", job: msg })
146
- end
147
-
148
- send_to_morgue(msg) unless msg['dead'] == false
149
- end
150
-
151
- def send_to_morgue(msg)
152
- Sidekiq.logger.info { "Adding dead #{msg['class']} job #{msg['jid']}" }
153
- payload = Sidekiq.dump_json(msg)
154
- now = Time.now.to_f
155
- Sidekiq.redis do |conn|
156
- conn.multi do
157
- conn.zadd('dead', now, payload)
158
- conn.zremrangebyscore('dead', '-inf', now - DeadSet.timeout)
159
- conn.zremrangebyrank('dead', 0, -DeadSet.max_jobs)
160
- end
161
- end
162
- end
163
-
164
- def retry_attempts_from(msg_retry, default)
165
- if msg_retry.is_a?(Fixnum)
166
- msg_retry
167
- else
168
- default
169
- end
170
- end
171
-
172
- def delay_for(worker, count, exception)
173
- worker.sidekiq_retry_in_block? && retry_in(worker, count, exception) || seconds_to_delay(count)
174
- end
175
-
176
- # delayed_job uses the same basic formula
177
- def seconds_to_delay(count)
178
- (count ** 4) + 15 + (rand(30)*(count+1))
179
- end
180
-
181
- def retry_in(worker, count, exception)
182
- begin
183
- worker.sidekiq_retry_in_block.call(count, exception).to_i
184
- rescue Exception => e
185
- handle_exception(e, { context: "Failure scheduling retry using the defined `sidekiq_retry_in` in #{worker.class.name}, falling back to default" })
186
- nil
187
- end
188
- end
189
-
190
- def exception_caused_by_shutdown?(e, checked_causes = [])
191
- # In Ruby 2.1.0 only, check if exception is a result of shutdown.
192
- return false unless defined?(e.cause)
193
-
194
- # Handle circular causes
195
- checked_causes << e.object_id
196
- return false if checked_causes.include?(e.cause.object_id)
197
-
198
- e.cause.instance_of?(Sidekiq::Shutdown) ||
199
- exception_caused_by_shutdown?(e.cause, checked_causes)
200
- end
201
-
202
- end
203
- end
204
- end
205
- end
data/test/config.yml DELETED
@@ -1,9 +0,0 @@
1
- ---
2
- :verbose: false
3
- :require: ./test/fake_env.rb
4
- :pidfile: /tmp/sidekiq-config-test.pid
5
- :logfile: /tmp/sidekiq.log
6
- :concurrency: 50
7
- :queues:
8
- - [<%="very_"%>often, 2]
9
- - [seldom, 1]
@@ -1,11 +0,0 @@
1
- ---
2
- :pidfile: /tmp/sidekiq-config-test.pid
3
- :concurrency: 50
4
- staging:
5
- :verbose: false
6
- :require: ./test/fake_env.rb
7
- :logfile: /tmp/sidekiq.log
8
- :concurrency: 5
9
- :queues:
10
- - [<%="very_"%>often, 2]
11
- - [seldom, 1]
data/test/fake_env.rb DELETED
@@ -1 +0,0 @@
1
- # frozen_string_literal: true
data/test/fixtures/en.yml DELETED
@@ -1,2 +0,0 @@
1
- en:
2
- translated_text: 'Changed text from add locals'
data/test/helper.rb DELETED
@@ -1,75 +0,0 @@
1
- # frozen_string_literal: true
2
- $TESTING = true
3
- # disable minitest/parallel threads
4
- ENV["N"] = "0"
5
-
6
- if ENV["COVERAGE"]
7
- require 'simplecov'
8
- SimpleCov.start do
9
- add_filter "/test/"
10
- add_filter "/myapp/"
11
- end
12
- end
13
- ENV['RACK_ENV'] = ENV['RAILS_ENV'] = 'test'
14
-
15
- trap 'USR1' do
16
- threads = Thread.list
17
-
18
- puts
19
- puts "=" * 80
20
- puts "Received USR1 signal; printing all #{threads.count} thread backtraces."
21
-
22
- threads.each do |thr|
23
- description = thr == Thread.main ? "Main thread" : thr.inspect
24
- puts
25
- puts "#{description} backtrace: "
26
- puts thr.backtrace.join("\n")
27
- end
28
-
29
- puts "=" * 80
30
- end
31
-
32
- begin
33
- require 'pry-byebug'
34
- rescue LoadError
35
- end
36
-
37
- require 'minitest/autorun'
38
-
39
- require 'sidekiq'
40
- require 'sidekiq/util'
41
- Sidekiq.logger.level = Logger::ERROR
42
-
43
- Sidekiq::Test = Minitest::Test
44
-
45
- require 'sidekiq/redis_connection'
46
- REDIS_URL = ENV['REDIS_URL'] || 'redis://localhost/15'
47
- REDIS = Sidekiq::RedisConnection.create(:url => REDIS_URL, :namespace => 'testy')
48
-
49
- Sidekiq.configure_client do |config|
50
- config.redis = { :url => REDIS_URL, :namespace => 'testy' }
51
- end
52
-
53
- def capture_logging(lvl=Logger::INFO)
54
- old = Sidekiq.logger
55
- begin
56
- out = StringIO.new
57
- logger = Logger.new(out)
58
- logger.level = lvl
59
- Sidekiq.logger = logger
60
- yield
61
- out.string
62
- ensure
63
- Sidekiq.logger = old
64
- end
65
- end
66
-
67
- def with_logging(lvl=Logger::DEBUG)
68
- old = Sidekiq.logger.level
69
- begin
70
- Sidekiq.logger.level = lvl
71
- yield
72
- ensure
73
- Sidekiq.logger.level = old
74
- end
75
- end