sidekiq 4.1.4 → 4.2.10

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 (134) hide show
  1. checksums.yaml +4 -4
  2. data/.github/issue_template.md +6 -1
  3. data/.travis.yml +9 -9
  4. data/Changes.md +100 -0
  5. data/Ent-Changes.md +51 -1
  6. data/Gemfile +6 -6
  7. data/Pro-Changes.md +69 -0
  8. data/README.md +4 -3
  9. data/Rakefile +5 -2
  10. data/bin/sidekiqload +11 -24
  11. data/lib/generators/sidekiq/templates/worker_test.rb.erb +1 -1
  12. data/lib/sidekiq/api.rb +21 -13
  13. data/lib/sidekiq/cli.rb +19 -5
  14. data/lib/sidekiq/core_ext.rb +13 -0
  15. data/lib/sidekiq/launcher.rb +36 -23
  16. data/lib/sidekiq/manager.rb +3 -2
  17. data/lib/sidekiq/middleware/server/logging.rb +8 -17
  18. data/lib/sidekiq/middleware/server/retry_jobs.rb +1 -1
  19. data/lib/sidekiq/processor.rb +31 -16
  20. data/lib/sidekiq/rails.rb +84 -0
  21. data/lib/sidekiq/redis_connection.rb +8 -1
  22. data/lib/sidekiq/scheduled.rb +1 -0
  23. data/lib/sidekiq/testing.rb +10 -2
  24. data/lib/sidekiq/util.rb +2 -1
  25. data/lib/sidekiq/version.rb +1 -1
  26. data/lib/sidekiq/web/action.rb +93 -0
  27. data/lib/sidekiq/web/application.rb +336 -0
  28. data/lib/sidekiq/{web_helpers.rb → web/helpers.rb} +39 -16
  29. data/lib/sidekiq/web/router.rb +100 -0
  30. data/lib/sidekiq/web.rb +119 -184
  31. data/lib/sidekiq/worker.rb +3 -3
  32. data/lib/sidekiq.rb +7 -7
  33. data/sidekiq.gemspec +11 -5
  34. data/web/assets/images/{status-sd8051fd480.png → status.png} +0 -0
  35. data/web/assets/javascripts/application.js +24 -20
  36. data/web/assets/javascripts/dashboard.js +1 -1
  37. data/web/assets/stylesheets/application.css +26 -1
  38. data/web/assets/stylesheets/bootstrap.css +4 -8
  39. data/web/locales/de.yml +1 -1
  40. data/web/locales/fa.yml +79 -0
  41. data/web/views/_footer.erb +1 -1
  42. data/web/views/_job_info.erb +1 -1
  43. data/web/views/busy.erb +2 -2
  44. data/web/views/dashboard.erb +4 -4
  45. data/web/views/dead.erb +1 -1
  46. data/web/views/layout.erb +3 -4
  47. data/web/views/morgue.erb +14 -10
  48. data/web/views/queue.erb +6 -6
  49. data/web/views/queues.erb +3 -3
  50. data/web/views/retries.erb +12 -10
  51. data/web/views/retry.erb +2 -2
  52. data/web/views/scheduled.erb +2 -2
  53. data/web/views/scheduled_job_info.erb +1 -1
  54. metadata +86 -129
  55. data/test/config.yml +0 -9
  56. data/test/env_based_config.yml +0 -11
  57. data/test/fake_env.rb +0 -1
  58. data/test/fixtures/en.yml +0 -2
  59. data/test/helper.rb +0 -75
  60. data/test/test_actors.rb +0 -138
  61. data/test/test_api.rb +0 -528
  62. data/test/test_cli.rb +0 -406
  63. data/test/test_client.rb +0 -266
  64. data/test/test_exception_handler.rb +0 -56
  65. data/test/test_extensions.rb +0 -127
  66. data/test/test_fetch.rb +0 -50
  67. data/test/test_launcher.rb +0 -85
  68. data/test/test_logging.rb +0 -35
  69. data/test/test_manager.rb +0 -50
  70. data/test/test_middleware.rb +0 -158
  71. data/test/test_processor.rb +0 -201
  72. data/test/test_rails.rb +0 -22
  73. data/test/test_redis_connection.rb +0 -132
  74. data/test/test_retry.rb +0 -326
  75. data/test/test_retry_exhausted.rb +0 -149
  76. data/test/test_scheduled.rb +0 -115
  77. data/test/test_scheduling.rb +0 -50
  78. data/test/test_sidekiq.rb +0 -107
  79. data/test/test_testing.rb +0 -143
  80. data/test/test_testing_fake.rb +0 -357
  81. data/test/test_testing_inline.rb +0 -94
  82. data/test/test_util.rb +0 -13
  83. data/test/test_web.rb +0 -614
  84. data/test/test_web_helpers.rb +0 -54
  85. data/web/assets/images/bootstrap/glyphicons-halflings-white.png +0 -0
  86. data/web/assets/images/bootstrap/glyphicons-halflings.png +0 -0
  87. data/web/assets/images/status/active.png +0 -0
  88. data/web/assets/images/status/idle.png +0 -0
  89. data/web/assets/javascripts/locales/README.md +0 -27
  90. data/web/assets/javascripts/locales/jquery.timeago.ar.js +0 -96
  91. data/web/assets/javascripts/locales/jquery.timeago.bg.js +0 -18
  92. data/web/assets/javascripts/locales/jquery.timeago.bs.js +0 -49
  93. data/web/assets/javascripts/locales/jquery.timeago.ca.js +0 -18
  94. data/web/assets/javascripts/locales/jquery.timeago.cs.js +0 -18
  95. data/web/assets/javascripts/locales/jquery.timeago.cy.js +0 -20
  96. data/web/assets/javascripts/locales/jquery.timeago.da.js +0 -18
  97. data/web/assets/javascripts/locales/jquery.timeago.de.js +0 -18
  98. data/web/assets/javascripts/locales/jquery.timeago.el.js +0 -18
  99. data/web/assets/javascripts/locales/jquery.timeago.en-short.js +0 -20
  100. data/web/assets/javascripts/locales/jquery.timeago.en.js +0 -20
  101. data/web/assets/javascripts/locales/jquery.timeago.es.js +0 -18
  102. data/web/assets/javascripts/locales/jquery.timeago.et.js +0 -18
  103. data/web/assets/javascripts/locales/jquery.timeago.fa.js +0 -22
  104. data/web/assets/javascripts/locales/jquery.timeago.fi.js +0 -28
  105. data/web/assets/javascripts/locales/jquery.timeago.fr-short.js +0 -16
  106. data/web/assets/javascripts/locales/jquery.timeago.fr.js +0 -17
  107. data/web/assets/javascripts/locales/jquery.timeago.he.js +0 -18
  108. data/web/assets/javascripts/locales/jquery.timeago.hr.js +0 -49
  109. data/web/assets/javascripts/locales/jquery.timeago.hu.js +0 -18
  110. data/web/assets/javascripts/locales/jquery.timeago.hy.js +0 -18
  111. data/web/assets/javascripts/locales/jquery.timeago.id.js +0 -18
  112. data/web/assets/javascripts/locales/jquery.timeago.it.js +0 -16
  113. data/web/assets/javascripts/locales/jquery.timeago.ja.js +0 -19
  114. data/web/assets/javascripts/locales/jquery.timeago.ko.js +0 -17
  115. data/web/assets/javascripts/locales/jquery.timeago.lt.js +0 -20
  116. data/web/assets/javascripts/locales/jquery.timeago.mk.js +0 -20
  117. data/web/assets/javascripts/locales/jquery.timeago.nb.js +0 -18
  118. data/web/assets/javascripts/locales/jquery.timeago.nl.js +0 -20
  119. data/web/assets/javascripts/locales/jquery.timeago.pl.js +0 -31
  120. data/web/assets/javascripts/locales/jquery.timeago.pt-br.js +0 -16
  121. data/web/assets/javascripts/locales/jquery.timeago.pt.js +0 -16
  122. data/web/assets/javascripts/locales/jquery.timeago.ro.js +0 -18
  123. data/web/assets/javascripts/locales/jquery.timeago.rs.js +0 -49
  124. data/web/assets/javascripts/locales/jquery.timeago.ru.js +0 -34
  125. data/web/assets/javascripts/locales/jquery.timeago.sk.js +0 -18
  126. data/web/assets/javascripts/locales/jquery.timeago.sl.js +0 -44
  127. data/web/assets/javascripts/locales/jquery.timeago.sv.js +0 -18
  128. data/web/assets/javascripts/locales/jquery.timeago.th.js +0 -20
  129. data/web/assets/javascripts/locales/jquery.timeago.tr.js +0 -16
  130. data/web/assets/javascripts/locales/jquery.timeago.uk.js +0 -34
  131. data/web/assets/javascripts/locales/jquery.timeago.uz.js +0 -19
  132. data/web/assets/javascripts/locales/jquery.timeago.zh-cn.js +0 -20
  133. data/web/assets/javascripts/locales/jquery.timeago.zh-tw.js +0 -20
  134. data/web/views/_poll_js.erb +0 -5
@@ -1,201 +0,0 @@
1
- # frozen_string_literal: true
2
- require_relative 'helper'
3
- require 'sidekiq/fetch'
4
- require 'sidekiq/cli'
5
- require 'sidekiq/processor'
6
-
7
- class TestProcessor < Sidekiq::Test
8
- TestException = Class.new(StandardError)
9
- TEST_EXCEPTION = TestException.new("kerboom!")
10
-
11
- describe 'processor' do
12
- before do
13
- $invokes = 0
14
- @mgr = Minitest::Mock.new
15
- @mgr.expect(:options, {:queues => ['default']})
16
- @mgr.expect(:options, {:queues => ['default']})
17
- @processor = ::Sidekiq::Processor.new(@mgr)
18
- end
19
-
20
- class MockWorker
21
- include Sidekiq::Worker
22
- def perform(args)
23
- raise TEST_EXCEPTION if args == 'boom'
24
- args.pop if args.is_a? Array
25
- $invokes += 1
26
- end
27
- end
28
-
29
- def work(msg, queue='queue:default')
30
- Sidekiq::BasicFetch::UnitOfWork.new(queue, msg)
31
- end
32
-
33
- it 'processes as expected' do
34
- msg = Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => ['myarg'] })
35
- @processor.process(work(msg))
36
- assert_equal 1, $invokes
37
- end
38
-
39
- it 'executes a worker as expected' do
40
- worker = Minitest::Mock.new
41
- worker.expect(:perform, nil, [1, 2, 3])
42
- @processor.execute_job(worker, [1, 2, 3])
43
- end
44
-
45
- it 're-raises exceptions after handling' do
46
- msg = Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => ['boom'] })
47
- re_raise = false
48
-
49
- begin
50
- @processor.process(work(msg))
51
- flunk "Expected exception"
52
- rescue TestException
53
- re_raise = true
54
- end
55
-
56
- assert_equal 0, $invokes
57
- assert re_raise, "does not re-raise exceptions after handling"
58
- end
59
-
60
- it 'does not modify original arguments' do
61
- msg = { 'class' => MockWorker.to_s, 'args' => [['myarg']] }
62
- msgstr = Sidekiq.dump_json(msg)
63
- @mgr.expect(:processor_done, nil, [@processor])
64
- @processor.process(work(msgstr))
65
- assert_equal [['myarg']], msg['args']
66
- end
67
-
68
- describe 'acknowledgement' do
69
- class ExceptionRaisingMiddleware
70
- def initialize(raise_before_yield, raise_after_yield, skip)
71
- @raise_before_yield = raise_before_yield
72
- @raise_after_yield = raise_after_yield
73
- @skip = skip
74
- end
75
-
76
- def call(worker, item, queue)
77
- raise TEST_EXCEPTION if @raise_before_yield
78
- yield unless @skip
79
- raise TEST_EXCEPTION if @raise_after_yield
80
- end
81
- end
82
-
83
- let(:raise_before_yield) { false }
84
- let(:raise_after_yield) { false }
85
- let(:skip_job) { false }
86
- let(:worker_args) { ['myarg'] }
87
- let(:work) { MiniTest::Mock.new }
88
-
89
- before do
90
- work.expect(:queue_name, 'queue:default')
91
- work.expect(:job, Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => worker_args }))
92
- Sidekiq.server_middleware do |chain|
93
- chain.prepend ExceptionRaisingMiddleware, raise_before_yield, raise_after_yield, skip_job
94
- end
95
- end
96
-
97
- after do
98
- Sidekiq.server_middleware do |chain|
99
- chain.remove ExceptionRaisingMiddleware
100
- end
101
- work.verify
102
- end
103
-
104
- describe 'middleware throws an exception before processing the work' do
105
- let(:raise_before_yield) { true }
106
-
107
- it 'does not ack' do
108
- begin
109
- @processor.process(work)
110
- flunk "Expected #process to raise exception"
111
- rescue TestException
112
- end
113
- end
114
- end
115
-
116
- describe 'middleware throws an exception after processing the work' do
117
- let(:raise_after_yield) { true }
118
-
119
- it 'acks the job' do
120
- work.expect(:acknowledge, nil)
121
- begin
122
- @processor.process(work)
123
- flunk "Expected #process to raise exception"
124
- rescue TestException
125
- end
126
- end
127
- end
128
-
129
- describe 'middleware decides to skip work' do
130
- let(:skip_job) { true }
131
-
132
- it 'acks the job' do
133
- work.expect(:acknowledge, nil)
134
- @mgr.expect(:processor_done, nil, [@processor])
135
- @processor.process(work)
136
- end
137
- end
138
-
139
- describe 'worker raises an exception' do
140
- let(:worker_args) { ['boom'] }
141
-
142
- it 'acks the job' do
143
- work.expect(:acknowledge, nil)
144
- begin
145
- @processor.process(work)
146
- flunk "Expected #process to raise exception"
147
- rescue TestException
148
- end
149
- end
150
- end
151
-
152
- describe 'everything goes well' do
153
- it 'acks the job' do
154
- work.expect(:acknowledge, nil)
155
- @mgr.expect(:processor_done, nil, [@processor])
156
- @processor.process(work)
157
- end
158
- end
159
- end
160
-
161
- describe 'stats' do
162
- before do
163
- Sidekiq.redis {|c| c.flushdb }
164
- end
165
-
166
- describe 'when successful' do
167
- let(:processed_today_key) { "stat:processed:#{Time.now.utc.strftime("%Y-%m-%d")}" }
168
-
169
- def successful_job
170
- msg = Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => ['myarg'] })
171
- @mgr.expect(:processor_done, nil, [@processor])
172
- @processor.process(work(msg))
173
- end
174
-
175
- it 'increments processed stat' do
176
- Sidekiq::Processor::PROCESSED.value = 0
177
- successful_job
178
- assert_equal 1, Sidekiq::Processor::PROCESSED.value
179
- end
180
- end
181
-
182
- describe 'when failed' do
183
- let(:failed_today_key) { "stat:failed:#{Time.now.utc.strftime("%Y-%m-%d")}" }
184
-
185
- def failed_job
186
- msg = Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => ['boom'] })
187
- begin
188
- @processor.process(work(msg))
189
- rescue TestException
190
- end
191
- end
192
-
193
- it 'increments failed stat' do
194
- Sidekiq::Processor::FAILURE.value = 0
195
- failed_job
196
- assert_equal 1, Sidekiq::Processor::FAILURE.value
197
- end
198
- end
199
- end
200
- end
201
- end
data/test/test_rails.rb DELETED
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
- require_relative 'helper'
3
-
4
- $HAS_AJ = true
5
- begin
6
- require 'active_job'
7
- rescue LoadError
8
- $HAS_AJ = false
9
- end
10
-
11
- class TestRails < Sidekiq::Test
12
-
13
- describe 'ActiveJob' do
14
- it 'does not allow Sidekiq::Worker in AJ::Base classes' do
15
- ex = assert_raises ArgumentError do
16
- c = Class.new(ActiveJob::Base)
17
- c.send(:include, Sidekiq::Worker)
18
- end
19
- assert_includes ex.message, "cannot include"
20
- end if $HAS_AJ
21
- end
22
- end
@@ -1,132 +0,0 @@
1
- # frozen_string_literal: true
2
- require_relative 'helper'
3
-
4
- class TestRedisConnection < Sidekiq::Test
5
-
6
- describe ".create" do
7
-
8
- it "creates a pooled redis connection" do
9
- pool = Sidekiq::RedisConnection.create
10
- assert_equal Redis, pool.checkout.class
11
- end
12
-
13
- describe "network_timeout" do
14
- it "sets a custom network_timeout if specified" do
15
- pool = Sidekiq::RedisConnection.create(:network_timeout => 8)
16
- redis = pool.checkout
17
-
18
- assert_equal 8, redis.client.timeout
19
- end
20
-
21
- it "uses the default network_timeout if none specified" do
22
- pool = Sidekiq::RedisConnection.create
23
- redis = pool.checkout
24
-
25
- assert_equal 5, redis.client.timeout
26
- end
27
- end
28
-
29
- describe "namespace" do
30
- it "uses a given :namespace set by a symbol key" do
31
- pool = Sidekiq::RedisConnection.create(:namespace => "xxx")
32
- assert_equal "xxx", pool.checkout.namespace
33
- end
34
-
35
- it "uses a given :namespace set by a string key" do
36
- pool = Sidekiq::RedisConnection.create("namespace" => "xxx")
37
- assert_equal "xxx", pool.checkout.namespace
38
- end
39
-
40
- it "uses given :namespace over :namespace from Sidekiq.options" do
41
- Sidekiq.options[:namespace] = "xxx"
42
- pool = Sidekiq::RedisConnection.create(:namespace => "yyy")
43
- assert_equal "yyy", pool.checkout.namespace
44
- end
45
- end
46
-
47
- describe "socket path" do
48
- it "uses a given :path" do
49
- pool = Sidekiq::RedisConnection.create(:path => "/var/run/redis.sock")
50
- assert_equal "unix", pool.checkout.client.scheme
51
- assert_equal "redis:///var/run/redis.sock/0", pool.checkout.client.id
52
- end
53
-
54
- it "uses a given :path and :db" do
55
- pool = Sidekiq::RedisConnection.create(:path => "/var/run/redis.sock", :db => 8)
56
- assert_equal "unix", pool.checkout.client.scheme
57
- assert_equal "redis:///var/run/redis.sock/8", pool.checkout.client.id
58
- end
59
- end
60
-
61
- describe "pool_timeout" do
62
- it "uses a given :timeout over the default of 1" do
63
- pool = Sidekiq::RedisConnection.create(:pool_timeout => 5)
64
-
65
- assert_equal 5, pool.instance_eval{ @timeout }
66
- end
67
-
68
- it "uses the default timeout of 1 if no override" do
69
- pool = Sidekiq::RedisConnection.create
70
-
71
- assert_equal 1, pool.instance_eval{ @timeout }
72
- end
73
- end
74
- end
75
-
76
- describe ".determine_redis_provider" do
77
-
78
- before do
79
- @old_env = ENV.to_hash
80
- end
81
-
82
- after do
83
- ENV.update(@old_env)
84
- end
85
-
86
- def with_env_var(var, uri, skip_provider=false)
87
- vars = ['REDISTOGO_URL', 'REDIS_PROVIDER', 'REDIS_URL'] - [var]
88
- vars.each do |v|
89
- next if skip_provider
90
- ENV[v] = nil
91
- end
92
- ENV[var] = uri
93
- assert_equal uri, Sidekiq::RedisConnection.__send__(:determine_redis_provider)
94
- ENV[var] = nil
95
- end
96
-
97
- describe "with REDISTOGO_URL and a parallel REDIS_PROVIDER set" do
98
- it "sets connection URI to the provider" do
99
- uri = 'redis://sidekiq-redis-provider:6379/0'
100
- provider = 'SIDEKIQ_REDIS_PROVIDER'
101
-
102
- ENV['REDIS_PROVIDER'] = provider
103
- ENV[provider] = uri
104
- ENV['REDISTOGO_URL'] = 'redis://redis-to-go:6379/0'
105
- with_env_var provider, uri, true
106
-
107
- ENV[provider] = nil
108
- end
109
- end
110
-
111
- describe "with REDIS_PROVIDER set" do
112
- it "sets connection URI to the provider" do
113
- uri = 'redis://sidekiq-redis-provider:6379/0'
114
- provider = 'SIDEKIQ_REDIS_PROVIDER'
115
-
116
- ENV['REDIS_PROVIDER'] = provider
117
- ENV[provider] = uri
118
-
119
- with_env_var provider, uri, true
120
-
121
- ENV[provider] = nil
122
- end
123
- end
124
-
125
- describe "with REDIS_URL set" do
126
- it "sets connection URI to custom uri" do
127
- with_env_var 'REDIS_URL', 'redis://redis-uri:6379/0'
128
- end
129
- end
130
-
131
- end
132
- end
data/test/test_retry.rb DELETED
@@ -1,326 +0,0 @@
1
- # frozen_string_literal: true
2
- # encoding: utf-8
3
- require_relative 'helper'
4
- require 'sidekiq/scheduled'
5
- require 'sidekiq/middleware/server/retry_jobs'
6
-
7
- class TestRetry < Sidekiq::Test
8
- describe 'middleware' do
9
- class SomeWorker
10
- include Sidekiq::Worker
11
- end
12
-
13
- before do
14
- Sidekiq.redis {|c| c.flushdb }
15
- end
16
-
17
- def worker
18
- @worker ||= SomeWorker.new
19
- end
20
-
21
- def handler(options={})
22
- @handler ||= Sidekiq::Middleware::Server::RetryJobs.new(options)
23
- end
24
-
25
- def job(options={})
26
- @job ||= { 'class' => 'Bob', 'args' => [1,2,'foo'], 'retry' => true }.merge(options)
27
- end
28
-
29
- it 'allows disabling retry' do
30
- assert_raises RuntimeError do
31
- handler.call(worker, job('retry' => false), 'default') do
32
- raise "kerblammo!"
33
- end
34
- end
35
- assert_equal 0, Sidekiq::RetrySet.new.size
36
- end
37
-
38
- it 'allows a numeric retry' do
39
- assert_raises RuntimeError do
40
- handler.call(worker, job('retry' => 2), 'default') do
41
- raise "kerblammo!"
42
- end
43
- end
44
- assert_equal 1, Sidekiq::RetrySet.new.size
45
- assert_equal 0, Sidekiq::DeadSet.new.size
46
- end
47
-
48
- it 'allows 0 retry => no retry and dead queue' do
49
- assert_raises RuntimeError do
50
- handler.call(worker, job('retry' => 0), 'default') do
51
- raise "kerblammo!"
52
- end
53
- end
54
- assert_equal 0, Sidekiq::RetrySet.new.size
55
- assert_equal 1, Sidekiq::DeadSet.new.size
56
- end
57
-
58
- it 'handles zany characters in error message, #1705' do
59
- skip 'skipped! test requires ruby 2.1+' if RUBY_VERSION <= '2.1.0'
60
-
61
- assert_raises RuntimeError do
62
- handler.call(worker, job, 'default') do
63
- raise "kerblammo! #{195.chr}"
64
- end
65
- end
66
- assert_equal "kerblammo! �", job["error_message"]
67
- end
68
-
69
-
70
- it 'allows a max_retries option in initializer' do
71
- max_retries = 7
72
- 1.upto(max_retries + 1) do
73
- assert_raises RuntimeError do
74
- handler(:max_retries => max_retries).call(worker, job, 'default') do
75
- raise "kerblammo!"
76
- end
77
- end
78
- end
79
-
80
- assert_equal max_retries, Sidekiq::RetrySet.new.size
81
- assert_equal 1, Sidekiq::DeadSet.new.size
82
- end
83
-
84
- it 'saves backtraces' do
85
- c = nil
86
- assert_raises RuntimeError do
87
- handler.call(worker, job('backtrace' => true), 'default') do
88
- c = caller(0); raise "kerblammo!"
89
- end
90
- end
91
- assert job["error_backtrace"]
92
- assert_equal c[0], job["error_backtrace"][0]
93
- end
94
-
95
- it 'saves partial backtraces' do
96
- c = nil
97
- assert_raises RuntimeError do
98
- handler.call(worker, job('backtrace' => 3), 'default') do
99
- c = caller(0)[0...3]; raise "kerblammo!"
100
- end
101
- end
102
- assert job["error_backtrace"]
103
- assert_equal c, job["error_backtrace"]
104
- assert_equal 3, c.size
105
- end
106
-
107
- it 'handles a new failed message' do
108
- assert_raises RuntimeError do
109
- handler.call(worker, job, 'default') do
110
- raise "kerblammo!"
111
- end
112
- end
113
- assert_equal 'default', job["queue"]
114
- assert_equal 'kerblammo!', job["error_message"]
115
- assert_equal 'RuntimeError', job["error_class"]
116
- assert_equal 0, job["retry_count"]
117
- refute job["error_backtrace"]
118
- assert job["failed_at"]
119
- end
120
-
121
- it 'shuts down without retrying work-in-progress, which will resume' do
122
- rs = Sidekiq::RetrySet.new
123
- assert_equal 0, rs.size
124
- msg = { 'class' => 'Bob', 'args' => [1,2,'foo'], 'retry' => true }
125
- assert_raises Sidekiq::Shutdown do
126
- handler.call(worker, msg, 'default') do
127
- raise Sidekiq::Shutdown
128
- end
129
- end
130
- assert_equal 0, rs.size
131
- end
132
-
133
- it 'shuts down cleanly when shutdown causes exception' do
134
- skip('Not supported in Ruby < 2.1.0') if RUBY_VERSION < '2.1.0'
135
-
136
- rs = Sidekiq::RetrySet.new
137
- assert_equal 0, rs.size
138
- msg = { 'class' => 'Bob', 'args' => [1,2,'foo'], 'retry' => true }
139
- assert_raises Sidekiq::Shutdown do
140
- handler.call(worker, msg, 'default') do
141
- begin
142
- raise Sidekiq::Shutdown
143
- rescue Interrupt
144
- raise "kerblammo!"
145
- end
146
- end
147
- end
148
- assert_equal 0, rs.size
149
- end
150
-
151
- it 'shuts down cleanly when shutdown causes chained exceptions' do
152
- skip('Not supported in Ruby < 2.1.0') if RUBY_VERSION < '2.1.0'
153
-
154
- rs = Sidekiq::RetrySet.new
155
- assert_equal 0, rs.size
156
- assert_raises Sidekiq::Shutdown do
157
- handler.call(worker, job, 'default') do
158
- begin
159
- raise Sidekiq::Shutdown
160
- rescue Interrupt
161
- begin
162
- raise "kerblammo!"
163
- rescue
164
- raise "kablooie!"
165
- end
166
- end
167
- end
168
- end
169
- assert_equal 0, rs.size
170
- end
171
-
172
- it 'allows a retry queue' do
173
- assert_raises RuntimeError do
174
- handler.call(worker, job("retry_queue" => 'retryx'), 'default') do
175
- raise "kerblammo!"
176
- end
177
- end
178
- assert_equal 'retryx', job["queue"]
179
- assert_equal 'kerblammo!', job["error_message"]
180
- assert_equal 'RuntimeError', job["error_class"]
181
- assert_equal 0, job["retry_count"]
182
- refute job["error_backtrace"]
183
- assert job["failed_at"]
184
- end
185
-
186
- it 'handles a recurring failed message' do
187
- now = Time.now.to_f
188
- msg = {"queue"=>"default", "error_message"=>"kerblammo!", "error_class"=>"RuntimeError", "failed_at"=>now, "retry_count"=>10}
189
- assert_raises RuntimeError do
190
- handler.call(worker, job(msg), 'default') do
191
- raise "kerblammo!"
192
- end
193
- end
194
- assert_equal 'default', job["queue"]
195
- assert_equal 'kerblammo!', job["error_message"]
196
- assert_equal 'RuntimeError', job["error_class"]
197
- assert_equal 11, job["retry_count"]
198
- assert job["failed_at"]
199
- end
200
-
201
- it 'throws away old messages after too many retries (using the default)' do
202
- q = Sidekiq::Queue.new
203
- rs = Sidekiq::RetrySet.new
204
- ds = Sidekiq::DeadSet.new
205
- assert_equal 0, q.size
206
- assert_equal 0, rs.size
207
- assert_equal 0, ds.size
208
- now = Time.now.to_f
209
- msg = {"queue"=>"default", "error_message"=>"kerblammo!", "error_class"=>"RuntimeError", "failed_at"=>now, "retry_count"=>25}
210
- assert_raises RuntimeError do
211
- handler.call(worker, job(msg), 'default') do
212
- raise "kerblammo!"
213
- end
214
- end
215
- assert_equal 0, q.size
216
- assert_equal 0, rs.size
217
- assert_equal 1, ds.size
218
- end
219
-
220
- describe "custom retry delay" do
221
- before do
222
- @old_logger = Sidekiq.logger
223
- @tmp_log_path = '/tmp/sidekiq-retries.log'
224
- Sidekiq.logger = Logger.new(@tmp_log_path)
225
- end
226
-
227
- after do
228
- Sidekiq.logger = @old_logger
229
- Sidekiq.options.delete(:logfile)
230
- File.unlink @tmp_log_path if File.exist?(@tmp_log_path)
231
- end
232
-
233
- class CustomWorkerWithoutException
234
- include Sidekiq::Worker
235
-
236
- sidekiq_retry_in do |count|
237
- count * 2
238
- end
239
- end
240
-
241
- class CustomWorkerWithException
242
- include Sidekiq::Worker
243
-
244
- sidekiq_retry_in do |count, exception|
245
- case exception
246
- when ArgumentError
247
- count * 4
248
- else
249
- count * 2
250
- end
251
- end
252
- end
253
-
254
- class ErrorWorker
255
- include Sidekiq::Worker
256
-
257
- sidekiq_retry_in do |count|
258
- count / 0
259
- end
260
- end
261
-
262
- it "retries with a default delay" do
263
- refute_equal 4, handler.__send__(:delay_for, worker, 2, StandardError.new)
264
- end
265
-
266
- it "retries with a custom delay and exception 1" do
267
- assert_equal 8, handler.__send__(:delay_for, CustomWorkerWithException, 2, ArgumentError.new)
268
- end
269
-
270
- it "retries with a custom delay and exception 2" do
271
- assert_equal 4, handler.__send__(:delay_for, CustomWorkerWithException, 2, StandardError.new)
272
- end
273
-
274
- it "retries with a custom delay without exception" do
275
- assert_equal 4, handler.__send__(:delay_for, CustomWorkerWithoutException, 2, StandardError.new)
276
- end
277
-
278
- it "falls back to the default retry on exception" do
279
- refute_equal 4, handler.__send__(:delay_for, ErrorWorker, 2, StandardError.new)
280
- assert_match(/Failure scheduling retry using the defined `sidekiq_retry_in`/,
281
- File.read(@tmp_log_path), 'Log entry missing for sidekiq_retry_in')
282
- end
283
- end
284
-
285
- describe 'handles errors withouth cause' do
286
- before do
287
- @error = nil
288
- begin
289
- raise ::StandardError, 'Error'
290
- rescue ::StandardError => e
291
- @error = e
292
- end
293
- end
294
-
295
- it "does not recurse infinitely checking if it's a shutdown" do
296
- assert(!Sidekiq::Middleware::Server::RetryJobs.new.send(
297
- :exception_caused_by_shutdown?, @error))
298
- end
299
- end
300
-
301
- describe 'handles errors with circular causes' do
302
- before do
303
- @error = nil
304
- begin
305
- begin
306
- raise ::StandardError, 'Error 1'
307
- rescue ::StandardError => e1
308
- begin
309
- raise ::StandardError, 'Error 2'
310
- rescue ::StandardError
311
- raise e1
312
- end
313
- end
314
- rescue ::StandardError => e
315
- @error = e
316
- end
317
- end
318
-
319
- it "does not recurse infinitely checking if it's a shutdown" do
320
- assert(!Sidekiq::Middleware::Server::RetryJobs.new.send(
321
- :exception_caused_by_shutdown?, @error))
322
- end
323
- end
324
- end
325
-
326
- end