sidekiq_cleaner 5.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +61 -0
  3. data/.github/contributing.md +32 -0
  4. data/.github/issue_template.md +11 -0
  5. data/.gitignore +15 -0
  6. data/.travis.yml +11 -0
  7. data/3.0-Upgrade.md +70 -0
  8. data/4.0-Upgrade.md +53 -0
  9. data/5.0-Upgrade.md +56 -0
  10. data/COMM-LICENSE +97 -0
  11. data/Changes.md +1536 -0
  12. data/Ent-Changes.md +238 -0
  13. data/Gemfile +23 -0
  14. data/LICENSE +9 -0
  15. data/Pro-2.0-Upgrade.md +138 -0
  16. data/Pro-3.0-Upgrade.md +44 -0
  17. data/Pro-4.0-Upgrade.md +35 -0
  18. data/Pro-Changes.md +759 -0
  19. data/README.md +55 -0
  20. data/Rakefile +9 -0
  21. data/bin/sidekiq +18 -0
  22. data/bin/sidekiqctl +20 -0
  23. data/bin/sidekiqload +149 -0
  24. data/cleaner/assets/images/favicon.ico +0 -0
  25. data/cleaner/assets/images/logo.png +0 -0
  26. data/cleaner/assets/images/status.png +0 -0
  27. data/cleaner/assets/javascripts/application.js +172 -0
  28. data/cleaner/assets/javascripts/dashboard.js +315 -0
  29. data/cleaner/assets/stylesheets/application-rtl.css +246 -0
  30. data/cleaner/assets/stylesheets/application.css +1144 -0
  31. data/cleaner/assets/stylesheets/bootstrap-rtl.min.css +9 -0
  32. data/cleaner/assets/stylesheets/bootstrap.css +5 -0
  33. data/cleaner/locales/ar.yml +81 -0
  34. data/cleaner/locales/cs.yml +78 -0
  35. data/cleaner/locales/da.yml +68 -0
  36. data/cleaner/locales/de.yml +69 -0
  37. data/cleaner/locales/el.yml +68 -0
  38. data/cleaner/locales/en.yml +81 -0
  39. data/cleaner/locales/es.yml +70 -0
  40. data/cleaner/locales/fa.yml +80 -0
  41. data/cleaner/locales/fr.yml +78 -0
  42. data/cleaner/locales/he.yml +79 -0
  43. data/cleaner/locales/hi.yml +75 -0
  44. data/cleaner/locales/it.yml +69 -0
  45. data/cleaner/locales/ja.yml +80 -0
  46. data/cleaner/locales/ko.yml +68 -0
  47. data/cleaner/locales/nb.yml +77 -0
  48. data/cleaner/locales/nl.yml +68 -0
  49. data/cleaner/locales/pl.yml +59 -0
  50. data/cleaner/locales/pt-br.yml +68 -0
  51. data/cleaner/locales/pt.yml +67 -0
  52. data/cleaner/locales/ru.yml +78 -0
  53. data/cleaner/locales/sv.yml +68 -0
  54. data/cleaner/locales/ta.yml +75 -0
  55. data/cleaner/locales/uk.yml +76 -0
  56. data/cleaner/locales/ur.yml +80 -0
  57. data/cleaner/locales/zh-cn.yml +68 -0
  58. data/cleaner/locales/zh-tw.yml +68 -0
  59. data/cleaner/views/_footer.erb +20 -0
  60. data/cleaner/views/_job_info.erb +88 -0
  61. data/cleaner/views/_nav.erb +52 -0
  62. data/cleaner/views/_paging.erb +23 -0
  63. data/cleaner/views/_poll_link.erb +7 -0
  64. data/cleaner/views/_status.erb +4 -0
  65. data/cleaner/views/_summary.erb +40 -0
  66. data/cleaner/views/busy.erb +98 -0
  67. data/cleaner/views/dashboard.erb +75 -0
  68. data/cleaner/views/dead.erb +34 -0
  69. data/cleaner/views/errors.erb +84 -0
  70. data/cleaner/views/layout.erb +40 -0
  71. data/cleaner/views/morgue.erb +75 -0
  72. data/cleaner/views/queue.erb +46 -0
  73. data/cleaner/views/queues.erb +30 -0
  74. data/cleaner/views/retries.erb +80 -0
  75. data/cleaner/views/retry.erb +34 -0
  76. data/cleaner/views/scheduled.erb +54 -0
  77. data/cleaner/views/scheduled_job_info.erb +8 -0
  78. data/cleaner-stats.png +0 -0
  79. data/cleaner.png +0 -0
  80. data/code_of_conduct.md +50 -0
  81. data/lib/generators/sidekiq/templates/worker.rb.erb +9 -0
  82. data/lib/generators/sidekiq/templates/worker_spec.rb.erb +6 -0
  83. data/lib/generators/sidekiq/templates/worker_test.rb.erb +8 -0
  84. data/lib/generators/sidekiq/worker_generator.rb +49 -0
  85. data/lib/sidekiq/api.rb +940 -0
  86. data/lib/sidekiq/cleaner/action.rb +89 -0
  87. data/lib/sidekiq/cleaner/application.rb +385 -0
  88. data/lib/sidekiq/cleaner/helpers.rb +325 -0
  89. data/lib/sidekiq/cleaner/router.rb +100 -0
  90. data/lib/sidekiq/cleaner.rb +214 -0
  91. data/lib/sidekiq/cli.rb +445 -0
  92. data/lib/sidekiq/client.rb +243 -0
  93. data/lib/sidekiq/core_ext.rb +1 -0
  94. data/lib/sidekiq/ctl.rb +221 -0
  95. data/lib/sidekiq/delay.rb +42 -0
  96. data/lib/sidekiq/exception_handler.rb +29 -0
  97. data/lib/sidekiq/extensions/action_mailer.rb +57 -0
  98. data/lib/sidekiq/extensions/active_record.rb +40 -0
  99. data/lib/sidekiq/extensions/class_methods.rb +40 -0
  100. data/lib/sidekiq/extensions/generic_proxy.rb +31 -0
  101. data/lib/sidekiq/fetch.rb +81 -0
  102. data/lib/sidekiq/job_logger.rb +25 -0
  103. data/lib/sidekiq/job_retry.rb +262 -0
  104. data/lib/sidekiq/launcher.rb +173 -0
  105. data/lib/sidekiq/logging.rb +122 -0
  106. data/lib/sidekiq/manager.rb +137 -0
  107. data/lib/sidekiq/middleware/chain.rb +150 -0
  108. data/lib/sidekiq/middleware/i18n.rb +42 -0
  109. data/lib/sidekiq/middleware/server/active_record.rb +23 -0
  110. data/lib/sidekiq/paginator.rb +43 -0
  111. data/lib/sidekiq/processor.rb +279 -0
  112. data/lib/sidekiq/rails.rb +58 -0
  113. data/lib/sidekiq/redis_connection.rb +144 -0
  114. data/lib/sidekiq/scheduled.rb +174 -0
  115. data/lib/sidekiq/testing/inline.rb +29 -0
  116. data/lib/sidekiq/testing.rb +333 -0
  117. data/lib/sidekiq/util.rb +66 -0
  118. data/lib/sidekiq/version.rb +4 -0
  119. data/lib/sidekiq/worker.rb +220 -0
  120. data/lib/sidekiq.rb +237 -0
  121. data/sidekiq_cleaner.gemspec +21 -0
  122. metadata +235 -0
@@ -0,0 +1,150 @@
1
+ # frozen_string_literal: true
2
+ module Sidekiq
3
+ # Middleware is code configured to run before/after
4
+ # a message is processed. It is patterned after Rack
5
+ # middleware. Middleware exists for the client side
6
+ # (pushing jobs onto the queue) as well as the server
7
+ # side (when jobs are actually processed).
8
+ #
9
+ # To add middleware for the client:
10
+ #
11
+ # Sidekiq.configure_client do |config|
12
+ # config.client_middleware do |chain|
13
+ # chain.add MyClientHook
14
+ # end
15
+ # end
16
+ #
17
+ # To modify middleware for the server, just call
18
+ # with another block:
19
+ #
20
+ # Sidekiq.configure_server do |config|
21
+ # config.server_middleware do |chain|
22
+ # chain.add MyServerHook
23
+ # chain.remove ActiveRecord
24
+ # end
25
+ # end
26
+ #
27
+ # To insert immediately preceding another entry:
28
+ #
29
+ # Sidekiq.configure_client do |config|
30
+ # config.client_middleware do |chain|
31
+ # chain.insert_before ActiveRecord, MyClientHook
32
+ # end
33
+ # end
34
+ #
35
+ # To insert immediately after another entry:
36
+ #
37
+ # Sidekiq.configure_client do |config|
38
+ # config.client_middleware do |chain|
39
+ # chain.insert_after ActiveRecord, MyClientHook
40
+ # end
41
+ # end
42
+ #
43
+ # This is an example of a minimal server middleware:
44
+ #
45
+ # class MyServerHook
46
+ # def call(worker_instance, msg, queue)
47
+ # puts "Before work"
48
+ # yield
49
+ # puts "After work"
50
+ # end
51
+ # end
52
+ #
53
+ # This is an example of a minimal client middleware, note
54
+ # the method must return the result or the job will not push
55
+ # to Redis:
56
+ #
57
+ # class MyClientHook
58
+ # def call(worker_class, msg, queue, redis_pool)
59
+ # puts "Before push"
60
+ # result = yield
61
+ # puts "After push"
62
+ # result
63
+ # end
64
+ # end
65
+ #
66
+ module Middleware
67
+ class Chain
68
+ include Enumerable
69
+ attr_reader :entries
70
+
71
+ def initialize_copy(copy)
72
+ copy.instance_variable_set(:@entries, entries.dup)
73
+ end
74
+
75
+ def each(&block)
76
+ entries.each(&block)
77
+ end
78
+
79
+ def initialize
80
+ @entries = []
81
+ yield self if block_given?
82
+ end
83
+
84
+ def remove(klass)
85
+ entries.delete_if { |entry| entry.klass == klass }
86
+ end
87
+
88
+ def add(klass, *args)
89
+ remove(klass) if exists?(klass)
90
+ entries << Entry.new(klass, *args)
91
+ end
92
+
93
+ def prepend(klass, *args)
94
+ remove(klass) if exists?(klass)
95
+ entries.insert(0, Entry.new(klass, *args))
96
+ end
97
+
98
+ def insert_before(oldklass, newklass, *args)
99
+ i = entries.index { |entry| entry.klass == newklass }
100
+ new_entry = i.nil? ? Entry.new(newklass, *args) : entries.delete_at(i)
101
+ i = entries.index { |entry| entry.klass == oldklass } || 0
102
+ entries.insert(i, new_entry)
103
+ end
104
+
105
+ def insert_after(oldklass, newklass, *args)
106
+ i = entries.index { |entry| entry.klass == newklass }
107
+ new_entry = i.nil? ? Entry.new(newklass, *args) : entries.delete_at(i)
108
+ i = entries.index { |entry| entry.klass == oldklass } || entries.count - 1
109
+ entries.insert(i+1, new_entry)
110
+ end
111
+
112
+ def exists?(klass)
113
+ any? { |entry| entry.klass == klass }
114
+ end
115
+
116
+ def retrieve
117
+ map(&:make_new)
118
+ end
119
+
120
+ def clear
121
+ entries.clear
122
+ end
123
+
124
+ def invoke(*args)
125
+ chain = retrieve.dup
126
+ traverse_chain = lambda do
127
+ if chain.empty?
128
+ yield
129
+ else
130
+ chain.shift.call(*args, &traverse_chain)
131
+ end
132
+ end
133
+ traverse_chain.call
134
+ end
135
+ end
136
+
137
+ class Entry
138
+ attr_reader :klass
139
+
140
+ def initialize(klass, *args)
141
+ @klass = klass
142
+ @args = args
143
+ end
144
+
145
+ def make_new
146
+ @klass.new(*@args)
147
+ end
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Simple middleware to save the current locale and restore it when the job executes.
4
+ # Use it by requiring it in your initializer:
5
+ #
6
+ # require 'sidekiq/middleware/i18n'
7
+ #
8
+ module Sidekiq::Middleware::I18n
9
+ # Get the current locale and store it in the message
10
+ # to be sent to Sidekiq.
11
+ class Client
12
+ def call(worker_class, msg, queue, redis_pool)
13
+ msg['locale'] ||= I18n.locale
14
+ yield
15
+ end
16
+ end
17
+
18
+ # Pull the msg locale out and set the current thread to use it.
19
+ class Server
20
+ def call(worker, msg, queue)
21
+ I18n.locale = msg['locale'] || I18n.default_locale
22
+ yield
23
+ ensure
24
+ I18n.locale = I18n.default_locale
25
+ end
26
+ end
27
+ end
28
+
29
+ Sidekiq.configure_client do |config|
30
+ config.client_middleware do |chain|
31
+ chain.add Sidekiq::Middleware::I18n::Client
32
+ end
33
+ end
34
+
35
+ Sidekiq.configure_server do |config|
36
+ config.client_middleware do |chain|
37
+ chain.add Sidekiq::Middleware::I18n::Client
38
+ end
39
+ config.server_middleware do |chain|
40
+ chain.add Sidekiq::Middleware::I18n::Server
41
+ end
42
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+ module Sidekiq
3
+ module Middleware
4
+ module Server
5
+ class ActiveRecord
6
+
7
+ def initialize
8
+ # With Rails 5+ we must use the Reloader **always**.
9
+ # The reloader handles code loading and db connection management.
10
+ if defined?(::Rails) && ::Rails::VERSION::MAJOR >= 5
11
+ raise ArgumentError, "Rails 5 no longer needs or uses the ActiveRecord middleware."
12
+ end
13
+ end
14
+
15
+ def call(*args)
16
+ yield
17
+ ensure
18
+ ::ActiveRecord::Base.clear_active_connections!
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+ module Sidekiq
3
+ module Paginator
4
+
5
+ def page(key, pageidx=1, page_size=25, opts=nil)
6
+ current_page = pageidx.to_i < 1 ? 1 : pageidx.to_i
7
+ pageidx = current_page - 1
8
+ total_size = 0
9
+ items = []
10
+ starting = pageidx * page_size
11
+ ending = starting + page_size - 1
12
+
13
+ Sidekiq.redis do |conn|
14
+ type = conn.type(key)
15
+
16
+ case type
17
+ when 'zset'
18
+ rev = opts && opts[:reverse]
19
+ total_size, items = conn.multi do
20
+ conn.zcard(key)
21
+ if rev
22
+ conn.zrevrange(key, starting, ending, :with_scores => true)
23
+ else
24
+ conn.zrange(key, starting, ending, :with_scores => true)
25
+ end
26
+ end
27
+ [current_page, total_size, items]
28
+ when 'list'
29
+ total_size, items = conn.multi do
30
+ conn.llen(key)
31
+ conn.lrange(key, starting, ending)
32
+ end
33
+ [current_page, total_size, items]
34
+ when 'none'
35
+ [1, 0, []]
36
+ else
37
+ raise "can't page a #{type}"
38
+ end
39
+ end
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,279 @@
1
+ # frozen_string_literal: true
2
+ require 'sidekiq/util'
3
+ require 'sidekiq/fetch'
4
+ require 'sidekiq/job_logger'
5
+ require 'sidekiq/job_retry'
6
+ require 'thread'
7
+
8
+ module Sidekiq
9
+ ##
10
+ # The Processor is a standalone thread which:
11
+ #
12
+ # 1. fetches a job from Redis
13
+ # 2. executes the job
14
+ # a. instantiate the Worker
15
+ # b. run the middleware chain
16
+ # c. call #perform
17
+ #
18
+ # A Processor can exit due to shutdown (processor_stopped)
19
+ # or due to an error during job execution (processor_died)
20
+ #
21
+ # If an error occurs in the job execution, the
22
+ # Processor calls the Manager to create a new one
23
+ # to replace itself and exits.
24
+ #
25
+ class Processor
26
+
27
+ include Util
28
+
29
+ attr_reader :thread
30
+ attr_reader :job
31
+
32
+ def initialize(mgr)
33
+ @mgr = mgr
34
+ @down = false
35
+ @done = false
36
+ @job = nil
37
+ @thread = nil
38
+ @strategy = (mgr.options[:fetch] || Sidekiq::BasicFetch).new(mgr.options)
39
+ @reloader = Sidekiq.options[:reloader]
40
+ @logging = (mgr.options[:job_logger] || Sidekiq::JobLogger).new
41
+ @retrier = Sidekiq::JobRetry.new
42
+ end
43
+
44
+ def terminate(wait=false)
45
+ @done = true
46
+ return if !@thread
47
+ @thread.value if wait
48
+ end
49
+
50
+ def kill(wait=false)
51
+ @done = true
52
+ return if !@thread
53
+ # unlike the other actors, terminate does not wait
54
+ # for the thread to finish because we don't know how
55
+ # long the job will take to finish. Instead we
56
+ # provide a `kill` method to call after the shutdown
57
+ # timeout passes.
58
+ @thread.raise ::Sidekiq::Shutdown
59
+ @thread.value if wait
60
+ end
61
+
62
+ def start
63
+ @thread ||= safe_thread("processor", &method(:run))
64
+ end
65
+
66
+ private unless $TESTING
67
+
68
+ def run
69
+ begin
70
+ while !@done
71
+ process_one
72
+ end
73
+ @mgr.processor_stopped(self)
74
+ rescue Sidekiq::Shutdown
75
+ @mgr.processor_stopped(self)
76
+ rescue Exception => ex
77
+ @mgr.processor_died(self, ex)
78
+ end
79
+ end
80
+
81
+ def process_one
82
+ @job = fetch
83
+ process(@job) if @job
84
+ @job = nil
85
+ end
86
+
87
+ def get_one
88
+ begin
89
+ work = @strategy.retrieve_work
90
+ (logger.info { "Redis is online, #{::Process.clock_gettime(::Process::CLOCK_MONOTONIC) - @down} sec downtime" }; @down = nil) if @down
91
+ work
92
+ rescue Sidekiq::Shutdown
93
+ rescue => ex
94
+ handle_fetch_exception(ex)
95
+ end
96
+ end
97
+
98
+ def fetch
99
+ j = get_one
100
+ if j && @done
101
+ j.requeue
102
+ nil
103
+ else
104
+ j
105
+ end
106
+ end
107
+
108
+ def handle_fetch_exception(ex)
109
+ if !@down
110
+ @down = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
111
+ logger.error("Error fetching job: #{ex}")
112
+ handle_exception(ex)
113
+ end
114
+ sleep(1)
115
+ nil
116
+ end
117
+
118
+ def dispatch(job_hash, queue)
119
+ # since middleware can mutate the job hash
120
+ # we clone here so we report the original
121
+ # job structure to the Web UI
122
+ pristine = cloned(job_hash)
123
+
124
+ Sidekiq::Logging.with_job_hash_context(job_hash) do
125
+ @retrier.global(pristine, queue) do
126
+ @logging.call(job_hash, queue) do
127
+ stats(pristine, queue) do
128
+ # Rails 5 requires a Reloader to wrap code execution. In order to
129
+ # constantize the worker and instantiate an instance, we have to call
130
+ # the Reloader. It handles code loading, db connection management, etc.
131
+ # Effectively this block denotes a "unit of work" to Rails.
132
+ @reloader.call do
133
+ klass = constantize(job_hash['class'])
134
+ worker = klass.new
135
+ worker.jid = job_hash['jid']
136
+ @retrier.local(worker, pristine, queue) do
137
+ yield worker
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
145
+
146
+ def process(work)
147
+ jobstr = work.job
148
+ queue = work.queue_name
149
+
150
+ # Treat malformed JSON as a special case: job goes straight to the morgue.
151
+ job_hash = nil
152
+ begin
153
+ job_hash = Sidekiq.load_json(jobstr)
154
+ rescue => ex
155
+ handle_exception(ex, { :context => "Invalid JSON for job", :jobstr => jobstr })
156
+ # we can't notify because the job isn't a valid hash payload.
157
+ DeadSet.new.kill(jobstr, notify_failure: false)
158
+ return work.acknowledge
159
+ end
160
+
161
+ ack = true
162
+ begin
163
+ dispatch(job_hash, queue) do |worker|
164
+ Sidekiq.server_middleware.invoke(worker, job_hash, queue) do
165
+ execute_job(worker, cloned(job_hash['args']))
166
+ end
167
+ end
168
+ rescue Sidekiq::Shutdown
169
+ # Had to force kill this job because it didn't finish
170
+ # within the timeout. Don't acknowledge the work since
171
+ # we didn't properly finish it.
172
+ ack = false
173
+ rescue Sidekiq::JobRetry::Handled => h
174
+ # this is the common case: job raised error and Sidekiq::JobRetry::Handled
175
+ # signals that we created a retry successfully. We can acknowlege the job.
176
+ e = h.cause ? h.cause : h
177
+ handle_exception(e, { :context => "Job raised exception", :job => job_hash, :jobstr => jobstr })
178
+ raise e
179
+ rescue Exception => ex
180
+ # Unexpected error! This is very bad and indicates an exception that got past
181
+ # the retry subsystem (e.g. network partition). We won't acknowledge the job
182
+ # so it can be rescued when using Sidekiq Pro.
183
+ ack = false
184
+ handle_exception(ex, { :context => "Internal exception!", :job => job_hash, :jobstr => jobstr })
185
+ raise e
186
+ ensure
187
+ work.acknowledge if ack
188
+ end
189
+ end
190
+
191
+ def execute_job(worker, cloned_args)
192
+ worker.perform(*cloned_args)
193
+ end
194
+
195
+ # Ruby doesn't provide atomic counters out of the box so we'll
196
+ # implement something simple ourselves.
197
+ # https://bugs.ruby-lang.org/issues/14706
198
+ class Counter
199
+ def initialize
200
+ @value = 0
201
+ @lock = Mutex.new
202
+ end
203
+
204
+ def incr(amount=1)
205
+ @lock.synchronize { @value = @value + amount }
206
+ end
207
+
208
+ def reset
209
+ @lock.synchronize { val = @value; @value = 0; val }
210
+ end
211
+ end
212
+
213
+ # jruby's Hash implementation is not threadsafe, so we wrap it in a mutex here
214
+ class SharedWorkerState
215
+ def initialize
216
+ @worker_state = {}
217
+ @lock = Mutex.new
218
+ end
219
+
220
+ def set(tid, hash)
221
+ @lock.synchronize { @worker_state[tid] = hash }
222
+ end
223
+
224
+ def delete(tid)
225
+ @lock.synchronize { @worker_state.delete(tid) }
226
+ end
227
+
228
+ def dup
229
+ @lock.synchronize { @worker_state.dup }
230
+ end
231
+
232
+ def size
233
+ @lock.synchronize { @worker_state.size }
234
+ end
235
+
236
+ def clear
237
+ @lock.synchronize { @worker_state.clear }
238
+ end
239
+ end
240
+
241
+ PROCESSED = Counter.new
242
+ FAILURE = Counter.new
243
+ WORKER_STATE = SharedWorkerState.new
244
+
245
+ def stats(job_hash, queue)
246
+ tid = Sidekiq::Logging.tid
247
+ WORKER_STATE.set(tid, {:queue => queue, :payload => job_hash, :run_at => Time.now.to_i })
248
+
249
+ begin
250
+ yield
251
+ rescue Exception
252
+ FAILURE.incr
253
+ raise
254
+ ensure
255
+ WORKER_STATE.delete(tid)
256
+ PROCESSED.incr
257
+ end
258
+ end
259
+
260
+ # Deep clone the arguments passed to the worker so that if
261
+ # the job fails, what is pushed back onto Redis hasn't
262
+ # been mutated by the worker.
263
+ def cloned(thing)
264
+ Marshal.load(Marshal.dump(thing))
265
+ end
266
+
267
+ def constantize(str)
268
+ names = str.split('::')
269
+ names.shift if names.empty? || names.first.empty?
270
+
271
+ names.inject(Object) do |constant, name|
272
+ # the false flag limits search for name to under the constant namespace
273
+ # which mimics Rails' behaviour
274
+ constant.const_defined?(name, false) ? constant.const_get(name, false) : constant.const_missing(name)
275
+ end
276
+ end
277
+
278
+ end
279
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sidekiq
4
+ class Rails < ::Rails::Engine
5
+ # We need to setup this up before any application configuration which might
6
+ # change Sidekiq middleware.
7
+ #
8
+ # This hook happens after `Rails::Application` is inherited within
9
+ # config/application.rb and before config is touched, usually within the
10
+ # class block. Definitely before config/environments/*.rb and
11
+ # config/initializers/*.rb.
12
+ config.before_configuration do
13
+ if ::Rails::VERSION::MAJOR < 5 && defined?(::ActiveRecord)
14
+ Sidekiq.server_middleware do |chain|
15
+ require 'sidekiq/middleware/server/active_record'
16
+ chain.add Sidekiq::Middleware::Server::ActiveRecord
17
+ end
18
+ end
19
+ end
20
+
21
+ config.after_initialize do
22
+ # This hook happens after all initializers are run, just before returning
23
+ # from config/environment.rb back to sidekiq/cli.rb.
24
+ # We have to add the reloader after initialize to see if cache_classes has
25
+ # been turned on.
26
+ #
27
+ # None of this matters on the client-side, only within the Sidekiq process itself.
28
+ #
29
+ Sidekiq.configure_server do |_|
30
+ if ::Rails::VERSION::MAJOR >= 5
31
+ Sidekiq.options[:reloader] = Sidekiq::Rails::Reloader.new
32
+ end
33
+ end
34
+ end
35
+
36
+ class Reloader
37
+ def initialize(app = ::Rails.application)
38
+ @app = app
39
+ end
40
+
41
+ def call
42
+ @app.reloader.wrap do
43
+ yield
44
+ end
45
+ end
46
+
47
+ def inspect
48
+ "#<Sidekiq::Rails::Reloader @app=#{@app.class.name}>"
49
+ end
50
+ end
51
+ end if defined?(::Rails)
52
+ end
53
+
54
+ if defined?(::Rails) && ::Rails::VERSION::MAJOR < 4
55
+ $stderr.puts("**************************************************")
56
+ $stderr.puts("⛔️ WARNING: Sidekiq server is no longer supported by Rails 3.2 - please ensure your server/workers are updated")
57
+ $stderr.puts("**************************************************")
58
+ end