File: sidekiq.rb

package info (click to toggle)
ruby-sidekiq 5.2.3%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 828 kB
  • sloc: ruby: 4,065; makefile: 24; sh: 6
file content (235 lines) | stat: -rw-r--r-- 6,462 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
# frozen_string_literal: true
require 'sidekiq/version'
fail "Sidekiq #{Sidekiq::VERSION} does not support Ruby versions below 2.2.2." if RUBY_PLATFORM != 'java' && Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.2.2')

require 'sidekiq/logging'
require 'sidekiq/client'
require 'sidekiq/worker'
require 'sidekiq/redis_connection'
require 'sidekiq/delay'

require 'json'

module Sidekiq
  NAME = 'Sidekiq'
  LICENSE = 'See LICENSE and the LGPL-3.0 for licensing details.'

  DEFAULTS = {
    queues: [],
    labels: [],
    concurrency: 10,
    require: '.',
    environment: nil,
    timeout: 8,
    poll_interval_average: nil,
    average_scheduled_poll_interval: 5,
    error_handlers: [],
    death_handlers: [],
    lifecycle_events: {
      startup: [],
      quiet: [],
      shutdown: [],
      heartbeat: [],
    },
    dead_max_jobs: 10_000,
    dead_timeout_in_seconds: 180 * 24 * 60 * 60, # 6 months
    reloader: proc { |&block| block.call },
  }

  DEFAULT_WORKER_OPTIONS = {
    'retry' => true,
    'queue' => 'default'
  }

  FAKE_INFO = {
    "redis_version" => "9.9.9",
    "uptime_in_days" => "9999",
    "connected_clients" => "9999",
    "used_memory_human" => "9P",
    "used_memory_peak_human" => "9P"
  }

  def self.❨╯°□°❩╯︵┻━┻
    puts "Calm down, yo."
  end

  def self.options
    @options ||= DEFAULTS.dup
  end
  def self.options=(opts)
    @options = opts
  end

  ##
  # Configuration for Sidekiq server, use like:
  #
  #   Sidekiq.configure_server do |config|
  #     config.redis = { :namespace => 'myapp', :size => 25, :url => 'redis://myhost:8877/0' }
  #     config.server_middleware do |chain|
  #       chain.add MyServerHook
  #     end
  #   end
  def self.configure_server
    yield self if server?
  end

  ##
  # Configuration for Sidekiq client, use like:
  #
  #   Sidekiq.configure_client do |config|
  #     config.redis = { :namespace => 'myapp', :size => 1, :url => 'redis://myhost:8877/0' }
  #   end
  def self.configure_client
    yield self unless server?
  end

  def self.server?
    defined?(Sidekiq::CLI)
  end

  def self.redis
    raise ArgumentError, "requires a block" unless block_given?
    redis_pool.with do |conn|
      retryable = true
      begin
        yield conn
      rescue Redis::CommandError => ex
        #2550 Failover can cause the server to become a slave, need
        # to disconnect and reopen the socket to get back to the master.
        (conn.disconnect!; retryable = false; retry) if retryable && ex.message =~ /READONLY/
        raise
      end
    end
  end

  def self.redis_info
    redis do |conn|
      begin
        # admin commands can't go through redis-namespace starting
        # in redis-namespace 2.0
        if conn.respond_to?(:namespace)
          conn.redis.info
        else
          conn.info
        end
      rescue Redis::CommandError => ex
        #2850 return fake version when INFO command has (probably) been renamed
        raise unless ex.message =~ /unknown command/
        FAKE_INFO
      end
    end
  end

  def self.redis_pool
    @redis ||= Sidekiq::RedisConnection.create
  end

  def self.redis=(hash)
    @redis = if hash.is_a?(ConnectionPool)
      hash
    else
      Sidekiq::RedisConnection.create(hash)
    end
  end

  def self.client_middleware
    @client_chain ||= Middleware::Chain.new
    yield @client_chain if block_given?
    @client_chain
  end

  def self.server_middleware
    @server_chain ||= default_server_middleware
    yield @server_chain if block_given?
    @server_chain
  end

  def self.default_server_middleware
    Middleware::Chain.new
  end

  def self.default_worker_options=(hash)
    # stringify
    @default_worker_options = default_worker_options.merge(Hash[hash.map{|k, v| [k.to_s, v]}])
  end
  def self.default_worker_options
    defined?(@default_worker_options) ? @default_worker_options : DEFAULT_WORKER_OPTIONS
  end

  def self.default_retries_exhausted=(prok)
    logger.info { "default_retries_exhausted is deprecated, please use `config.death_handlers << -> {|job, ex| }`" }
    return nil unless prok
    death_handlers << prok
  end

  ##
  # Death handlers are called when all retries for a job have been exhausted and
  # the job dies.  It's the notification to your application
  # that this job will not succeed without manual intervention.
  #
  # Sidekiq.configure_server do |config|
  #   config.death_handlers << ->(job, ex) do
  #   end
  # end
  def self.death_handlers
    options[:death_handlers]
  end

  def self.load_json(string)
    JSON.parse(string)
  end
  def self.dump_json(object)
    JSON.generate(object)
  end

  def self.logger
    Sidekiq::Logging.logger
  end
  def self.logger=(log)
    Sidekiq::Logging.logger = log
  end

  # How frequently Redis should be checked by a random Sidekiq process for
  # scheduled and retriable jobs. Each individual process will take turns by
  # waiting some multiple of this value.
  #
  # See sidekiq/scheduled.rb for an in-depth explanation of this value
  def self.average_scheduled_poll_interval=(interval)
    self.options[:average_scheduled_poll_interval] = interval
  end

  # Register a proc to handle any error which occurs within the Sidekiq process.
  #
  #   Sidekiq.configure_server do |config|
  #     config.error_handlers << proc {|ex,ctx_hash| MyErrorService.notify(ex, ctx_hash) }
  #   end
  #
  # The default error handler logs errors to Sidekiq.logger.
  def self.error_handlers
    self.options[:error_handlers]
  end

  # Register a block to run at a point in the Sidekiq lifecycle.
  # :startup, :quiet or :shutdown are valid events.
  #
  #   Sidekiq.configure_server do |config|
  #     config.on(:shutdown) do
  #       puts "Goodbye cruel world!"
  #     end
  #   end
  def self.on(event, &block)
    raise ArgumentError, "Symbols only please: #{event}" unless event.is_a?(Symbol)
    raise ArgumentError, "Invalid event name: #{event}" unless options[:lifecycle_events].key?(event)
    options[:lifecycle_events][event] << block
  end

  # We are shutting down Sidekiq but what about workers that
  # are working on some long job?  This error is
  # raised in workers that have not finished within the hard
  # timeout limit.  This is needed to rollback db transactions,
  # otherwise Ruby's Thread#kill will commit.  See #377.
  # DO NOT RESCUE THIS ERROR IN YOUR WORKERS
  class Shutdown < Interrupt; end
end

require 'sidekiq/rails' if defined?(::Rails::Engine)