sidekiq 5.2.5 → 6.0.3

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 (79) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +82 -0
  3. data/.gitignore +0 -2
  4. data/.standard.yml +20 -0
  5. data/6.0-Upgrade.md +72 -0
  6. data/COMM-LICENSE +11 -9
  7. data/Changes.md +136 -0
  8. data/Ent-2.0-Upgrade.md +37 -0
  9. data/Ent-Changes.md +32 -1
  10. data/Gemfile +12 -17
  11. data/Gemfile.lock +196 -0
  12. data/Pro-5.0-Upgrade.md +25 -0
  13. data/Pro-Changes.md +26 -2
  14. data/README.md +19 -31
  15. data/Rakefile +5 -4
  16. data/bin/sidekiqload +33 -25
  17. data/bin/sidekiqmon +8 -0
  18. data/lib/generators/sidekiq/templates/worker_test.rb.erb +1 -1
  19. data/lib/generators/sidekiq/worker_generator.rb +20 -12
  20. data/lib/sidekiq/api.rb +230 -214
  21. data/lib/sidekiq/cli.rb +111 -174
  22. data/lib/sidekiq/client.rb +55 -46
  23. data/lib/sidekiq/delay.rb +5 -6
  24. data/lib/sidekiq/exception_handler.rb +10 -12
  25. data/lib/sidekiq/extensions/action_mailer.rb +10 -20
  26. data/lib/sidekiq/extensions/active_record.rb +9 -7
  27. data/lib/sidekiq/extensions/class_methods.rb +9 -7
  28. data/lib/sidekiq/extensions/generic_proxy.rb +4 -4
  29. data/lib/sidekiq/fetch.rb +11 -12
  30. data/lib/sidekiq/job_logger.rb +45 -7
  31. data/lib/sidekiq/job_retry.rb +71 -60
  32. data/lib/sidekiq/launcher.rb +57 -51
  33. data/lib/sidekiq/logger.rb +165 -0
  34. data/lib/sidekiq/manager.rb +7 -9
  35. data/lib/sidekiq/middleware/chain.rb +14 -4
  36. data/lib/sidekiq/middleware/i18n.rb +5 -7
  37. data/lib/sidekiq/monitor.rb +133 -0
  38. data/lib/sidekiq/paginator.rb +18 -14
  39. data/lib/sidekiq/processor.rb +83 -75
  40. data/lib/sidekiq/rails.rb +23 -29
  41. data/lib/sidekiq/redis_connection.rb +31 -37
  42. data/lib/sidekiq/scheduled.rb +28 -29
  43. data/lib/sidekiq/testing/inline.rb +2 -1
  44. data/lib/sidekiq/testing.rb +34 -23
  45. data/lib/sidekiq/util.rb +17 -16
  46. data/lib/sidekiq/version.rb +2 -1
  47. data/lib/sidekiq/web/action.rb +14 -10
  48. data/lib/sidekiq/web/application.rb +64 -66
  49. data/lib/sidekiq/web/helpers.rb +89 -71
  50. data/lib/sidekiq/web/router.rb +17 -14
  51. data/lib/sidekiq/web.rb +41 -49
  52. data/lib/sidekiq/worker.rb +129 -97
  53. data/lib/sidekiq.rb +61 -42
  54. data/sidekiq.gemspec +16 -16
  55. data/web/assets/javascripts/dashboard.js +4 -23
  56. data/web/assets/stylesheets/application-dark.css +125 -0
  57. data/web/assets/stylesheets/application.css +9 -0
  58. data/web/assets/stylesheets/bootstrap.css +1 -1
  59. data/web/locales/de.yml +14 -2
  60. data/web/locales/ja.yml +2 -1
  61. data/web/views/_job_info.erb +2 -1
  62. data/web/views/busy.erb +4 -1
  63. data/web/views/dead.erb +2 -2
  64. data/web/views/layout.erb +1 -0
  65. data/web/views/morgue.erb +4 -1
  66. data/web/views/queue.erb +10 -1
  67. data/web/views/queues.erb +1 -1
  68. data/web/views/retries.erb +4 -1
  69. data/web/views/retry.erb +2 -2
  70. data/web/views/scheduled.erb +4 -1
  71. metadata +21 -32
  72. data/.travis.yml +0 -17
  73. data/Appraisals +0 -9
  74. data/bin/sidekiqctl +0 -237
  75. data/gemfiles/rails_4.gemfile +0 -31
  76. data/gemfiles/rails_5.gemfile +0 -31
  77. data/lib/sidekiq/core_ext.rb +0 -1
  78. data/lib/sidekiq/logging.rb +0 -122
  79. data/lib/sidekiq/middleware/server/active_record.rb +0 -23
@@ -1,36 +1,38 @@
1
1
  # frozen_string_literal: true
2
- require 'connection_pool'
3
- require 'redis'
4
- require 'uri'
2
+
3
+ require "connection_pool"
4
+ require "redis"
5
+ require "uri"
5
6
 
6
7
  module Sidekiq
7
8
  class RedisConnection
8
9
  class << self
9
-
10
- def create(options={})
10
+ def create(options = {})
11
11
  options.keys.each do |key|
12
12
  options[key.to_sym] = options.delete(key)
13
13
  end
14
14
 
15
- options[:id] = "Sidekiq-#{Sidekiq.server? ? "server" : "client"}-PID-#{$$}" if !options.has_key?(:id)
15
+ options[:id] = "Sidekiq-#{Sidekiq.server? ? "server" : "client"}-PID-#{::Process.pid}" unless options.key?(:id)
16
16
  options[:url] ||= determine_redis_provider
17
17
 
18
18
  size = if options[:size]
19
- options[:size]
20
- elsif Sidekiq.server?
21
- Sidekiq.options[:concurrency] + 5
22
- elsif ENV['RAILS_MAX_THREADS']
23
- Integer(ENV['RAILS_MAX_THREADS'])
24
- else
25
- 5
26
- end
19
+ options[:size]
20
+ elsif Sidekiq.server?
21
+ # Give ourselves plenty of connections. pool is lazy
22
+ # so we won't create them until we need them.
23
+ Sidekiq.options[:concurrency] + 5
24
+ elsif ENV["RAILS_MAX_THREADS"]
25
+ Integer(ENV["RAILS_MAX_THREADS"])
26
+ else
27
+ 5
28
+ end
27
29
 
28
30
  verify_sizing(size, Sidekiq.options[:concurrency]) if Sidekiq.server?
29
31
 
30
32
  pool_timeout = options[:pool_timeout] || 1
31
33
  log_info(options)
32
34
 
33
- ConnectionPool.new(:timeout => pool_timeout, :size => size) do
35
+ ConnectionPool.new(timeout: pool_timeout, size: size) do
34
36
  build_client(options)
35
37
  end
36
38
  end
@@ -46,7 +48,7 @@ module Sidekiq
46
48
  # - enterprise's leader election
47
49
  # - enterprise's cron support
48
50
  def verify_sizing(size, concurrency)
49
- raise ArgumentError, "Your Redis connection pool is too small for Sidekiq to work. Your pool has #{size} connections but must have at least #{concurrency + 2}" if size <= concurrency
51
+ raise ArgumentError, "Your Redis connection pool is too small for Sidekiq to work. Your pool has #{size} connections but must have at least #{concurrency + 2}" if size < (concurrency + 2)
50
52
  end
51
53
 
52
54
  def build_client(options)
@@ -55,8 +57,8 @@ module Sidekiq
55
57
  client = Redis.new client_opts(options)
56
58
  if namespace
57
59
  begin
58
- require 'redis/namespace'
59
- Redis::Namespace.new(namespace, :redis => client)
60
+ require "redis/namespace"
61
+ Redis::Namespace.new(namespace, redis: client)
60
62
  rescue LoadError
61
63
  Sidekiq.logger.error("Your Redis configuration uses the namespace '#{namespace}' but the redis-namespace gem is not included in the Gemfile." \
62
64
  "Add the gem to your Gemfile to continue using a namespace. Otherwise, remove the namespace parameter.")
@@ -78,7 +80,7 @@ module Sidekiq
78
80
  opts.delete(:network_timeout)
79
81
  end
80
82
 
81
- opts[:driver] ||= Redis::Connection.drivers.last || 'ruby'
83
+ opts[:driver] ||= Redis::Connection.drivers.last || "ruby"
82
84
 
83
85
  # Issue #3303, redis-rb will silently retry an operation.
84
86
  # This can lead to duplicate jobs if Sidekiq::Client's LPUSH
@@ -115,30 +117,22 @@ module Sidekiq
115
117
  # REDIS_PROVIDER=MY_REDIS_URL
116
118
  # and Sidekiq will find your custom URL variable with no custom
117
119
  # initialization code at all.
118
- p = ENV['REDIS_PROVIDER']
120
+ #
121
+ p = ENV["REDIS_PROVIDER"]
119
122
  if p && p =~ /\:/
120
- Sidekiq.logger.error <<-EOM
121
-
122
- #################################################################################
123
-
124
- REDIS_PROVIDER should be set to the **name** of the variable which contains the Redis URL, not a URL itself.
125
- Platforms like Heroku sell addons that publish a *_URL variable. You tell Sidekiq with REDIS_PROVIDER, e.g.:
123
+ raise <<~EOM
124
+ REDIS_PROVIDER should be set to the name of the variable which contains the Redis URL, not a URL itself.
125
+ Platforms like Heroku will sell addons that publish a *_URL variable. You need to tell Sidekiq with REDIS_PROVIDER, e.g.:
126
126
 
127
- REDIS_PROVIDER=REDISTOGO_URL
128
- REDISTOGO_URL=redis://somehost.example.com:6379/4
129
-
130
- Use REDIS_URL if you wish to point Sidekiq to a URL directly.
131
-
132
- This configuration error will crash starting in Sidekiq 5.3.
133
-
134
- #################################################################################
135
- EOM
127
+ REDISTOGO_URL=redis://somehost.example.com:6379/4
128
+ REDIS_PROVIDER=REDISTOGO_URL
129
+ EOM
136
130
  end
131
+
137
132
  ENV[
138
- ENV['REDIS_PROVIDER'] || 'REDIS_URL'
133
+ p || "REDIS_URL"
139
134
  ]
140
135
  end
141
-
142
136
  end
143
137
  end
144
138
  end
@@ -1,30 +1,32 @@
1
1
  # frozen_string_literal: true
2
- require 'sidekiq'
3
- require 'sidekiq/util'
4
- require 'sidekiq/api'
2
+
3
+ require "sidekiq"
4
+ require "sidekiq/util"
5
+ require "sidekiq/api"
5
6
 
6
7
  module Sidekiq
7
8
  module Scheduled
8
- SETS = %w(retry schedule)
9
+ SETS = %w[retry schedule]
9
10
 
10
11
  class Enq
11
- def enqueue_jobs(now=Time.now.to_f.to_s, sorted_sets=SETS)
12
+ def enqueue_jobs(now = Time.now.to_f.to_s, sorted_sets = SETS)
12
13
  # A job's "score" in Redis is the time at which it should be processed.
13
14
  # Just check Redis for the set of jobs with a timestamp before now.
14
15
  Sidekiq.redis do |conn|
15
16
  sorted_sets.each do |sorted_set|
16
- # Get the next item in the queue if it's score (time to execute) is <= now.
17
- # We need to go through the list one at a time to reduce the risk of something
18
- # going wrong between the time jobs are popped from the scheduled queue and when
19
- # they are pushed onto a work queue and losing the jobs.
20
- while job = conn.zrangebyscore(sorted_set, '-inf', now, :limit => [0, 1]).first do
21
-
22
- # Pop item off the queue and add it to the work queue. If the job can't be popped from
23
- # the queue, it's because another process already popped it so we can move on to the
24
- # next one.
25
- if conn.zrem(sorted_set, job)
26
- Sidekiq::Client.push(Sidekiq.load_json(job))
27
- Sidekiq::Logging.logger.debug { "enqueued #{sorted_set}: #{job}" }
17
+ # Get next items in the queue with scores (time to execute) <= now.
18
+ until (jobs = conn.zrangebyscore(sorted_set, "-inf", now, limit: [0, 100])).empty?
19
+ # We need to go through the list one at a time to reduce the risk of something
20
+ # going wrong between the time jobs are popped from the scheduled queue and when
21
+ # they are pushed onto a work queue and losing the jobs.
22
+ jobs.each do |job|
23
+ # Pop item off the queue and add it to the work queue. If the job can't be popped from
24
+ # the queue, it's because another process already popped it so we can move on to the
25
+ # next one.
26
+ if conn.zrem(sorted_set, job)
27
+ Sidekiq::Client.push(Sidekiq.load_json(job))
28
+ Sidekiq.logger.debug { "enqueued #{sorted_set}: #{job}" }
29
+ end
28
30
  end
29
31
  end
30
32
  end
@@ -61,26 +63,24 @@ module Sidekiq
61
63
  end
62
64
 
63
65
  def start
64
- @thread ||= safe_thread("scheduler") do
66
+ @thread ||= safe_thread("scheduler") {
65
67
  initial_wait
66
68
 
67
- while !@done
69
+ until @done
68
70
  enqueue
69
71
  wait
70
72
  end
71
73
  Sidekiq.logger.info("Scheduler exiting...")
72
- end
74
+ }
73
75
  end
74
76
 
75
77
  def enqueue
76
- begin
77
- @enq.enqueue_jobs
78
- rescue => ex
79
- # Most likely a problem with redis networking.
80
- # Punt and try again at the next interval
81
- logger.error ex.message
82
- handle_exception(ex)
83
- end
78
+ @enq.enqueue_jobs
79
+ rescue => ex
80
+ # Most likely a problem with redis networking.
81
+ # Punt and try again at the next interval
82
+ logger.error ex.message
83
+ handle_exception(ex)
84
84
  end
85
85
 
86
86
  private
@@ -168,7 +168,6 @@ module Sidekiq
168
168
  @sleeper.pop(total)
169
169
  rescue Timeout::Error
170
170
  end
171
-
172
171
  end
173
172
  end
174
173
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
- require 'sidekiq/testing'
2
+
3
+ require "sidekiq/testing"
3
4
 
4
5
  ##
5
6
  # The Sidekiq inline infrastructure overrides perform_async so that it
@@ -1,16 +1,16 @@
1
1
  # frozen_string_literal: true
2
- require 'securerandom'
3
- require 'sidekiq'
4
2
 
5
- module Sidekiq
3
+ require "securerandom"
4
+ require "sidekiq"
6
5
 
6
+ module Sidekiq
7
7
  class Testing
8
8
  class << self
9
9
  attr_accessor :__test_mode
10
10
 
11
11
  def __set_test_mode(mode)
12
12
  if block_given?
13
- current_mode = self.__test_mode
13
+ current_mode = __test_mode
14
14
  begin
15
15
  self.__test_mode = mode
16
16
  yield
@@ -35,19 +35,19 @@ module Sidekiq
35
35
  end
36
36
 
37
37
  def enabled?
38
- self.__test_mode != :disable
38
+ __test_mode != :disable
39
39
  end
40
40
 
41
41
  def disabled?
42
- self.__test_mode == :disable
42
+ __test_mode == :disable
43
43
  end
44
44
 
45
45
  def fake?
46
- self.__test_mode == :fake
46
+ __test_mode == :fake
47
47
  end
48
48
 
49
49
  def inline?
50
- self.__test_mode == :inline
50
+ __test_mode == :inline
51
51
  end
52
52
 
53
53
  def server_middleware
@@ -57,7 +57,7 @@ module Sidekiq
57
57
  end
58
58
 
59
59
  def constantize(str)
60
- names = str.split('::')
60
+ names = str.split("::")
61
61
  names.shift if names.empty? || names.first.empty?
62
62
 
63
63
  names.inject(Object) do |constant, name|
@@ -77,14 +77,14 @@ module Sidekiq
77
77
  if Sidekiq::Testing.fake?
78
78
  payloads.each do |job|
79
79
  job = Sidekiq.load_json(Sidekiq.dump_json(job))
80
- job.merge!('enqueued_at' => Time.now.to_f) unless job['at']
81
- Queues.push(job['queue'], job['class'], job)
80
+ job["enqueued_at"] = Time.now.to_f unless job["at"]
81
+ Queues.push(job["queue"], job["class"], job)
82
82
  end
83
83
  true
84
84
  elsif Sidekiq::Testing.inline?
85
85
  payloads.each do |job|
86
- klass = Sidekiq::Testing.constantize(job['class'])
87
- job['id'] ||= SecureRandom.hex(12)
86
+ klass = Sidekiq::Testing.constantize(job["class"])
87
+ job["id"] ||= SecureRandom.hex(12)
88
88
  job_hash = Sidekiq.load_json(Sidekiq.dump_json(job))
89
89
  klass.process_job(job_hash)
90
90
  end
@@ -255,27 +255,26 @@ module Sidekiq
255
255
  # Then I should receive a welcome email to "foo@example.com"
256
256
  #
257
257
  module ClassMethods
258
-
259
258
  # Queue for this worker
260
259
  def queue
261
- self.sidekiq_options["queue"]
260
+ get_sidekiq_options["queue"]
262
261
  end
263
262
 
264
263
  # Jobs queued for this worker
265
264
  def jobs
266
- Queues.jobs_by_worker[self.to_s]
265
+ Queues.jobs_by_worker[to_s]
267
266
  end
268
267
 
269
268
  # Clear all jobs for this worker
270
269
  def clear
271
- Queues.clear_for(queue, self.to_s)
270
+ Queues.clear_for(queue, to_s)
272
271
  end
273
272
 
274
273
  # Drain and run all jobs for this worker
275
274
  def drain
276
275
  while jobs.any?
277
276
  next_job = jobs.first
278
- Queues.delete_for(next_job["jid"], next_job["queue"], self.to_s)
277
+ Queues.delete_for(next_job["jid"], next_job["queue"], to_s)
279
278
  process_job(next_job)
280
279
  end
281
280
  end
@@ -284,16 +283,16 @@ module Sidekiq
284
283
  def perform_one
285
284
  raise(EmptyQueueError, "perform_one called with empty job queue") if jobs.empty?
286
285
  next_job = jobs.first
287
- Queues.delete_for(next_job["jid"], queue, self.to_s)
286
+ Queues.delete_for(next_job["jid"], queue, to_s)
288
287
  process_job(next_job)
289
288
  end
290
289
 
291
290
  def process_job(job)
292
291
  worker = new
293
- worker.jid = job['jid']
294
- worker.bid = job['bid'] if worker.respond_to?(:bid=)
295
- Sidekiq::Testing.server_middleware.invoke(worker, job, job['queue']) do
296
- execute_job(worker, job['args'])
292
+ worker.jid = job["jid"]
293
+ worker.bid = job["bid"] if worker.respond_to?(:bid=)
294
+ Sidekiq::Testing.server_middleware.invoke(worker, job, job["queue"]) do
295
+ execute_job(worker, job["args"])
297
296
  end
298
297
  end
299
298
 
@@ -324,6 +323,18 @@ module Sidekiq
324
323
  end
325
324
  end
326
325
  end
326
+
327
+ module TestingExtensions
328
+ def jobs_for(klass)
329
+ jobs.select do |job|
330
+ marshalled = job["args"][0]
331
+ marshalled.index(klass.to_s) && YAML.load(marshalled)[0] == klass
332
+ end
333
+ end
334
+ end
335
+
336
+ Sidekiq::Extensions::DelayedMailer.extend(TestingExtensions) if defined?(Sidekiq::Extensions::DelayedMailer)
337
+ Sidekiq::Extensions::DelayedModel.extend(TestingExtensions) if defined?(Sidekiq::Extensions::DelayedModel)
327
338
  end
328
339
 
329
340
  if defined?(::Rails) && Rails.respond_to?(:env) && !Rails.env.test?
data/lib/sidekiq/util.rb CHANGED
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
- require 'socket'
3
- require 'securerandom'
4
- require 'sidekiq/exception_handler'
2
+
3
+ require "socket"
4
+ require "securerandom"
5
+ require "sidekiq/exception_handler"
5
6
 
6
7
  module Sidekiq
7
8
  ##
@@ -10,18 +11,16 @@ module Sidekiq
10
11
  module Util
11
12
  include ExceptionHandler
12
13
 
13
- EXPIRY = 60 * 60 * 24
14
-
15
14
  def watchdog(last_words)
16
15
  yield
17
16
  rescue Exception => ex
18
- handle_exception(ex, { context: last_words })
17
+ handle_exception(ex, {context: last_words})
19
18
  raise ex
20
19
  end
21
20
 
22
21
  def safe_thread(name, &block)
23
22
  Thread.new do
24
- Thread.current['sidekiq_label'] = name
23
+ Thread.current.name = name
25
24
  watchdog(name, &block)
26
25
  end
27
26
  end
@@ -34,8 +33,12 @@ module Sidekiq
34
33
  Sidekiq.redis(&block)
35
34
  end
36
35
 
36
+ def tid
37
+ Thread.current["sidekiq_tid"] ||= (Thread.current.object_id ^ ::Process.pid).to_s(36)
38
+ end
39
+
37
40
  def hostname
38
- ENV['DYNO'] || Socket.gethostname
41
+ ENV["DYNO"] || Socket.gethostname
39
42
  end
40
43
 
41
44
  def process_nonce
@@ -43,22 +46,20 @@ module Sidekiq
43
46
  end
44
47
 
45
48
  def identity
46
- @@identity ||= "#{hostname}:#{$$}:#{process_nonce}"
49
+ @@identity ||= "#{hostname}:#{::Process.pid}:#{process_nonce}"
47
50
  end
48
51
 
49
- def fire_event(event, options={})
52
+ def fire_event(event, options = {})
50
53
  reverse = options[:reverse]
51
54
  reraise = options[:reraise]
52
55
 
53
56
  arr = Sidekiq.options[:lifecycle_events][event]
54
57
  arr.reverse! if reverse
55
58
  arr.each do |block|
56
- begin
57
- block.call
58
- rescue => ex
59
- handle_exception(ex, { context: "Exception during Sidekiq lifecycle event.", event: event })
60
- raise ex if reraise
61
- end
59
+ block.call
60
+ rescue => ex
61
+ handle_exception(ex, {context: "Exception during Sidekiq lifecycle event.", event: event})
62
+ raise ex if reraise
62
63
  end
63
64
  arr.clear
64
65
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Sidekiq
3
- VERSION = "5.2.5"
4
+ VERSION = "6.0.3"
4
5
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Sidekiq
4
4
  class WebAction
5
- RACK_SESSION = 'rack.session'
5
+ RACK_SESSION = "rack.session"
6
6
 
7
7
  attr_accessor :env, :block, :type
8
8
 
@@ -19,14 +19,14 @@ module Sidekiq
19
19
  end
20
20
 
21
21
  def redirect(location)
22
- throw :halt, [302, { "Location" => "#{request.base_url}#{location}" }, []]
22
+ throw :halt, [302, {"Location" => "#{request.base_url}#{location}"}, []]
23
23
  end
24
24
 
25
25
  def params
26
- indifferent_hash = Hash.new {|hash,key| hash[key.to_s] if Symbol === key }
26
+ indifferent_hash = Hash.new { |hash, key| hash[key.to_s] if Symbol === key }
27
27
 
28
28
  indifferent_hash.merge! request.params
29
- route_params.each {|k,v| indifferent_hash[k.to_s] = v }
29
+ route_params.each { |k, v| indifferent_hash[k.to_s] = v }
30
30
 
31
31
  indifferent_hash
32
32
  end
@@ -40,10 +40,14 @@ module Sidekiq
40
40
  end
41
41
 
42
42
  def erb(content, options = {})
43
- if content.kind_of? Symbol
43
+ if content.is_a? Symbol
44
44
  unless respond_to?(:"_erb_#{content}")
45
45
  src = ERB.new(File.read("#{Web.settings.views}/#{content}.erb")).src
46
- WebAction.class_eval("def _erb_#{content}\n#{src}\n end")
46
+ WebAction.class_eval <<-RUBY, __FILE__, __LINE__ + 1
47
+ def _erb_#{content}
48
+ #{src}
49
+ end
50
+ RUBY
47
51
  end
48
52
  end
49
53
 
@@ -64,22 +68,22 @@ module Sidekiq
64
68
  end
65
69
 
66
70
  def json(payload)
67
- [200, { "Content-Type" => "application/json", "Cache-Control" => "no-cache" }, [Sidekiq.dump_json(payload)]]
71
+ [200, {"Content-Type" => "application/json", "Cache-Control" => "no-cache"}, [Sidekiq.dump_json(payload)]]
68
72
  end
69
73
 
70
74
  def initialize(env, block)
71
75
  @_erb = false
72
76
  @env = env
73
77
  @block = block
74
- @@files ||= {}
78
+ @files ||= {}
75
79
  end
76
80
 
77
81
  private
78
82
 
79
83
  def _erb(file, locals)
80
- locals.each {|k, v| define_singleton_method(k){ v } unless (singleton_methods.include? k)} if locals
84
+ locals&.each { |k, v| define_singleton_method(k) { v } unless singleton_methods.include? k }
81
85
 
82
- if file.kind_of?(String)
86
+ if file.is_a?(String)
83
87
  ERB.new(file).result(binding)
84
88
  else
85
89
  send(:"_erb_#{file}")