sr-sidekiq 4.1.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (186) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/3.0-Upgrade.md +70 -0
  4. data/4.0-Upgrade.md +50 -0
  5. data/COMM-LICENSE (sidekiq) +95 -0
  6. data/Changes.md +1241 -0
  7. data/Ent-Changes.md +112 -0
  8. data/Gemfile +29 -0
  9. data/LICENSE (sidekiq) +9 -0
  10. data/LICENSE (sr-sidekiq) +5 -0
  11. data/Pro-2.0-Upgrade.md +138 -0
  12. data/Pro-3.0-Upgrade.md +44 -0
  13. data/Pro-Changes.md +539 -0
  14. data/README.md +8 -0
  15. data/Rakefile +9 -0
  16. data/bin/sidekiq +18 -0
  17. data/bin/sidekiqctl +99 -0
  18. data/bin/sidekiqload +167 -0
  19. data/code_of_conduct.md +50 -0
  20. data/lib/generators/sidekiq/templates/worker.rb.erb +9 -0
  21. data/lib/generators/sidekiq/templates/worker_spec.rb.erb +6 -0
  22. data/lib/generators/sidekiq/templates/worker_test.rb.erb +8 -0
  23. data/lib/generators/sidekiq/worker_generator.rb +49 -0
  24. data/lib/sidekiq.rb +237 -0
  25. data/lib/sidekiq/api.rb +844 -0
  26. data/lib/sidekiq/cli.rb +389 -0
  27. data/lib/sidekiq/client.rb +260 -0
  28. data/lib/sidekiq/core_ext.rb +106 -0
  29. data/lib/sidekiq/exception_handler.rb +31 -0
  30. data/lib/sidekiq/extensions/action_mailer.rb +57 -0
  31. data/lib/sidekiq/extensions/active_record.rb +40 -0
  32. data/lib/sidekiq/extensions/class_methods.rb +40 -0
  33. data/lib/sidekiq/extensions/generic_proxy.rb +25 -0
  34. data/lib/sidekiq/fetch.rb +81 -0
  35. data/lib/sidekiq/launcher.rb +160 -0
  36. data/lib/sidekiq/logging.rb +106 -0
  37. data/lib/sidekiq/manager.rb +137 -0
  38. data/lib/sidekiq/middleware/chain.rb +150 -0
  39. data/lib/sidekiq/middleware/i18n.rb +42 -0
  40. data/lib/sidekiq/middleware/server/active_record.rb +13 -0
  41. data/lib/sidekiq/middleware/server/logging.rb +40 -0
  42. data/lib/sidekiq/middleware/server/retry_jobs.rb +205 -0
  43. data/lib/sidekiq/paginator.rb +43 -0
  44. data/lib/sidekiq/processor.rb +186 -0
  45. data/lib/sidekiq/rails.rb +39 -0
  46. data/lib/sidekiq/redis_connection.rb +97 -0
  47. data/lib/sidekiq/scheduled.rb +146 -0
  48. data/lib/sidekiq/testing.rb +316 -0
  49. data/lib/sidekiq/testing/inline.rb +29 -0
  50. data/lib/sidekiq/util.rb +62 -0
  51. data/lib/sidekiq/version.rb +4 -0
  52. data/lib/sidekiq/web.rb +278 -0
  53. data/lib/sidekiq/web_helpers.rb +255 -0
  54. data/lib/sidekiq/worker.rb +121 -0
  55. data/sidekiq.gemspec +26 -0
  56. data/sr-sidekiq-4.1.3.gem +0 -0
  57. data/sr-sidekiq-4.1.4.gem +0 -0
  58. data/sr-sidekiq-4.1.5.gem +0 -0
  59. data/test/config.yml +9 -0
  60. data/test/env_based_config.yml +11 -0
  61. data/test/fake_env.rb +1 -0
  62. data/test/fixtures/en.yml +2 -0
  63. data/test/helper.rb +75 -0
  64. data/test/test_actors.rb +138 -0
  65. data/test/test_api.rb +528 -0
  66. data/test/test_cli.rb +406 -0
  67. data/test/test_client.rb +262 -0
  68. data/test/test_exception_handler.rb +56 -0
  69. data/test/test_extensions.rb +127 -0
  70. data/test/test_fetch.rb +50 -0
  71. data/test/test_launcher.rb +85 -0
  72. data/test/test_logging.rb +35 -0
  73. data/test/test_manager.rb +50 -0
  74. data/test/test_middleware.rb +158 -0
  75. data/test/test_processor.rb +201 -0
  76. data/test/test_rails.rb +22 -0
  77. data/test/test_redis_connection.rb +127 -0
  78. data/test/test_retry.rb +326 -0
  79. data/test/test_retry_exhausted.rb +149 -0
  80. data/test/test_scheduled.rb +115 -0
  81. data/test/test_scheduling.rb +50 -0
  82. data/test/test_sidekiq.rb +107 -0
  83. data/test/test_testing.rb +143 -0
  84. data/test/test_testing_fake.rb +357 -0
  85. data/test/test_testing_inline.rb +94 -0
  86. data/test/test_util.rb +13 -0
  87. data/test/test_web.rb +614 -0
  88. data/test/test_web_helpers.rb +54 -0
  89. data/web/assets/images/bootstrap/glyphicons-halflings-white.png +0 -0
  90. data/web/assets/images/bootstrap/glyphicons-halflings.png +0 -0
  91. data/web/assets/images/favicon.ico +0 -0
  92. data/web/assets/images/logo.png +0 -0
  93. data/web/assets/images/status-sd8051fd480.png +0 -0
  94. data/web/assets/images/status/active.png +0 -0
  95. data/web/assets/images/status/idle.png +0 -0
  96. data/web/assets/javascripts/application.js +88 -0
  97. data/web/assets/javascripts/dashboard.js +300 -0
  98. data/web/assets/javascripts/locales/README.md +27 -0
  99. data/web/assets/javascripts/locales/jquery.timeago.ar.js +96 -0
  100. data/web/assets/javascripts/locales/jquery.timeago.bg.js +18 -0
  101. data/web/assets/javascripts/locales/jquery.timeago.bs.js +49 -0
  102. data/web/assets/javascripts/locales/jquery.timeago.ca.js +18 -0
  103. data/web/assets/javascripts/locales/jquery.timeago.cs.js +18 -0
  104. data/web/assets/javascripts/locales/jquery.timeago.cy.js +20 -0
  105. data/web/assets/javascripts/locales/jquery.timeago.da.js +18 -0
  106. data/web/assets/javascripts/locales/jquery.timeago.de.js +18 -0
  107. data/web/assets/javascripts/locales/jquery.timeago.el.js +18 -0
  108. data/web/assets/javascripts/locales/jquery.timeago.en-short.js +20 -0
  109. data/web/assets/javascripts/locales/jquery.timeago.en.js +20 -0
  110. data/web/assets/javascripts/locales/jquery.timeago.es.js +18 -0
  111. data/web/assets/javascripts/locales/jquery.timeago.et.js +18 -0
  112. data/web/assets/javascripts/locales/jquery.timeago.fa.js +22 -0
  113. data/web/assets/javascripts/locales/jquery.timeago.fi.js +28 -0
  114. data/web/assets/javascripts/locales/jquery.timeago.fr-short.js +16 -0
  115. data/web/assets/javascripts/locales/jquery.timeago.fr.js +17 -0
  116. data/web/assets/javascripts/locales/jquery.timeago.he.js +18 -0
  117. data/web/assets/javascripts/locales/jquery.timeago.hr.js +49 -0
  118. data/web/assets/javascripts/locales/jquery.timeago.hu.js +18 -0
  119. data/web/assets/javascripts/locales/jquery.timeago.hy.js +18 -0
  120. data/web/assets/javascripts/locales/jquery.timeago.id.js +18 -0
  121. data/web/assets/javascripts/locales/jquery.timeago.it.js +16 -0
  122. data/web/assets/javascripts/locales/jquery.timeago.ja.js +19 -0
  123. data/web/assets/javascripts/locales/jquery.timeago.ko.js +17 -0
  124. data/web/assets/javascripts/locales/jquery.timeago.lt.js +20 -0
  125. data/web/assets/javascripts/locales/jquery.timeago.mk.js +20 -0
  126. data/web/assets/javascripts/locales/jquery.timeago.nl.js +20 -0
  127. data/web/assets/javascripts/locales/jquery.timeago.no.js +18 -0
  128. data/web/assets/javascripts/locales/jquery.timeago.pl.js +31 -0
  129. data/web/assets/javascripts/locales/jquery.timeago.pt-br.js +16 -0
  130. data/web/assets/javascripts/locales/jquery.timeago.pt.js +16 -0
  131. data/web/assets/javascripts/locales/jquery.timeago.ro.js +18 -0
  132. data/web/assets/javascripts/locales/jquery.timeago.rs.js +49 -0
  133. data/web/assets/javascripts/locales/jquery.timeago.ru.js +34 -0
  134. data/web/assets/javascripts/locales/jquery.timeago.sk.js +18 -0
  135. data/web/assets/javascripts/locales/jquery.timeago.sl.js +44 -0
  136. data/web/assets/javascripts/locales/jquery.timeago.sv.js +18 -0
  137. data/web/assets/javascripts/locales/jquery.timeago.th.js +20 -0
  138. data/web/assets/javascripts/locales/jquery.timeago.tr.js +16 -0
  139. data/web/assets/javascripts/locales/jquery.timeago.uk.js +34 -0
  140. data/web/assets/javascripts/locales/jquery.timeago.uz.js +19 -0
  141. data/web/assets/javascripts/locales/jquery.timeago.zh-cn.js +20 -0
  142. data/web/assets/javascripts/locales/jquery.timeago.zh-tw.js +20 -0
  143. data/web/assets/stylesheets/application.css +754 -0
  144. data/web/assets/stylesheets/bootstrap.css +9 -0
  145. data/web/locales/cs.yml +78 -0
  146. data/web/locales/da.yml +68 -0
  147. data/web/locales/de.yml +69 -0
  148. data/web/locales/el.yml +68 -0
  149. data/web/locales/en.yml +79 -0
  150. data/web/locales/es.yml +69 -0
  151. data/web/locales/fr.yml +78 -0
  152. data/web/locales/hi.yml +75 -0
  153. data/web/locales/it.yml +69 -0
  154. data/web/locales/ja.yml +78 -0
  155. data/web/locales/ko.yml +68 -0
  156. data/web/locales/nb.yml +77 -0
  157. data/web/locales/nl.yml +68 -0
  158. data/web/locales/pl.yml +59 -0
  159. data/web/locales/pt-br.yml +68 -0
  160. data/web/locales/pt.yml +67 -0
  161. data/web/locales/ru.yml +78 -0
  162. data/web/locales/sv.yml +68 -0
  163. data/web/locales/ta.yml +75 -0
  164. data/web/locales/uk.yml +76 -0
  165. data/web/locales/zh-cn.yml +68 -0
  166. data/web/locales/zh-tw.yml +68 -0
  167. data/web/views/_footer.erb +17 -0
  168. data/web/views/_job_info.erb +88 -0
  169. data/web/views/_nav.erb +66 -0
  170. data/web/views/_paging.erb +23 -0
  171. data/web/views/_poll_js.erb +5 -0
  172. data/web/views/_poll_link.erb +7 -0
  173. data/web/views/_status.erb +4 -0
  174. data/web/views/_summary.erb +40 -0
  175. data/web/views/busy.erb +94 -0
  176. data/web/views/dashboard.erb +75 -0
  177. data/web/views/dead.erb +34 -0
  178. data/web/views/layout.erb +32 -0
  179. data/web/views/morgue.erb +71 -0
  180. data/web/views/queue.erb +45 -0
  181. data/web/views/queues.erb +28 -0
  182. data/web/views/retries.erb +74 -0
  183. data/web/views/retry.erb +34 -0
  184. data/web/views/scheduled.erb +54 -0
  185. data/web/views/scheduled_job_info.erb +8 -0
  186. metadata +408 -0
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'helper'
3
+ require 'sidekiq/exception_handler'
4
+ require 'stringio'
5
+ require 'logger'
6
+
7
+ ExceptionHandlerTestException = Class.new(StandardError)
8
+ TEST_EXCEPTION = ExceptionHandlerTestException.new("Something didn't work!")
9
+
10
+ class Component
11
+ include Sidekiq::ExceptionHandler
12
+
13
+ def invoke_exception(args)
14
+ raise TEST_EXCEPTION
15
+ rescue ExceptionHandlerTestException => e
16
+ handle_exception(e,args)
17
+ end
18
+ end
19
+
20
+ class TestExceptionHandler < Sidekiq::Test
21
+ describe "with mock logger" do
22
+ before do
23
+ @old_logger = Sidekiq.logger
24
+ @str_logger = StringIO.new
25
+ Sidekiq.logger = Logger.new(@str_logger)
26
+ end
27
+
28
+ after do
29
+ Sidekiq.logger = @old_logger
30
+ end
31
+
32
+ it "logs the exception to Sidekiq.logger" do
33
+ Component.new.invoke_exception(:a => 1)
34
+ @str_logger.rewind
35
+ log = @str_logger.readlines
36
+ assert_match(/"a":1/, log[0], "didn't include the context")
37
+ assert_match(/Something didn't work!/, log[1], "didn't include the exception message")
38
+ assert_match(/test\/test_exception_handler.rb/, log[2], "didn't include the backtrace")
39
+ end
40
+
41
+ describe "when the exception does not have a backtrace" do
42
+ it "does not fail" do
43
+ exception = ExceptionHandlerTestException.new
44
+ assert_nil exception.backtrace
45
+
46
+ begin
47
+ Component.new.handle_exception exception
48
+ pass
49
+ rescue StandardError
50
+ flunk "failed handling a nil backtrace"
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ end
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'helper'
3
+ require 'sidekiq'
4
+ require 'active_record'
5
+ require 'action_mailer'
6
+ require 'sidekiq/extensions/action_mailer'
7
+ require 'sidekiq/extensions/active_record'
8
+ require 'sidekiq/rails'
9
+
10
+ Sidekiq.hook_rails!
11
+
12
+ class TestExtensions < Sidekiq::Test
13
+ describe 'sidekiq extensions' do
14
+ before do
15
+ Sidekiq.redis = REDIS
16
+ Sidekiq.redis {|c| c.flushdb }
17
+ end
18
+
19
+ class MyModel < ActiveRecord::Base
20
+ def self.long_class_method
21
+ raise "Should not be called!"
22
+ end
23
+ end
24
+
25
+ it 'allows delayed execution of ActiveRecord class methods' do
26
+ assert_equal [], Sidekiq::Queue.all.map(&:name)
27
+ q = Sidekiq::Queue.new
28
+ assert_equal 0, q.size
29
+ MyModel.delay.long_class_method
30
+ assert_equal ['default'], Sidekiq::Queue.all.map(&:name)
31
+ assert_equal 1, q.size
32
+ end
33
+
34
+ it 'uses and stringifies specified options' do
35
+ assert_equal [], Sidekiq::Queue.all.map(&:name)
36
+ q = Sidekiq::Queue.new('notdefault')
37
+ assert_equal 0, q.size
38
+ MyModel.delay(queue: :notdefault).long_class_method
39
+ assert_equal ['notdefault'], Sidekiq::Queue.all.map(&:name)
40
+ assert_equal 1, q.size
41
+ end
42
+
43
+ it 'allows delayed scheduling of AR class methods' do
44
+ ss = Sidekiq::ScheduledSet.new
45
+ assert_equal 0, ss.size
46
+ MyModel.delay_for(5.days).long_class_method
47
+ assert_equal 1, ss.size
48
+ end
49
+
50
+ it 'allows until delayed scheduling of AR class methods' do
51
+ ss = Sidekiq::ScheduledSet.new
52
+ assert_equal 0, ss.size
53
+ MyModel.delay_until(1.day.from_now).long_class_method
54
+ assert_equal 1, ss.size
55
+ end
56
+
57
+ class UserMailer < ActionMailer::Base
58
+ def greetings(a, b)
59
+ raise "Should not be called!"
60
+ end
61
+ end
62
+
63
+ it 'allows delayed delivery of ActionMailer mails' do
64
+ assert_equal [], Sidekiq::Queue.all.map(&:name)
65
+ q = Sidekiq::Queue.new
66
+ assert_equal 0, q.size
67
+ UserMailer.delay.greetings(1, 2)
68
+ assert_equal ['default'], Sidekiq::Queue.all.map(&:name)
69
+ assert_equal 1, q.size
70
+ end
71
+
72
+ it 'allows delayed scheduling of AM mails' do
73
+ ss = Sidekiq::ScheduledSet.new
74
+ assert_equal 0, ss.size
75
+ UserMailer.delay_for(5.days).greetings(1, 2)
76
+ assert_equal 1, ss.size
77
+ end
78
+
79
+ it 'allows until delay scheduling of AM mails' do
80
+ ss = Sidekiq::ScheduledSet.new
81
+ assert_equal 0, ss.size
82
+ UserMailer.delay_until(5.days.from_now).greetings(1, 2)
83
+ assert_equal 1, ss.size
84
+ end
85
+
86
+ class SomeClass
87
+ def self.doit(arg)
88
+ end
89
+ end
90
+
91
+ it 'allows delay of any ole class method' do
92
+ q = Sidekiq::Queue.new
93
+ assert_equal 0, q.size
94
+ SomeClass.delay.doit(Date.today)
95
+ assert_equal 1, q.size
96
+ end
97
+
98
+ module SomeModule
99
+ def self.doit(arg)
100
+ end
101
+ end
102
+
103
+ it 'allows delay of any module class method' do
104
+ q = Sidekiq::Queue.new
105
+ assert_equal 0, q.size
106
+ SomeModule.delay.doit(Date.today)
107
+ assert_equal 1, q.size
108
+ end
109
+
110
+ it 'allows removing of the #delay methods' do
111
+ q = Sidekiq::Queue.new
112
+ Sidekiq.remove_delay!
113
+ assert_equal 0, q.size
114
+ assert_raises NoMethodError do
115
+ SomeModule.delay.doit(Date.today)
116
+ end
117
+
118
+ Sidekiq.instance_eval { remove_instance_variable :@delay_removed }
119
+ # Reload modified modules
120
+ load 'sidekiq/extensions/action_mailer.rb'
121
+ load 'sidekiq/extensions/active_record.rb'
122
+ load 'sidekiq/extensions/generic_proxy.rb'
123
+ load 'sidekiq/extensions/class_methods.rb'
124
+ end
125
+ end
126
+
127
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'helper'
3
+ require 'sidekiq/fetch'
4
+
5
+ class TestFetcher < Sidekiq::Test
6
+ describe 'fetcher' do
7
+ before do
8
+ Sidekiq.redis = { :url => REDIS_URL, :namespace => 'fuzzy' }
9
+ Sidekiq.redis do |conn|
10
+ conn.flushdb
11
+ conn.rpush('queue:basic', 'msg')
12
+ end
13
+ end
14
+
15
+ after do
16
+ Sidekiq.redis = REDIS
17
+ end
18
+
19
+ it 'retrieves' do
20
+ fetch = Sidekiq::BasicFetch.new(:queues => ['basic', 'bar'])
21
+ uow = fetch.retrieve_work
22
+ refute_nil uow
23
+ assert_equal 'basic', uow.queue_name
24
+ assert_equal 'msg', uow.job
25
+ q = Sidekiq::Queue.new('basic')
26
+ assert_equal 0, q.size
27
+ uow.requeue
28
+ assert_equal 1, q.size
29
+ assert_nil uow.acknowledge
30
+ end
31
+
32
+ it 'retrieves with strict setting' do
33
+ fetch = Sidekiq::BasicFetch.new(:queues => ['basic', 'bar', 'bar'], :strict => true)
34
+ cmd = fetch.queues_cmd
35
+ assert_equal cmd, ['queue:basic', 'queue:bar', Sidekiq::BasicFetch::TIMEOUT]
36
+ end
37
+
38
+ it 'bulk requeues' do
39
+ q1 = Sidekiq::Queue.new('foo')
40
+ q2 = Sidekiq::Queue.new('bar')
41
+ assert_equal 0, q1.size
42
+ assert_equal 0, q2.size
43
+ uow = Sidekiq::BasicFetch::UnitOfWork
44
+ Sidekiq::BasicFetch.bulk_requeue([uow.new('fuzzy:queue:foo', 'bob'), uow.new('fuzzy:queue:foo', 'bar'), uow.new('fuzzy:queue:bar', 'widget')], {:queues => []})
45
+ assert_equal 2, q1.size
46
+ assert_equal 1, q2.size
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'helper'
3
+ require 'sidekiq/launcher'
4
+
5
+ class TestLauncher < Sidekiq::Test
6
+
7
+ describe 'launcher' do
8
+ before do
9
+ Sidekiq.redis {|c| c.flushdb }
10
+ end
11
+
12
+ def new_manager(opts)
13
+ Sidekiq::Manager.new(opts)
14
+ end
15
+
16
+ describe 'heartbeat' do
17
+ before do
18
+ uow = Object.new
19
+
20
+ @mgr = new_manager(options)
21
+ @launcher = Sidekiq::Launcher.new(options)
22
+ @launcher.manager = @mgr
23
+
24
+ Sidekiq::Processor::WORKER_STATE['a'] = {'b' => 1}
25
+
26
+ @proctitle = $0
27
+ end
28
+
29
+ after do
30
+ Sidekiq::Processor::WORKER_STATE.clear
31
+ $0 = @proctitle
32
+ end
33
+
34
+ describe 'when manager is active' do
35
+ before do
36
+ Sidekiq::CLI::PROCTITLES << proc { "xyz" }
37
+ @launcher.heartbeat('identity', heartbeat_data, Sidekiq.dump_json(heartbeat_data))
38
+ Sidekiq::CLI::PROCTITLES.pop
39
+ end
40
+
41
+ it 'sets useful info to proctitle' do
42
+ assert_equal "sidekiq #{Sidekiq::VERSION} myapp [1 of 3 busy] xyz", $0
43
+ end
44
+
45
+ it 'stores process info in redis' do
46
+ info = Sidekiq.redis { |c| c.hmget('identity', 'busy') }
47
+ assert_equal ["1"], info
48
+ expires = Sidekiq.redis { |c| c.pttl('identity') }
49
+ assert_in_delta 60000, expires, 500
50
+ end
51
+ end
52
+
53
+ describe 'when manager is stopped' do
54
+ before do
55
+ @launcher.quiet
56
+ @launcher.heartbeat('identity', heartbeat_data, Sidekiq.dump_json(heartbeat_data))
57
+ end
58
+
59
+ #after do
60
+ #puts system('redis-cli -n 15 keys "*" | while read LINE ; do TTL=`redis-cli -n 15 ttl "$LINE"`; if [ "$TTL" -eq -1 ]; then echo "$LINE"; fi; done;')
61
+ #end
62
+
63
+ it 'indicates stopping status in proctitle' do
64
+ assert_equal "sidekiq #{Sidekiq::VERSION} myapp [1 of 3 busy] stopping", $0
65
+ end
66
+
67
+ it 'stores process info in redis' do
68
+ info = Sidekiq.redis { |c| c.hmget('identity', 'busy') }
69
+ assert_equal ["1"], info
70
+ expires = Sidekiq.redis { |c| c.pttl('identity') }
71
+ assert_in_delta 60000, expires, 50
72
+ end
73
+ end
74
+ end
75
+
76
+ def options
77
+ { :concurrency => 3, :queues => ['default'] }
78
+ end
79
+
80
+ def heartbeat_data
81
+ { 'concurrency' => 3, 'tag' => 'myapp' }
82
+ end
83
+ end
84
+
85
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'helper'
3
+ require 'sidekiq/logging'
4
+
5
+ class TestLogging < Sidekiq::Test
6
+ describe Sidekiq::Logging do
7
+ describe "#with_context" do
8
+ def context
9
+ Sidekiq::Logging.logger.formatter.context
10
+ end
11
+
12
+ it "has no context by default" do
13
+ context.must_equal nil
14
+ end
15
+
16
+ it "can add a context" do
17
+ Sidekiq::Logging.with_context "xx" do
18
+ context.must_equal " xx"
19
+ end
20
+ context.must_equal nil
21
+ end
22
+
23
+ it "can use multiple contexts" do
24
+ Sidekiq::Logging.with_context "xx" do
25
+ context.must_equal " xx"
26
+ Sidekiq::Logging.with_context "yy" do
27
+ context.must_equal " xx yy"
28
+ end
29
+ context.must_equal " xx"
30
+ end
31
+ context.must_equal nil
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'helper'
3
+ require 'sidekiq/manager'
4
+
5
+ class TestManager < Sidekiq::Test
6
+
7
+ describe 'manager' do
8
+ before do
9
+ Sidekiq.redis {|c| c.flushdb }
10
+ end
11
+
12
+ def new_manager(opts)
13
+ Sidekiq::Manager.new(opts)
14
+ end
15
+
16
+ it 'creates N processor instances' do
17
+ mgr = new_manager(options)
18
+ assert_equal options[:concurrency], mgr.workers.size
19
+ end
20
+
21
+ it 'shuts down the system' do
22
+ mgr = new_manager(options)
23
+ mgr.stop(Time.now)
24
+ end
25
+
26
+ it 'throws away dead processors' do
27
+ mgr = new_manager(options)
28
+ init_size = mgr.workers.size
29
+ processor = mgr.workers.first
30
+ begin
31
+ mgr.processor_died(processor, 'ignored')
32
+
33
+ assert_equal init_size, mgr.workers.size
34
+ refute mgr.workers.include?(processor)
35
+ ensure
36
+ mgr.workers.each {|p| p.terminate(true) }
37
+ end
38
+ end
39
+
40
+ it 'does not support invalid concurrency' do
41
+ assert_raises(ArgumentError) { new_manager(concurrency: 0) }
42
+ assert_raises(ArgumentError) { new_manager(concurrency: -1) }
43
+ end
44
+
45
+ def options
46
+ { :concurrency => 3, :queues => ['default'] }
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,158 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'helper'
3
+ require 'sidekiq/middleware/chain'
4
+ require 'sidekiq/processor'
5
+
6
+ class TestMiddleware < Sidekiq::Test
7
+ describe 'middleware chain' do
8
+ before do
9
+ $errors = []
10
+ Sidekiq.redis = REDIS
11
+ end
12
+
13
+ class CustomMiddleware
14
+ def initialize(name, recorder)
15
+ @name = name
16
+ @recorder = recorder
17
+ end
18
+
19
+ def call(*args)
20
+ @recorder << [@name, 'before']
21
+ yield
22
+ @recorder << [@name, 'after']
23
+ end
24
+ end
25
+
26
+ it 'supports custom middleware' do
27
+ chain = Sidekiq::Middleware::Chain.new
28
+ chain.add CustomMiddleware, 1, []
29
+
30
+ assert_equal CustomMiddleware, chain.entries.last.klass
31
+ end
32
+
33
+ class CustomWorker
34
+ $recorder = []
35
+ include Sidekiq::Worker
36
+ def perform(recorder)
37
+ $recorder << ['work_performed']
38
+ end
39
+ end
40
+
41
+ class NonYieldingMiddleware
42
+ def call(*args)
43
+ end
44
+ end
45
+
46
+ class AnotherCustomMiddleware
47
+ def initialize(name, recorder)
48
+ @name = name
49
+ @recorder = recorder
50
+ end
51
+
52
+ def call(*args)
53
+ @recorder << [@name, 'before']
54
+ yield
55
+ @recorder << [@name, 'after']
56
+ end
57
+ end
58
+
59
+ class YetAnotherCustomMiddleware
60
+ def initialize(name, recorder)
61
+ @name = name
62
+ @recorder = recorder
63
+ end
64
+
65
+ def call(*args)
66
+ @recorder << [@name, 'before']
67
+ yield
68
+ @recorder << [@name, 'after']
69
+ end
70
+ end
71
+
72
+ it 'executes middleware in the proper order' do
73
+ msg = Sidekiq.dump_json({ 'class' => CustomWorker.to_s, 'args' => [$recorder] })
74
+
75
+ Sidekiq.server_middleware do |chain|
76
+ # should only add once, second should replace the first
77
+ 2.times { |i| chain.add CustomMiddleware, i.to_s, $recorder }
78
+ chain.insert_before CustomMiddleware, AnotherCustomMiddleware, '2', $recorder
79
+ chain.insert_after AnotherCustomMiddleware, YetAnotherCustomMiddleware, '3', $recorder
80
+ end
81
+
82
+ boss = Minitest::Mock.new
83
+ boss.expect(:options, {:queues => ['default'] }, [])
84
+ boss.expect(:options, {:queues => ['default'] }, [])
85
+ processor = Sidekiq::Processor.new(boss)
86
+ boss.expect(:processor_done, nil, [processor])
87
+ processor.process(Sidekiq::BasicFetch::UnitOfWork.new('queue:default', msg))
88
+ assert_equal %w(2 before 3 before 1 before work_performed 1 after 3 after 2 after), $recorder.flatten
89
+ end
90
+
91
+ it 'correctly replaces middleware when using middleware with options in the initializer' do
92
+ chain = Sidekiq::Middleware::Chain.new
93
+ chain.add Sidekiq::Middleware::Server::RetryJobs
94
+ chain.add Sidekiq::Middleware::Server::RetryJobs, {:max_retries => 5}
95
+ assert_equal 1, chain.count
96
+ end
97
+
98
+ it 'correctly prepends middleware' do
99
+ chain = Sidekiq::Middleware::Chain.new
100
+ chain_entries = chain.entries
101
+ chain.add CustomMiddleware
102
+ chain.prepend YetAnotherCustomMiddleware
103
+ assert_equal YetAnotherCustomMiddleware, chain_entries.first.klass
104
+ assert_equal CustomMiddleware, chain_entries.last.klass
105
+ end
106
+
107
+ it 'allows middleware to abruptly stop processing rest of chain' do
108
+ recorder = []
109
+ chain = Sidekiq::Middleware::Chain.new
110
+ chain.add NonYieldingMiddleware
111
+ chain.add CustomMiddleware, 1, recorder
112
+
113
+ final_action = nil
114
+ chain.invoke { final_action = true }
115
+ assert_equal nil, final_action
116
+ assert_equal [], recorder
117
+ end
118
+ end
119
+
120
+ describe 'i18n' do
121
+ before do
122
+ require 'i18n'
123
+ I18n.enforce_available_locales = false
124
+ require 'sidekiq/middleware/i18n'
125
+ end
126
+
127
+ it 'saves and restores locale' do
128
+ I18n.locale = 'fr'
129
+ msg = {}
130
+ mw = Sidekiq::Middleware::I18n::Client.new
131
+ mw.call(nil, msg, nil, nil) { }
132
+ assert_equal :fr, msg['locale']
133
+
134
+ msg['locale'] = 'jp'
135
+ I18n.locale = I18n.default_locale
136
+ assert_equal :en, I18n.locale
137
+ mw = Sidekiq::Middleware::I18n::Server.new
138
+ mw.call(nil, msg, nil) do
139
+ assert_equal :jp, I18n.locale
140
+ end
141
+ assert_equal :en, I18n.locale
142
+ end
143
+
144
+ it 'supports I18n.enforce_available_locales = true' do
145
+ I18n.enforce_available_locales = true
146
+ I18n.available_locales = [:en, :jp]
147
+
148
+ msg = { 'locale' => 'jp' }
149
+ mw = Sidekiq::Middleware::I18n::Server.new
150
+ mw.call(nil, msg, nil) do
151
+ assert_equal :jp, I18n.locale
152
+ end
153
+
154
+ I18n.enforce_available_locales = false
155
+ I18n.available_locales = nil
156
+ end
157
+ end
158
+ end