sr-sidekiq 4.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/3.0-Upgrade.md +70 -0
- data/4.0-Upgrade.md +50 -0
- data/COMM-LICENSE (sidekiq) +95 -0
- data/Changes.md +1241 -0
- data/Ent-Changes.md +112 -0
- data/Gemfile +29 -0
- data/LICENSE (sidekiq) +9 -0
- data/LICENSE (sr-sidekiq) +5 -0
- data/Pro-2.0-Upgrade.md +138 -0
- data/Pro-3.0-Upgrade.md +44 -0
- data/Pro-Changes.md +539 -0
- data/README.md +8 -0
- data/Rakefile +9 -0
- data/bin/sidekiq +18 -0
- data/bin/sidekiqctl +99 -0
- data/bin/sidekiqload +167 -0
- data/code_of_conduct.md +50 -0
- data/lib/generators/sidekiq/templates/worker.rb.erb +9 -0
- data/lib/generators/sidekiq/templates/worker_spec.rb.erb +6 -0
- data/lib/generators/sidekiq/templates/worker_test.rb.erb +8 -0
- data/lib/generators/sidekiq/worker_generator.rb +49 -0
- data/lib/sidekiq.rb +237 -0
- data/lib/sidekiq/api.rb +844 -0
- data/lib/sidekiq/cli.rb +389 -0
- data/lib/sidekiq/client.rb +260 -0
- data/lib/sidekiq/core_ext.rb +106 -0
- data/lib/sidekiq/exception_handler.rb +31 -0
- data/lib/sidekiq/extensions/action_mailer.rb +57 -0
- data/lib/sidekiq/extensions/active_record.rb +40 -0
- data/lib/sidekiq/extensions/class_methods.rb +40 -0
- data/lib/sidekiq/extensions/generic_proxy.rb +25 -0
- data/lib/sidekiq/fetch.rb +81 -0
- data/lib/sidekiq/launcher.rb +160 -0
- data/lib/sidekiq/logging.rb +106 -0
- data/lib/sidekiq/manager.rb +137 -0
- data/lib/sidekiq/middleware/chain.rb +150 -0
- data/lib/sidekiq/middleware/i18n.rb +42 -0
- data/lib/sidekiq/middleware/server/active_record.rb +13 -0
- data/lib/sidekiq/middleware/server/logging.rb +40 -0
- data/lib/sidekiq/middleware/server/retry_jobs.rb +205 -0
- data/lib/sidekiq/paginator.rb +43 -0
- data/lib/sidekiq/processor.rb +186 -0
- data/lib/sidekiq/rails.rb +39 -0
- data/lib/sidekiq/redis_connection.rb +97 -0
- data/lib/sidekiq/scheduled.rb +146 -0
- data/lib/sidekiq/testing.rb +316 -0
- data/lib/sidekiq/testing/inline.rb +29 -0
- data/lib/sidekiq/util.rb +62 -0
- data/lib/sidekiq/version.rb +4 -0
- data/lib/sidekiq/web.rb +278 -0
- data/lib/sidekiq/web_helpers.rb +255 -0
- data/lib/sidekiq/worker.rb +121 -0
- data/sidekiq.gemspec +26 -0
- data/sr-sidekiq-4.1.3.gem +0 -0
- data/sr-sidekiq-4.1.4.gem +0 -0
- data/sr-sidekiq-4.1.5.gem +0 -0
- data/test/config.yml +9 -0
- data/test/env_based_config.yml +11 -0
- data/test/fake_env.rb +1 -0
- data/test/fixtures/en.yml +2 -0
- data/test/helper.rb +75 -0
- data/test/test_actors.rb +138 -0
- data/test/test_api.rb +528 -0
- data/test/test_cli.rb +406 -0
- data/test/test_client.rb +262 -0
- data/test/test_exception_handler.rb +56 -0
- data/test/test_extensions.rb +127 -0
- data/test/test_fetch.rb +50 -0
- data/test/test_launcher.rb +85 -0
- data/test/test_logging.rb +35 -0
- data/test/test_manager.rb +50 -0
- data/test/test_middleware.rb +158 -0
- data/test/test_processor.rb +201 -0
- data/test/test_rails.rb +22 -0
- data/test/test_redis_connection.rb +127 -0
- data/test/test_retry.rb +326 -0
- data/test/test_retry_exhausted.rb +149 -0
- data/test/test_scheduled.rb +115 -0
- data/test/test_scheduling.rb +50 -0
- data/test/test_sidekiq.rb +107 -0
- data/test/test_testing.rb +143 -0
- data/test/test_testing_fake.rb +357 -0
- data/test/test_testing_inline.rb +94 -0
- data/test/test_util.rb +13 -0
- data/test/test_web.rb +614 -0
- data/test/test_web_helpers.rb +54 -0
- data/web/assets/images/bootstrap/glyphicons-halflings-white.png +0 -0
- data/web/assets/images/bootstrap/glyphicons-halflings.png +0 -0
- data/web/assets/images/favicon.ico +0 -0
- data/web/assets/images/logo.png +0 -0
- data/web/assets/images/status-sd8051fd480.png +0 -0
- data/web/assets/images/status/active.png +0 -0
- data/web/assets/images/status/idle.png +0 -0
- data/web/assets/javascripts/application.js +88 -0
- data/web/assets/javascripts/dashboard.js +300 -0
- data/web/assets/javascripts/locales/README.md +27 -0
- data/web/assets/javascripts/locales/jquery.timeago.ar.js +96 -0
- data/web/assets/javascripts/locales/jquery.timeago.bg.js +18 -0
- data/web/assets/javascripts/locales/jquery.timeago.bs.js +49 -0
- data/web/assets/javascripts/locales/jquery.timeago.ca.js +18 -0
- data/web/assets/javascripts/locales/jquery.timeago.cs.js +18 -0
- data/web/assets/javascripts/locales/jquery.timeago.cy.js +20 -0
- data/web/assets/javascripts/locales/jquery.timeago.da.js +18 -0
- data/web/assets/javascripts/locales/jquery.timeago.de.js +18 -0
- data/web/assets/javascripts/locales/jquery.timeago.el.js +18 -0
- data/web/assets/javascripts/locales/jquery.timeago.en-short.js +20 -0
- data/web/assets/javascripts/locales/jquery.timeago.en.js +20 -0
- data/web/assets/javascripts/locales/jquery.timeago.es.js +18 -0
- data/web/assets/javascripts/locales/jquery.timeago.et.js +18 -0
- data/web/assets/javascripts/locales/jquery.timeago.fa.js +22 -0
- data/web/assets/javascripts/locales/jquery.timeago.fi.js +28 -0
- data/web/assets/javascripts/locales/jquery.timeago.fr-short.js +16 -0
- data/web/assets/javascripts/locales/jquery.timeago.fr.js +17 -0
- data/web/assets/javascripts/locales/jquery.timeago.he.js +18 -0
- data/web/assets/javascripts/locales/jquery.timeago.hr.js +49 -0
- data/web/assets/javascripts/locales/jquery.timeago.hu.js +18 -0
- data/web/assets/javascripts/locales/jquery.timeago.hy.js +18 -0
- data/web/assets/javascripts/locales/jquery.timeago.id.js +18 -0
- data/web/assets/javascripts/locales/jquery.timeago.it.js +16 -0
- data/web/assets/javascripts/locales/jquery.timeago.ja.js +19 -0
- data/web/assets/javascripts/locales/jquery.timeago.ko.js +17 -0
- data/web/assets/javascripts/locales/jquery.timeago.lt.js +20 -0
- data/web/assets/javascripts/locales/jquery.timeago.mk.js +20 -0
- data/web/assets/javascripts/locales/jquery.timeago.nl.js +20 -0
- data/web/assets/javascripts/locales/jquery.timeago.no.js +18 -0
- data/web/assets/javascripts/locales/jquery.timeago.pl.js +31 -0
- data/web/assets/javascripts/locales/jquery.timeago.pt-br.js +16 -0
- data/web/assets/javascripts/locales/jquery.timeago.pt.js +16 -0
- data/web/assets/javascripts/locales/jquery.timeago.ro.js +18 -0
- data/web/assets/javascripts/locales/jquery.timeago.rs.js +49 -0
- data/web/assets/javascripts/locales/jquery.timeago.ru.js +34 -0
- data/web/assets/javascripts/locales/jquery.timeago.sk.js +18 -0
- data/web/assets/javascripts/locales/jquery.timeago.sl.js +44 -0
- data/web/assets/javascripts/locales/jquery.timeago.sv.js +18 -0
- data/web/assets/javascripts/locales/jquery.timeago.th.js +20 -0
- data/web/assets/javascripts/locales/jquery.timeago.tr.js +16 -0
- data/web/assets/javascripts/locales/jquery.timeago.uk.js +34 -0
- data/web/assets/javascripts/locales/jquery.timeago.uz.js +19 -0
- data/web/assets/javascripts/locales/jquery.timeago.zh-cn.js +20 -0
- data/web/assets/javascripts/locales/jquery.timeago.zh-tw.js +20 -0
- data/web/assets/stylesheets/application.css +754 -0
- data/web/assets/stylesheets/bootstrap.css +9 -0
- data/web/locales/cs.yml +78 -0
- data/web/locales/da.yml +68 -0
- data/web/locales/de.yml +69 -0
- data/web/locales/el.yml +68 -0
- data/web/locales/en.yml +79 -0
- data/web/locales/es.yml +69 -0
- data/web/locales/fr.yml +78 -0
- data/web/locales/hi.yml +75 -0
- data/web/locales/it.yml +69 -0
- data/web/locales/ja.yml +78 -0
- data/web/locales/ko.yml +68 -0
- data/web/locales/nb.yml +77 -0
- data/web/locales/nl.yml +68 -0
- data/web/locales/pl.yml +59 -0
- data/web/locales/pt-br.yml +68 -0
- data/web/locales/pt.yml +67 -0
- data/web/locales/ru.yml +78 -0
- data/web/locales/sv.yml +68 -0
- data/web/locales/ta.yml +75 -0
- data/web/locales/uk.yml +76 -0
- data/web/locales/zh-cn.yml +68 -0
- data/web/locales/zh-tw.yml +68 -0
- data/web/views/_footer.erb +17 -0
- data/web/views/_job_info.erb +88 -0
- data/web/views/_nav.erb +66 -0
- data/web/views/_paging.erb +23 -0
- data/web/views/_poll_js.erb +5 -0
- data/web/views/_poll_link.erb +7 -0
- data/web/views/_status.erb +4 -0
- data/web/views/_summary.erb +40 -0
- data/web/views/busy.erb +94 -0
- data/web/views/dashboard.erb +75 -0
- data/web/views/dead.erb +34 -0
- data/web/views/layout.erb +32 -0
- data/web/views/morgue.erb +71 -0
- data/web/views/queue.erb +45 -0
- data/web/views/queues.erb +28 -0
- data/web/views/retries.erb +74 -0
- data/web/views/retry.erb +34 -0
- data/web/views/scheduled.erb +54 -0
- data/web/views/scheduled_job_info.erb +8 -0
- metadata +408 -0
@@ -0,0 +1,149 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require_relative 'helper'
|
3
|
+
require 'sidekiq/middleware/server/retry_jobs'
|
4
|
+
|
5
|
+
class TestRetryExhausted < Sidekiq::Test
|
6
|
+
describe 'sidekiq_retries_exhausted' do
|
7
|
+
class NewWorker
|
8
|
+
include Sidekiq::Worker
|
9
|
+
|
10
|
+
class_attribute :exhausted_called, :exhausted_job, :exhausted_exception
|
11
|
+
|
12
|
+
sidekiq_retries_exhausted do |job, e|
|
13
|
+
self.exhausted_called = true
|
14
|
+
self.exhausted_job = job
|
15
|
+
self.exhausted_exception = e
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class OldWorker
|
20
|
+
include Sidekiq::Worker
|
21
|
+
|
22
|
+
class_attribute :exhausted_called, :exhausted_job, :exhausted_exception
|
23
|
+
|
24
|
+
sidekiq_retries_exhausted do |job|
|
25
|
+
self.exhausted_called = true
|
26
|
+
self.exhausted_job = job
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def cleanup
|
31
|
+
[NewWorker, OldWorker].each do |worker_class|
|
32
|
+
worker_class.exhausted_called = nil
|
33
|
+
worker_class.exhausted_job = nil
|
34
|
+
worker_class.exhausted_exception = nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
before do
|
39
|
+
cleanup
|
40
|
+
end
|
41
|
+
|
42
|
+
after do
|
43
|
+
cleanup
|
44
|
+
end
|
45
|
+
|
46
|
+
def new_worker
|
47
|
+
@new_worker ||= NewWorker.new
|
48
|
+
end
|
49
|
+
|
50
|
+
def old_worker
|
51
|
+
@old_worker ||= OldWorker.new
|
52
|
+
end
|
53
|
+
|
54
|
+
def handler(options={})
|
55
|
+
@handler ||= Sidekiq::Middleware::Server::RetryJobs.new(options)
|
56
|
+
end
|
57
|
+
|
58
|
+
def job(options={})
|
59
|
+
@job ||= {'class' => 'Bob', 'args' => [1, 2, 'foo']}.merge(options)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'does not run exhausted block when job successful on first run' do
|
63
|
+
handler.call(new_worker, job('retry' => 2), 'default') do
|
64
|
+
# successful
|
65
|
+
end
|
66
|
+
|
67
|
+
refute NewWorker.exhausted_called?
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'does not run exhausted block when job successful on last retry' do
|
71
|
+
handler.call(new_worker, job('retry_count' => 0, 'retry' => 1), 'default') do
|
72
|
+
# successful
|
73
|
+
end
|
74
|
+
|
75
|
+
refute NewWorker.exhausted_called?
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'does not run exhausted block when retries not exhausted yet' do
|
79
|
+
assert_raises RuntimeError do
|
80
|
+
handler.call(new_worker, job('retry' => 1), 'default') do
|
81
|
+
raise 'kerblammo!'
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
refute NewWorker.exhausted_called?
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'runs exhausted block when retries exhausted' do
|
89
|
+
assert_raises RuntimeError do
|
90
|
+
handler.call(new_worker, job('retry_count' => 0, 'retry' => 1), 'default') do
|
91
|
+
raise 'kerblammo!'
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
assert NewWorker.exhausted_called?
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
it 'passes job and exception to retries exhausted block' do
|
100
|
+
raised_error = assert_raises RuntimeError do
|
101
|
+
handler.call(new_worker, job('retry_count' => 0, 'retry' => 1), 'default') do
|
102
|
+
raise 'kerblammo!'
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
assert new_worker.exhausted_called?
|
107
|
+
assert_equal raised_error.message, new_worker.exhausted_job['error_message']
|
108
|
+
assert_equal raised_error, new_worker.exhausted_exception
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'passes job to retries exhausted block' do
|
112
|
+
raised_error = assert_raises RuntimeError do
|
113
|
+
handler.call(old_worker, job('retry_count' => 0, 'retry' => 1), 'default') do
|
114
|
+
raise 'kerblammo!'
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
assert old_worker.exhausted_called?
|
119
|
+
assert_equal raised_error.message, old_worker.exhausted_job['error_message']
|
120
|
+
assert_equal nil, new_worker.exhausted_exception
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'allows a global default handler' do
|
124
|
+
begin
|
125
|
+
class Foobar
|
126
|
+
include Sidekiq::Worker
|
127
|
+
end
|
128
|
+
|
129
|
+
exhausted_job = nil
|
130
|
+
exhausted_exception = nil
|
131
|
+
Sidekiq.default_retries_exhausted = lambda do |job, ex|
|
132
|
+
exhausted_job = job
|
133
|
+
exhausted_exception = ex
|
134
|
+
end
|
135
|
+
f = Foobar.new
|
136
|
+
raised_error = assert_raises RuntimeError do
|
137
|
+
handler.call(f, job('retry_count' => 0, 'retry' => 1), 'default') do
|
138
|
+
raise 'kerblammo!'
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
assert exhausted_job
|
143
|
+
assert_equal raised_error, exhausted_exception
|
144
|
+
ensure
|
145
|
+
Sidekiq.default_retries_exhausted = nil
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative 'helper'
|
3
|
+
require 'sidekiq/scheduled'
|
4
|
+
|
5
|
+
class TestScheduled < Sidekiq::Test
|
6
|
+
class ScheduledWorker
|
7
|
+
include Sidekiq::Worker
|
8
|
+
def perform(x)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe 'poller' do
|
13
|
+
before do
|
14
|
+
Sidekiq.redis{|c| c.flushdb}
|
15
|
+
@error_1 = { 'class' => ScheduledWorker.name, 'args' => [0], 'queue' => 'queue_1' }
|
16
|
+
@error_2 = { 'class' => ScheduledWorker.name, 'args' => [1], 'queue' => 'queue_2' }
|
17
|
+
@error_3 = { 'class' => ScheduledWorker.name, 'args' => [2], 'queue' => 'queue_3' }
|
18
|
+
@future_1 = { 'class' => ScheduledWorker.name, 'args' => [3], 'queue' => 'queue_4' }
|
19
|
+
@future_2 = { 'class' => ScheduledWorker.name, 'args' => [4], 'queue' => 'queue_5' }
|
20
|
+
@future_3 = { 'class' => ScheduledWorker.name, 'args' => [5], 'queue' => 'queue_6' }
|
21
|
+
|
22
|
+
@retry = Sidekiq::RetrySet.new
|
23
|
+
@scheduled = Sidekiq::ScheduledSet.new
|
24
|
+
@poller = Sidekiq::Scheduled::Poller.new
|
25
|
+
end
|
26
|
+
|
27
|
+
class Stopper
|
28
|
+
def call(worker_class, job, queue, r)
|
29
|
+
yield if job['args'].first.odd?
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'executes client middleware' do
|
34
|
+
Sidekiq.client_middleware.add Stopper
|
35
|
+
begin
|
36
|
+
@retry.schedule (Time.now - 60).to_f, @error_1
|
37
|
+
@retry.schedule (Time.now - 60).to_f, @error_2
|
38
|
+
@scheduled.schedule (Time.now - 60).to_f, @future_2
|
39
|
+
@scheduled.schedule (Time.now - 60).to_f, @future_3
|
40
|
+
|
41
|
+
@poller.enqueue
|
42
|
+
|
43
|
+
assert_equal 0, Sidekiq::Queue.new("queue_1").size
|
44
|
+
assert_equal 1, Sidekiq::Queue.new("queue_2").size
|
45
|
+
assert_equal 0, Sidekiq::Queue.new("queue_5").size
|
46
|
+
assert_equal 1, Sidekiq::Queue.new("queue_6").size
|
47
|
+
ensure
|
48
|
+
Sidekiq.client_middleware.remove Stopper
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should empty the retry and scheduled queues up to the current time' do
|
53
|
+
created_time = Time.new(2013, 2, 3)
|
54
|
+
enqueued_time = Time.new(2013, 2, 4)
|
55
|
+
|
56
|
+
Time.stub(:now, created_time) do
|
57
|
+
@retry.schedule (enqueued_time - 60).to_f, @error_1.merge!('created_at' => created_time.to_f)
|
58
|
+
@retry.schedule (enqueued_time - 50).to_f, @error_2.merge!('created_at' => created_time.to_f)
|
59
|
+
@retry.schedule (enqueued_time + 60).to_f, @error_3.merge!('created_at' => created_time.to_f)
|
60
|
+
@scheduled.schedule (enqueued_time - 60).to_f, @future_1.merge!('created_at' => created_time.to_f)
|
61
|
+
@scheduled.schedule (enqueued_time - 50).to_f, @future_2.merge!('created_at' => created_time.to_f)
|
62
|
+
@scheduled.schedule (enqueued_time + 60).to_f, @future_3.merge!('created_at' => created_time.to_f)
|
63
|
+
end
|
64
|
+
|
65
|
+
Time.stub(:now, enqueued_time) do
|
66
|
+
@poller.enqueue
|
67
|
+
|
68
|
+
Sidekiq.redis do |conn|
|
69
|
+
%w(queue:queue_1 queue:queue_2 queue:queue_4 queue:queue_5).each do |queue_name|
|
70
|
+
assert_equal 1, conn.llen(queue_name)
|
71
|
+
job = Sidekiq.load_json(conn.lrange(queue_name, 0, -1)[0])
|
72
|
+
assert_equal enqueued_time.to_f, job['enqueued_at']
|
73
|
+
assert_equal created_time.to_f, job['created_at']
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
assert_equal 1, @retry.size
|
78
|
+
assert_equal 1, @scheduled.size
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def with_sidekiq_option(name, value)
|
83
|
+
_original, Sidekiq.options[name] = Sidekiq.options[name], value
|
84
|
+
begin
|
85
|
+
yield
|
86
|
+
ensure
|
87
|
+
Sidekiq.options[name] = _original
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'generates random intervals that target a configured average' do
|
92
|
+
with_sidekiq_option(:poll_interval_average, 10) do
|
93
|
+
i = 500
|
94
|
+
intervals = Array.new(i){ @poller.send(:random_poll_interval) }
|
95
|
+
|
96
|
+
assert intervals.all?{|x| x >= 5}
|
97
|
+
assert intervals.all?{|x| x <= 15}
|
98
|
+
assert_in_delta 10, intervals.reduce(&:+).to_f / i, 0.5
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'calculates an average poll interval based on the number of known Sidekiq processes' do
|
103
|
+
with_sidekiq_option(:average_scheduled_poll_interval, 10) do
|
104
|
+
3.times do |i|
|
105
|
+
Sidekiq.redis do |conn|
|
106
|
+
conn.sadd("processes", "process-#{i}")
|
107
|
+
conn.hset("process-#{i}", "info", nil)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
assert_equal 30, @poller.send(:scaled_poll_interval)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative 'helper'
|
3
|
+
require 'sidekiq/scheduled'
|
4
|
+
|
5
|
+
class TestScheduling < Sidekiq::Test
|
6
|
+
describe 'middleware' do
|
7
|
+
class ScheduledWorker
|
8
|
+
include Sidekiq::Worker
|
9
|
+
sidekiq_options :queue => :custom_queue
|
10
|
+
def perform(x)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'schedules jobs' do
|
15
|
+
ss = Sidekiq::ScheduledSet.new
|
16
|
+
ss.clear
|
17
|
+
|
18
|
+
assert_equal 0, ss.size
|
19
|
+
|
20
|
+
assert ScheduledWorker.perform_in(600, 'mike')
|
21
|
+
assert_equal 1, ss.size
|
22
|
+
|
23
|
+
assert ScheduledWorker.perform_in(1.month, 'mike')
|
24
|
+
assert_equal 2, ss.size
|
25
|
+
|
26
|
+
assert ScheduledWorker.perform_in(5.days.from_now, 'mike')
|
27
|
+
assert_equal 3, ss.size
|
28
|
+
|
29
|
+
q = Sidekiq::Queue.new("custom_queue")
|
30
|
+
qs = q.size
|
31
|
+
assert ScheduledWorker.perform_in(-300, 'mike')
|
32
|
+
assert_equal 3, ss.size
|
33
|
+
assert_equal qs+1, q.size
|
34
|
+
|
35
|
+
assert Sidekiq::Client.push_bulk('class' => ScheduledWorker, 'args' => [['mike'], ['mike']], 'at' => 600)
|
36
|
+
assert_equal 5, ss.size
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'removes the enqueued_at field when scheduling' do
|
40
|
+
ss = Sidekiq::ScheduledSet.new
|
41
|
+
ss.clear
|
42
|
+
|
43
|
+
assert ScheduledWorker.perform_in(1.month, 'mike')
|
44
|
+
job = ss.first
|
45
|
+
assert job['created_at']
|
46
|
+
refute job['enqueued_at']
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# encoding: utf-8
|
3
|
+
require_relative 'helper'
|
4
|
+
|
5
|
+
class TestSidekiq < Sidekiq::Test
|
6
|
+
describe 'json processing' do
|
7
|
+
it 'handles json' do
|
8
|
+
assert_equal({"foo" => "bar"}, Sidekiq.load_json("{\"foo\":\"bar\"}"))
|
9
|
+
assert_equal "{\"foo\":\"bar\"}", Sidekiq.dump_json({ "foo" => "bar" })
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "redis connection" do
|
14
|
+
it "returns error without creating a connection if block is not given" do
|
15
|
+
assert_raises(ArgumentError) do
|
16
|
+
Sidekiq.redis
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "❨╯°□°❩╯︵┻━┻" do
|
22
|
+
before { $stdout = StringIO.new }
|
23
|
+
after { $stdout = STDOUT }
|
24
|
+
|
25
|
+
it "allows angry developers to express their emotional constitution and remedies it" do
|
26
|
+
Sidekiq.❨╯°□°❩╯︵┻━┻
|
27
|
+
assert_equal "Calm down, yo.\n", $stdout.string
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe 'lifecycle events' do
|
32
|
+
it 'handles invalid input' do
|
33
|
+
Sidekiq.options[:lifecycle_events][:startup].clear
|
34
|
+
|
35
|
+
e = assert_raises ArgumentError do
|
36
|
+
Sidekiq.on(:startp)
|
37
|
+
end
|
38
|
+
assert_match(/Invalid event name/, e.message)
|
39
|
+
e = assert_raises ArgumentError do
|
40
|
+
Sidekiq.on('startup')
|
41
|
+
end
|
42
|
+
assert_match(/Symbols only/, e.message)
|
43
|
+
Sidekiq.on(:startup) do
|
44
|
+
1 + 1
|
45
|
+
end
|
46
|
+
|
47
|
+
assert_equal 2, Sidekiq.options[:lifecycle_events][:startup].first.call
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe 'default_worker_options' do
|
52
|
+
it 'stringifies keys' do
|
53
|
+
@old_options = Sidekiq.default_worker_options
|
54
|
+
begin
|
55
|
+
Sidekiq.default_worker_options = { queue: 'cat'}
|
56
|
+
assert_equal 'cat', Sidekiq.default_worker_options['queue']
|
57
|
+
ensure
|
58
|
+
Sidekiq.default_worker_options = @old_options
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe 'error handling' do
|
64
|
+
it 'deals with user-specified error handlers which raise errors' do
|
65
|
+
output = capture_logging do
|
66
|
+
begin
|
67
|
+
Sidekiq.error_handlers << proc {|x, hash|
|
68
|
+
raise 'boom'
|
69
|
+
}
|
70
|
+
cli = Sidekiq::CLI.new
|
71
|
+
cli.handle_exception(RuntimeError.new("hello"))
|
72
|
+
ensure
|
73
|
+
Sidekiq.error_handlers.pop
|
74
|
+
end
|
75
|
+
end
|
76
|
+
assert_includes output, "boom"
|
77
|
+
assert_includes output, "ERROR"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe 'redis connection' do
|
82
|
+
it 'does not continually retry' do
|
83
|
+
assert_raises Redis::CommandError do
|
84
|
+
Sidekiq.redis do |c|
|
85
|
+
raise Redis::CommandError, "READONLY You can't write against a read only slave."
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'reconnects if connection is flagged as readonly' do
|
91
|
+
counts = []
|
92
|
+
Sidekiq.redis do |c|
|
93
|
+
counts << c.info['total_connections_received'].to_i
|
94
|
+
raise Redis::CommandError, "READONLY You can't write against a read only slave." if counts.size == 1
|
95
|
+
end
|
96
|
+
assert_equal 2, counts.size
|
97
|
+
assert_equal counts[0] + 1, counts[1]
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe 'redis info' do
|
102
|
+
it 'calls the INFO command which returns at least redis_version' do
|
103
|
+
output = Sidekiq.redis_info
|
104
|
+
assert_includes output.keys, "redis_version"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative 'helper'
|
3
|
+
|
4
|
+
require 'active_record'
|
5
|
+
require 'action_mailer'
|
6
|
+
require 'sidekiq/rails'
|
7
|
+
require 'sidekiq/extensions/action_mailer'
|
8
|
+
require 'sidekiq/extensions/active_record'
|
9
|
+
|
10
|
+
Sidekiq.hook_rails!
|
11
|
+
|
12
|
+
class TestTesting < Sidekiq::Test
|
13
|
+
describe 'sidekiq testing' do
|
14
|
+
describe 'require/load sidekiq/testing.rb' do
|
15
|
+
before do
|
16
|
+
require 'sidekiq/testing'
|
17
|
+
end
|
18
|
+
|
19
|
+
after do
|
20
|
+
Sidekiq::Testing.disable!
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'enables fake testing' do
|
24
|
+
Sidekiq::Testing.fake!
|
25
|
+
assert Sidekiq::Testing.enabled?
|
26
|
+
assert Sidekiq::Testing.fake?
|
27
|
+
refute Sidekiq::Testing.inline?
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'enables fake testing in a block' do
|
31
|
+
Sidekiq::Testing.disable!
|
32
|
+
assert Sidekiq::Testing.disabled?
|
33
|
+
refute Sidekiq::Testing.fake?
|
34
|
+
|
35
|
+
Sidekiq::Testing.fake! do
|
36
|
+
assert Sidekiq::Testing.enabled?
|
37
|
+
assert Sidekiq::Testing.fake?
|
38
|
+
refute Sidekiq::Testing.inline?
|
39
|
+
end
|
40
|
+
|
41
|
+
refute Sidekiq::Testing.enabled?
|
42
|
+
refute Sidekiq::Testing.fake?
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'disables testing in a block' do
|
46
|
+
Sidekiq::Testing.fake!
|
47
|
+
assert Sidekiq::Testing.fake?
|
48
|
+
|
49
|
+
Sidekiq::Testing.disable! do
|
50
|
+
refute Sidekiq::Testing.fake?
|
51
|
+
assert Sidekiq::Testing.disabled?
|
52
|
+
end
|
53
|
+
|
54
|
+
assert Sidekiq::Testing.fake?
|
55
|
+
assert Sidekiq::Testing.enabled?
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe 'require/load sidekiq/testing/inline.rb' do
|
60
|
+
before do
|
61
|
+
require 'sidekiq/testing/inline'
|
62
|
+
end
|
63
|
+
|
64
|
+
after do
|
65
|
+
Sidekiq::Testing.disable!
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'enables inline testing' do
|
69
|
+
Sidekiq::Testing.inline!
|
70
|
+
assert Sidekiq::Testing.enabled?
|
71
|
+
assert Sidekiq::Testing.inline?
|
72
|
+
refute Sidekiq::Testing.fake?
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'enables inline testing in a block' do
|
76
|
+
Sidekiq::Testing.disable!
|
77
|
+
assert Sidekiq::Testing.disabled?
|
78
|
+
refute Sidekiq::Testing.fake?
|
79
|
+
|
80
|
+
Sidekiq::Testing.inline! do
|
81
|
+
assert Sidekiq::Testing.enabled?
|
82
|
+
assert Sidekiq::Testing.inline?
|
83
|
+
end
|
84
|
+
|
85
|
+
refute Sidekiq::Testing.enabled?
|
86
|
+
refute Sidekiq::Testing.inline?
|
87
|
+
refute Sidekiq::Testing.fake?
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe 'with middleware' do
|
93
|
+
before do
|
94
|
+
require 'sidekiq/testing'
|
95
|
+
end
|
96
|
+
|
97
|
+
after do
|
98
|
+
Sidekiq::Testing.disable!
|
99
|
+
end
|
100
|
+
|
101
|
+
class AttributeWorker
|
102
|
+
include Sidekiq::Worker
|
103
|
+
class_attribute :count
|
104
|
+
self.count = 0
|
105
|
+
attr_accessor :foo
|
106
|
+
|
107
|
+
def perform
|
108
|
+
self.class.count += 1 if foo == :bar
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
class AttributeMiddleware
|
113
|
+
def call(worker, msg, queue)
|
114
|
+
worker.foo = :bar if worker.respond_to?(:foo=)
|
115
|
+
yield
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'wraps the inlined worker with middleware' do
|
120
|
+
Sidekiq::Testing.server_middleware do |chain|
|
121
|
+
chain.add AttributeMiddleware
|
122
|
+
end
|
123
|
+
|
124
|
+
begin
|
125
|
+
Sidekiq::Testing.fake! do
|
126
|
+
AttributeWorker.perform_async
|
127
|
+
assert_equal 0, AttributeWorker.count
|
128
|
+
end
|
129
|
+
|
130
|
+
AttributeWorker.perform_one
|
131
|
+
assert_equal 1, AttributeWorker.count
|
132
|
+
|
133
|
+
Sidekiq::Testing.inline! do
|
134
|
+
AttributeWorker.perform_async
|
135
|
+
assert_equal 2, AttributeWorker.count
|
136
|
+
end
|
137
|
+
ensure
|
138
|
+
Sidekiq::Testing.server_middleware.clear
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|