mini-clean-lib 0.0.1

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 (151) hide show
  1. checksums.yaml +7 -0
  2. data/mini-clean-lib.gemspec +12 -0
  3. data/sidekiq-8.1.6/Changes.md +2515 -0
  4. data/sidekiq-8.1.6/LICENSE.txt +9 -0
  5. data/sidekiq-8.1.6/README.md +124 -0
  6. data/sidekiq-8.1.6/bin/kiq +17 -0
  7. data/sidekiq-8.1.6/bin/lint-herb +13 -0
  8. data/sidekiq-8.1.6/bin/multi_queue_bench +271 -0
  9. data/sidekiq-8.1.6/bin/sidekiq +37 -0
  10. data/sidekiq-8.1.6/bin/sidekiqload +256 -0
  11. data/sidekiq-8.1.6/bin/sidekiqmon +11 -0
  12. data/sidekiq-8.1.6/bin/webload +69 -0
  13. data/sidekiq-8.1.6/lib/active_job/queue_adapters/sidekiq_adapter.rb +124 -0
  14. data/sidekiq-8.1.6/lib/generators/sidekiq/job_generator.rb +71 -0
  15. data/sidekiq-8.1.6/lib/generators/sidekiq/templates/job.rb.erb +9 -0
  16. data/sidekiq-8.1.6/lib/generators/sidekiq/templates/job_spec.rb.erb +6 -0
  17. data/sidekiq-8.1.6/lib/generators/sidekiq/templates/job_test.rb.erb +8 -0
  18. data/sidekiq-8.1.6/lib/sidekiq/api.rb +1466 -0
  19. data/sidekiq-8.1.6/lib/sidekiq/capsule.rb +135 -0
  20. data/sidekiq-8.1.6/lib/sidekiq/cli.rb +433 -0
  21. data/sidekiq-8.1.6/lib/sidekiq/client.rb +306 -0
  22. data/sidekiq-8.1.6/lib/sidekiq/component.rb +132 -0
  23. data/sidekiq-8.1.6/lib/sidekiq/config.rb +316 -0
  24. data/sidekiq-8.1.6/lib/sidekiq/deploy.rb +64 -0
  25. data/sidekiq-8.1.6/lib/sidekiq/embedded.rb +64 -0
  26. data/sidekiq-8.1.6/lib/sidekiq/fetch.rb +89 -0
  27. data/sidekiq-8.1.6/lib/sidekiq/iterable_job.rb +56 -0
  28. data/sidekiq-8.1.6/lib/sidekiq/job/interrupt_handler.rb +24 -0
  29. data/sidekiq-8.1.6/lib/sidekiq/job/iterable/active_record_enumerator.rb +53 -0
  30. data/sidekiq-8.1.6/lib/sidekiq/job/iterable/csv_enumerator.rb +47 -0
  31. data/sidekiq-8.1.6/lib/sidekiq/job/iterable/enumerators.rb +135 -0
  32. data/sidekiq-8.1.6/lib/sidekiq/job/iterable.rb +322 -0
  33. data/sidekiq-8.1.6/lib/sidekiq/job.rb +400 -0
  34. data/sidekiq-8.1.6/lib/sidekiq/job_logger.rb +54 -0
  35. data/sidekiq-8.1.6/lib/sidekiq/job_retry.rb +332 -0
  36. data/sidekiq-8.1.6/lib/sidekiq/job_util.rb +113 -0
  37. data/sidekiq-8.1.6/lib/sidekiq/launcher.rb +283 -0
  38. data/sidekiq-8.1.6/lib/sidekiq/loader.rb +57 -0
  39. data/sidekiq-8.1.6/lib/sidekiq/logger.rb +87 -0
  40. data/sidekiq-8.1.6/lib/sidekiq/manager.rb +134 -0
  41. data/sidekiq-8.1.6/lib/sidekiq/metrics/query.rb +184 -0
  42. data/sidekiq-8.1.6/lib/sidekiq/metrics/shared.rb +109 -0
  43. data/sidekiq-8.1.6/lib/sidekiq/metrics/tracking.rb +153 -0
  44. data/sidekiq-8.1.6/lib/sidekiq/middleware/chain.rb +207 -0
  45. data/sidekiq-8.1.6/lib/sidekiq/middleware/current_attributes.rb +120 -0
  46. data/sidekiq-8.1.6/lib/sidekiq/middleware/i18n.rb +44 -0
  47. data/sidekiq-8.1.6/lib/sidekiq/middleware/modules.rb +23 -0
  48. data/sidekiq-8.1.6/lib/sidekiq/monitor.rb +143 -0
  49. data/sidekiq-8.1.6/lib/sidekiq/paginator.rb +74 -0
  50. data/sidekiq-8.1.6/lib/sidekiq/processor.rb +298 -0
  51. data/sidekiq-8.1.6/lib/sidekiq/profiler.rb +73 -0
  52. data/sidekiq-8.1.6/lib/sidekiq/rails.rb +63 -0
  53. data/sidekiq-8.1.6/lib/sidekiq/redis_client_adapter.rb +117 -0
  54. data/sidekiq-8.1.6/lib/sidekiq/redis_connection.rb +115 -0
  55. data/sidekiq-8.1.6/lib/sidekiq/ring_buffer.rb +32 -0
  56. data/sidekiq-8.1.6/lib/sidekiq/scheduled.rb +235 -0
  57. data/sidekiq-8.1.6/lib/sidekiq/sd_notify.rb +149 -0
  58. data/sidekiq-8.1.6/lib/sidekiq/systemd.rb +26 -0
  59. data/sidekiq-8.1.6/lib/sidekiq/test_api.rb +331 -0
  60. data/sidekiq-8.1.6/lib/sidekiq/testing/inline.rb +2 -0
  61. data/sidekiq-8.1.6/lib/sidekiq/testing.rb +3 -0
  62. data/sidekiq-8.1.6/lib/sidekiq/transaction_aware_client.rb +59 -0
  63. data/sidekiq-8.1.6/lib/sidekiq/tui/controls.rb +53 -0
  64. data/sidekiq-8.1.6/lib/sidekiq/tui/filtering.rb +53 -0
  65. data/sidekiq-8.1.6/lib/sidekiq/tui/tabs/base_tab.rb +204 -0
  66. data/sidekiq-8.1.6/lib/sidekiq/tui/tabs/busy.rb +118 -0
  67. data/sidekiq-8.1.6/lib/sidekiq/tui/tabs/dead.rb +19 -0
  68. data/sidekiq-8.1.6/lib/sidekiq/tui/tabs/home.rb +144 -0
  69. data/sidekiq-8.1.6/lib/sidekiq/tui/tabs/metrics.rb +131 -0
  70. data/sidekiq-8.1.6/lib/sidekiq/tui/tabs/queues.rb +95 -0
  71. data/sidekiq-8.1.6/lib/sidekiq/tui/tabs/retries.rb +19 -0
  72. data/sidekiq-8.1.6/lib/sidekiq/tui/tabs/scheduled.rb +19 -0
  73. data/sidekiq-8.1.6/lib/sidekiq/tui/tabs/set_tab.rb +96 -0
  74. data/sidekiq-8.1.6/lib/sidekiq/tui/tabs.rb +15 -0
  75. data/sidekiq-8.1.6/lib/sidekiq/tui.rb +382 -0
  76. data/sidekiq-8.1.6/lib/sidekiq/version.rb +10 -0
  77. data/sidekiq-8.1.6/lib/sidekiq/web/action.rb +178 -0
  78. data/sidekiq-8.1.6/lib/sidekiq/web/application.rb +480 -0
  79. data/sidekiq-8.1.6/lib/sidekiq/web/config.rb +117 -0
  80. data/sidekiq-8.1.6/lib/sidekiq/web/helpers.rb +474 -0
  81. data/sidekiq-8.1.6/lib/sidekiq/web/router.rb +91 -0
  82. data/sidekiq-8.1.6/lib/sidekiq/web.rb +140 -0
  83. data/sidekiq-8.1.6/lib/sidekiq/worker_compatibility_alias.rb +13 -0
  84. data/sidekiq-8.1.6/lib/sidekiq.rb +161 -0
  85. data/sidekiq-8.1.6/sidekiq.gemspec +31 -0
  86. data/sidekiq-8.1.6/web/assets/images/apple-touch-icon.png +0 -0
  87. data/sidekiq-8.1.6/web/assets/images/favicon.ico +0 -0
  88. data/sidekiq-8.1.6/web/assets/images/logo.png +0 -0
  89. data/sidekiq-8.1.6/web/assets/images/status.png +0 -0
  90. data/sidekiq-8.1.6/web/assets/javascripts/application.js +204 -0
  91. data/sidekiq-8.1.6/web/assets/javascripts/base-charts.js +120 -0
  92. data/sidekiq-8.1.6/web/assets/javascripts/chart.min.js +13 -0
  93. data/sidekiq-8.1.6/web/assets/javascripts/chartjs-adapter-date-fns.min.js +7 -0
  94. data/sidekiq-8.1.6/web/assets/javascripts/chartjs-plugin-annotation.min.js +7 -0
  95. data/sidekiq-8.1.6/web/assets/javascripts/dashboard-charts.js +194 -0
  96. data/sidekiq-8.1.6/web/assets/javascripts/dashboard.js +63 -0
  97. data/sidekiq-8.1.6/web/assets/javascripts/metrics.js +280 -0
  98. data/sidekiq-8.1.6/web/assets/stylesheets/style.css +776 -0
  99. data/sidekiq-8.1.6/web/locales/ar.yml +89 -0
  100. data/sidekiq-8.1.6/web/locales/cs.yml +80 -0
  101. data/sidekiq-8.1.6/web/locales/da.yml +77 -0
  102. data/sidekiq-8.1.6/web/locales/de.yml +83 -0
  103. data/sidekiq-8.1.6/web/locales/el.yml +89 -0
  104. data/sidekiq-8.1.6/web/locales/en.yml +110 -0
  105. data/sidekiq-8.1.6/web/locales/es.yml +109 -0
  106. data/sidekiq-8.1.6/web/locales/fa.yml +82 -0
  107. data/sidekiq-8.1.6/web/locales/fr.yml +100 -0
  108. data/sidekiq-8.1.6/web/locales/gd.yml +110 -0
  109. data/sidekiq-8.1.6/web/locales/he.yml +82 -0
  110. data/sidekiq-8.1.6/web/locales/hi.yml +77 -0
  111. data/sidekiq-8.1.6/web/locales/it.yml +109 -0
  112. data/sidekiq-8.1.6/web/locales/ja.yml +92 -0
  113. data/sidekiq-8.1.6/web/locales/ko.yml +70 -0
  114. data/sidekiq-8.1.6/web/locales/lt.yml +85 -0
  115. data/sidekiq-8.1.6/web/locales/nb.yml +79 -0
  116. data/sidekiq-8.1.6/web/locales/nl.yml +70 -0
  117. data/sidekiq-8.1.6/web/locales/pl.yml +61 -0
  118. data/sidekiq-8.1.6/web/locales/pt-BR.yml +97 -0
  119. data/sidekiq-8.1.6/web/locales/pt.yml +69 -0
  120. data/sidekiq-8.1.6/web/locales/ru.yml +85 -0
  121. data/sidekiq-8.1.6/web/locales/sv.yml +70 -0
  122. data/sidekiq-8.1.6/web/locales/ta.yml +77 -0
  123. data/sidekiq-8.1.6/web/locales/tr.yml +102 -0
  124. data/sidekiq-8.1.6/web/locales/uk.yml +102 -0
  125. data/sidekiq-8.1.6/web/locales/ur.yml +82 -0
  126. data/sidekiq-8.1.6/web/locales/vi.yml +85 -0
  127. data/sidekiq-8.1.6/web/locales/zh-CN.yml +107 -0
  128. data/sidekiq-8.1.6/web/locales/zh-TW.yml +103 -0
  129. data/sidekiq-8.1.6/web/views/_footer.html.erb +32 -0
  130. data/sidekiq-8.1.6/web/views/_job_info.html.erb +115 -0
  131. data/sidekiq-8.1.6/web/views/_metrics_period_select.html.erb +15 -0
  132. data/sidekiq-8.1.6/web/views/_nav.html.erb +45 -0
  133. data/sidekiq-8.1.6/web/views/_paging.html.erb +26 -0
  134. data/sidekiq-8.1.6/web/views/_poll_link.html.erb +4 -0
  135. data/sidekiq-8.1.6/web/views/_summary.html.erb +40 -0
  136. data/sidekiq-8.1.6/web/views/busy.html.erb +155 -0
  137. data/sidekiq-8.1.6/web/views/dashboard.html.erb +104 -0
  138. data/sidekiq-8.1.6/web/views/dead.html.erb +38 -0
  139. data/sidekiq-8.1.6/web/views/filtering.html.erb +6 -0
  140. data/sidekiq-8.1.6/web/views/layout.html.erb +26 -0
  141. data/sidekiq-8.1.6/web/views/metrics.html.erb +85 -0
  142. data/sidekiq-8.1.6/web/views/metrics_for_job.html.erb +58 -0
  143. data/sidekiq-8.1.6/web/views/morgue.html.erb +69 -0
  144. data/sidekiq-8.1.6/web/views/profiles.html.erb +43 -0
  145. data/sidekiq-8.1.6/web/views/queue.html.erb +57 -0
  146. data/sidekiq-8.1.6/web/views/queues.html.erb +46 -0
  147. data/sidekiq-8.1.6/web/views/retries.html.erb +77 -0
  148. data/sidekiq-8.1.6/web/views/retry.html.erb +39 -0
  149. data/sidekiq-8.1.6/web/views/scheduled.html.erb +64 -0
  150. data/sidekiq-8.1.6/web/views/scheduled_job_info.html.erb +8 -0
  151. metadata +190 -0
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "sidekiq/component"
4
+
5
+ module Sidekiq
6
+ # A Sidekiq::Capsule is the set of resources necessary to
7
+ # process one or more queues with a given concurrency.
8
+ # One "default" Capsule is started but the user may declare additional
9
+ # Capsules in their initializer.
10
+ #
11
+ # This capsule will pull jobs from the "single" queue and process
12
+ # the jobs with one thread, meaning the jobs will be processed serially.
13
+ #
14
+ # Sidekiq.configure_server do |config|
15
+ # config.capsule("single-threaded") do |cap|
16
+ # cap.concurrency = 1
17
+ # cap.queues = %w(single)
18
+ # end
19
+ # end
20
+ class Capsule
21
+ include Sidekiq::Component
22
+ extend Forwardable
23
+
24
+ attr_reader :name
25
+ attr_reader :queues
26
+ attr_accessor :concurrency
27
+ attr_reader :mode
28
+ attr_reader :weights
29
+
30
+ def_delegators :@config, :[], :[]=, :fetch, :key?, :has_key?, :merge!, :dig, :thread_priority
31
+
32
+ def initialize(name, config)
33
+ @name = name
34
+ @config = config
35
+ @queues = ["default"]
36
+ @weights = {"default" => 0}
37
+ @concurrency = config[:concurrency]
38
+ @mode = :strict
39
+ end
40
+
41
+ def to_h
42
+ {concurrency: concurrency, mode: mode, weights: weights}
43
+ end
44
+
45
+ def fetcher
46
+ @fetcher ||= begin
47
+ instance = (config[:fetch_class] || Sidekiq::BasicFetch).new(self)
48
+ instance.setup(config[:fetch_setup]) if instance.respond_to?(:setup)
49
+ instance
50
+ end
51
+ end
52
+
53
+ def stop
54
+ end
55
+
56
+ # Sidekiq checks queues in three modes:
57
+ # - :strict - all queues have 0 weight and are checked strictly in order
58
+ # - :weighted - queues have arbitrary weight between 1 and N
59
+ # - :random - all queues have weight of 1
60
+ def queues=(val)
61
+ @weights = {}
62
+ @queues = Array(val).each_with_object([]) do |qstr, memo|
63
+ arr = qstr
64
+ arr = qstr.split(",") if qstr.is_a?(String)
65
+ name, weight = arr
66
+ @weights[name] = weight.to_i
67
+ [weight.to_i, 1].max.times do
68
+ memo << name
69
+ end
70
+ end
71
+ @mode = if @weights.values.all?(&:zero?)
72
+ :strict
73
+ elsif @weights.values.all? { |x| x == 1 }
74
+ :random
75
+ else
76
+ :weighted
77
+ end
78
+ end
79
+
80
+ # Allow the middleware to be different per-capsule.
81
+ # Avoid if possible and add middleware globally so all
82
+ # capsules share the same chains. Easier to debug that way.
83
+ def client_middleware
84
+ @client_chain ||= config.client_middleware.copy_for(self)
85
+ yield @client_chain if block_given?
86
+ @client_chain
87
+ end
88
+
89
+ def server_middleware
90
+ @server_chain ||= config.server_middleware.copy_for(self)
91
+ yield @server_chain if block_given?
92
+ @server_chain
93
+ end
94
+
95
+ def redis_pool
96
+ Thread.current[:sidekiq_redis_pool] || local_redis_pool
97
+ end
98
+
99
+ def local_redis_pool
100
+ # connection pool is lazy, it will not create connections unless you actually need them
101
+ # so don't be skimpy!
102
+ @redis ||= config.new_redis_pool(@concurrency, name)
103
+ end
104
+
105
+ def redis
106
+ raise ArgumentError, "requires a block" unless block_given?
107
+ redis_pool.with do |conn|
108
+ retryable = true
109
+ begin
110
+ yield conn
111
+ rescue RedisClientAdapter::BaseError => ex
112
+ # 2550 Failover can cause the server to become a replica, need
113
+ # to disconnect and reopen the socket to get back to the primary.
114
+ # 4495 Use the same logic if we have a "Not enough replicas" error from the primary
115
+ # 4985 Use the same logic when a blocking command is force-unblocked
116
+ # The same retry logic is also used in client.rb
117
+ if retryable && ex.message =~ /READONLY|NOREPLICAS|UNBLOCKED/
118
+ conn.close
119
+ retryable = false
120
+ retry
121
+ end
122
+ raise
123
+ end
124
+ end
125
+ end
126
+
127
+ def lookup(name)
128
+ config.lookup(name)
129
+ end
130
+
131
+ def logger
132
+ config.logger
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,433 @@
1
+ # frozen_string_literal: true
2
+
3
+ $stdout.sync = true
4
+
5
+ require "optparse"
6
+ require "erb"
7
+ require "fileutils"
8
+
9
+ require "sidekiq"
10
+ require "sidekiq/config"
11
+ require "sidekiq/component"
12
+ require "sidekiq/capsule"
13
+ require "sidekiq/launcher"
14
+
15
+ module Sidekiq # :nodoc:
16
+ class CLI
17
+ include Sidekiq::Component
18
+
19
+ attr_accessor :launcher
20
+ attr_accessor :environment
21
+ attr_accessor :config
22
+
23
+ def parse(args = ARGV.dup)
24
+ @config ||= Sidekiq.default_configuration
25
+
26
+ setup_options(args)
27
+ initialize_logger
28
+ validate!
29
+ end
30
+
31
+ def self.instance
32
+ @instance ||= new
33
+ end
34
+
35
+ def jruby?
36
+ defined?(::JRUBY_VERSION)
37
+ end
38
+
39
+ # Code within this method is not tested because it alters
40
+ # global process state irreversibly. PRs which improve the
41
+ # test coverage of Sidekiq::CLI are welcomed.
42
+ def run(boot_app: true, warmup: true)
43
+ boot_application if boot_app
44
+
45
+ if environment == "development" && $stdout.tty? && @config.logger.formatter.is_a?(Sidekiq::Logger::Formatters::Pretty)
46
+ print_banner
47
+ end
48
+ logger.info "Booted Rails #{::Rails.version} application in #{environment} environment" if rails_app?
49
+
50
+ self_read, self_write = IO.pipe
51
+ sigs = %w[INT TERM INFO TTIN TSTP]
52
+ # USR1 and USR2 don't work on the JVM
53
+ sigs << "USR2" if Sidekiq.pro? && !jruby?
54
+ sigs.each do |sig|
55
+ old_handler = Signal.trap(sig) do
56
+ if old_handler.respond_to?(:call)
57
+ begin
58
+ old_handler.call
59
+ rescue Exception => exc
60
+ # signal handlers can't use Logger so puts only
61
+ puts ["Error in #{sig} handler", exc].inspect
62
+ end
63
+ end
64
+ self_write.puts(sig)
65
+ end
66
+ rescue ArgumentError
67
+ puts "Signal #{sig} not supported"
68
+ end
69
+
70
+ logger.info "Running in #{RUBY_DESCRIPTION}"
71
+ logger.info Sidekiq::LICENSE
72
+ logger.info "Upgrade to Sidekiq Pro for more features and support: https://sidekiq.org" unless defined?(::Sidekiq::Pro)
73
+
74
+ # touch the connection pool so it is created before we
75
+ # fire startup and start multithreading.
76
+ info = @config.redis_info
77
+ ver = Gem::Version.new(info["redis_version"])
78
+ raise "You are connected to Redis #{ver}, Sidekiq requires Redis 7.0.0 or greater" if ver < Gem::Version.new("7.0.0")
79
+
80
+ maxmemory_policy = info["maxmemory_policy"]
81
+ if maxmemory_policy != "noeviction" && maxmemory_policy != ""
82
+ # Redis Enterprise Cloud returns "" for their policy 😳
83
+ logger.warn <<~EOM
84
+
85
+
86
+ WARNING: Your Redis instance will evict Sidekiq data under heavy load.
87
+ The 'noeviction' maxmemory policy is recommended (current policy: '#{maxmemory_policy}').
88
+ See: https://github.com/sidekiq/sidekiq/wiki/Using-Redis#memory
89
+
90
+ EOM
91
+ end
92
+
93
+ # Since the user can pass us a connection pool explicitly in the initializer, we
94
+ # need to verify the size is large enough or else Sidekiq's performance is dramatically slowed.
95
+ @config.capsules.each_pair do |name, cap|
96
+ raise ArgumentError, "Pool size too small for #{name}" if cap.redis_pool.size < cap.concurrency
97
+ end
98
+
99
+ # cache process identity
100
+ @config[:identity] = identity
101
+
102
+ # Touch middleware so it isn't lazy loaded by multiple threads, #3043
103
+ @config.server_middleware
104
+
105
+ ::Process.warmup if warmup && ::Process.respond_to?(:warmup) && ENV["RUBY_DISABLE_WARMUP"] != "1"
106
+
107
+ # Before this point, the process is initializing with just the main thread.
108
+ # Starting here the process will now have multiple threads running.
109
+ fire_event(:startup, reverse: false, reraise: true)
110
+
111
+ logger.debug { "Client Middleware: #{@config.default_capsule.client_middleware.map(&:klass).join(", ")}" }
112
+ logger.debug { "Server Middleware: #{@config.default_capsule.server_middleware.map(&:klass).join(", ")}" }
113
+
114
+ launch(self_read)
115
+ end
116
+
117
+ def launch(self_read)
118
+ if environment == "development" && $stdout.tty?
119
+ logger.info "Starting processing, hit Ctrl-C to stop"
120
+ end
121
+
122
+ @launcher = Sidekiq::Launcher.new(@config)
123
+
124
+ begin
125
+ launcher.run
126
+
127
+ while self_read.wait_readable
128
+ signal = self_read.gets.strip
129
+ handle_signal(signal)
130
+ end
131
+ rescue Interrupt
132
+ logger.info "Shutting down"
133
+ launcher.stop
134
+ logger.info "Bye!"
135
+
136
+ # Explicitly exit so busy Processor threads won't block process shutdown.
137
+ #
138
+ # NB: slow at_exit handlers will prevent a timely exit if they take
139
+ # a while to run. If Sidekiq is getting here but the process isn't exiting,
140
+ # use the TTIN signal to determine where things are stuck.
141
+ exit(0)
142
+ end
143
+ end
144
+
145
+ HOLIDAY_COLORS = {
146
+ # got other color-specific holidays from around the world?
147
+ # https://developer-book.com/post/definitive-guide-for-colored-text-in-terminal/#256-color-escape-codes
148
+ "3-17" => "\e[1;32m", # St. Patrick's Day green
149
+ "10-31" => "\e[38;5;208m" # Halloween orange
150
+ }
151
+
152
+ def self.day
153
+ @@day ||= begin
154
+ t = Date.today
155
+ "#{t.month}-#{t.day}"
156
+ end
157
+ end
158
+
159
+ def self.r
160
+ @@r ||= HOLIDAY_COLORS[day] || "\e[1;31m"
161
+ end
162
+
163
+ def self.b
164
+ @@b ||= HOLIDAY_COLORS[day] || "\e[30m"
165
+ end
166
+
167
+ def self.w
168
+ "\e[1;37m"
169
+ end
170
+
171
+ def self.reset
172
+ @@b = @@r = @@day = nil
173
+ "\e[0m"
174
+ end
175
+
176
+ def self.banner
177
+ %{
178
+ #{w} m,
179
+ #{w} `$b
180
+ #{w} .ss, $$: .,d$
181
+ #{w} `$$P,d$P' .,md$P"'
182
+ #{w} ,$$$$$b#{b}/#{w}md$$$P^'
183
+ #{w} .d$$$$$$#{b}/#{w}$$$P'
184
+ #{w} $$^' `"#{b}/#{w}$$$' #{r}____ _ _ _ _
185
+ #{w} $: #{b}'#{w},$$: #{r} / ___|(_) __| | ___| | _(_) __ _
186
+ #{w} `b :$$ #{r} \\___ \\| |/ _` |/ _ \\ |/ / |/ _` |
187
+ #{w} $$: #{r} ___) | | (_| | __/ <| | (_| |
188
+ #{w} $$ #{r}|____/|_|\\__,_|\\___|_|\\_\\_|\\__, |
189
+ #{w} .d$$ #{r} |_|
190
+ #{reset}}
191
+ end
192
+
193
+ SIGNAL_HANDLERS = {
194
+ # Ctrl-C in terminal
195
+ "INT" => ->(cli) { raise Interrupt },
196
+ # TERM is the signal that Sidekiq must exit.
197
+ # Heroku sends TERM and then waits 30 seconds for process to exit.
198
+ "TERM" => ->(cli) { raise Interrupt },
199
+ "TSTP" => ->(cli) {
200
+ cli.logger.info "Received TSTP, no longer accepting new work"
201
+ cli.launcher.quiet
202
+ },
203
+ "TTIN" => ->(cli) {
204
+ Thread.list.each do |thread|
205
+ cli.logger.warn "Thread TID-#{(thread.object_id ^ ::Process.pid).to_s(36)} #{thread.name}"
206
+ if thread.backtrace
207
+ cli.logger.warn thread.backtrace.join("\n")
208
+ else
209
+ cli.logger.warn "<no backtrace available>"
210
+ end
211
+ end
212
+ },
213
+ "INFO" => ->(cli) {
214
+ cli.logger.error { "DEPRECATED: the INFO signal does not work on Linux, use TTIN instead." }
215
+ Thread.list.each do |thread|
216
+ cli.logger.warn "Thread TID-#{(thread.object_id ^ ::Process.pid).to_s(36)} #{thread.name}"
217
+ if thread.backtrace
218
+ cli.logger.warn thread.backtrace.join("\n")
219
+ else
220
+ cli.logger.warn "<no backtrace available>"
221
+ end
222
+ end
223
+ }
224
+ }
225
+
226
+ def handle_signal(sig)
227
+ logger.debug "Got #{sig} signal"
228
+ hndlr = SIGNAL_HANDLERS[sig]
229
+ hndlr ? hndlr.call(self) :
230
+ logger.warn("No #{sig} signal handler registered, ignoring")
231
+ end
232
+
233
+ private
234
+
235
+ def print_banner
236
+ puts "\e[31m"
237
+ puts Sidekiq::CLI.banner
238
+ puts "\e[0m"
239
+ end
240
+
241
+ def set_environment(cli_env)
242
+ # See #984 for discussion.
243
+ # APP_ENV is now the preferred ENV term since it is not tech-specific.
244
+ # Both Sinatra 2.0+ and Sidekiq support this term.
245
+ # RAILS_ENV and RACK_ENV are there for legacy support.
246
+ @environment = cli_env || ENV["APP_ENV"] || ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development"
247
+ config[:environment] = @environment
248
+ end
249
+
250
+ def symbolize_keys_deep!(hash)
251
+ hash.keys.each do |k|
252
+ symkey = k.respond_to?(:to_sym) ? k.to_sym : k
253
+ hash[symkey] = hash.delete k
254
+ symbolize_keys_deep! hash[symkey] if hash[symkey].is_a? Hash
255
+ end
256
+ end
257
+
258
+ alias_method :die, :exit
259
+ alias_method :☠, :exit
260
+
261
+ def setup_options(args)
262
+ # parse CLI options
263
+ opts = parse_options(args)
264
+
265
+ set_environment opts[:environment]
266
+
267
+ # check config file presence
268
+ if opts[:config_file]
269
+ unless File.exist?(opts[:config_file])
270
+ raise ArgumentError, "No such file #{opts[:config_file]}"
271
+ end
272
+ else
273
+ config_dir = if File.directory?(opts[:require].to_s)
274
+ File.join(opts[:require], "config")
275
+ else
276
+ File.join(@config[:require], "config")
277
+ end
278
+
279
+ %w[sidekiq.yml sidekiq.yml.erb].each do |config_file|
280
+ path = File.join(config_dir, config_file)
281
+ opts[:config_file] ||= path if File.exist?(path)
282
+ end
283
+ end
284
+
285
+ # parse config file options
286
+ opts = parse_config(opts[:config_file]).merge(opts) if opts[:config_file]
287
+
288
+ # set defaults
289
+ opts[:queues] = ["default"] if opts[:queues].nil?
290
+ opts[:concurrency] = Integer(ENV["RAILS_MAX_THREADS"]) if opts[:concurrency].nil? && ENV["RAILS_MAX_THREADS"]
291
+
292
+ # merge with defaults
293
+ @config.merge!(opts)
294
+
295
+ @config.default_capsule.tap do |cap|
296
+ cap.queues = opts[:queues]
297
+ cap.concurrency = opts[:concurrency] || @config[:concurrency]
298
+ end
299
+
300
+ opts[:capsules]&.each do |name, cap_config|
301
+ @config.capsule(name.to_s) do |cap|
302
+ cap.queues = cap_config[:queues]
303
+ cap.concurrency = cap_config[:concurrency]
304
+ end
305
+ end
306
+ end
307
+
308
+ def boot_application
309
+ ENV["RACK_ENV"] = ENV["RAILS_ENV"] = environment
310
+
311
+ if File.directory?(@config[:require])
312
+ require "rails"
313
+ if ::Rails::VERSION::MAJOR < 7
314
+ warn "Sidekiq #{Sidekiq::VERSION} only supports Rails 7+"
315
+ end
316
+ require "sidekiq/rails"
317
+ require File.expand_path("#{@config[:require]}/config/environment.rb")
318
+ @config[:tag] ||= default_tag(::Rails.root)
319
+ else
320
+ require @config[:require]
321
+ @config[:tag] ||= default_tag
322
+ end
323
+ end
324
+
325
+ def validate!
326
+ if !File.exist?(@config[:require]) ||
327
+ (File.directory?(@config[:require]) && !File.exist?("#{@config[:require]}/config/application.rb"))
328
+ logger.info "=================================================================="
329
+ logger.info " Please point Sidekiq to a Rails application or a Ruby file "
330
+ logger.info " to load your job classes with -r [DIR|FILE]."
331
+ logger.info "=================================================================="
332
+ logger.info @parser
333
+ die(1)
334
+ end
335
+
336
+ [:concurrency, :timeout].each do |opt|
337
+ raise ArgumentError, "#{opt}: #{@config[opt]} is not a valid value" if @config[opt].to_i <= 0
338
+ end
339
+ end
340
+
341
+ def parse_options(argv)
342
+ opts = {}
343
+ @parser = option_parser(opts)
344
+ @parser.parse!(argv)
345
+ opts
346
+ end
347
+
348
+ def option_parser(opts)
349
+ parser = OptionParser.new { |o|
350
+ o.on "-c", "--concurrency INT", "processor threads to use" do |arg|
351
+ opts[:concurrency] = Integer(arg)
352
+ end
353
+
354
+ o.on "-e", "--environment ENV", "Application environment" do |arg|
355
+ opts[:environment] = arg
356
+ end
357
+
358
+ o.on "-g", "--tag TAG", "Process tag for procline" do |arg|
359
+ opts[:tag] = arg
360
+ end
361
+
362
+ o.on "-q", "--queue QUEUE[,WEIGHT]", "Queues to process with optional weights" do |arg|
363
+ opts[:queues] ||= []
364
+ opts[:queues] << arg
365
+ end
366
+
367
+ o.on "-r", "--require [PATH|DIR]", "Location of Rails application with jobs or file to require" do |arg|
368
+ opts[:require] = arg
369
+ end
370
+
371
+ o.on "-t", "--timeout NUM", "Shutdown timeout" do |arg|
372
+ opts[:timeout] = Integer(arg)
373
+ end
374
+
375
+ o.on "-v", "--verbose", "Print more verbose output" do |arg|
376
+ opts[:verbose] = arg
377
+ end
378
+
379
+ o.on "-C", "--config PATH", "path to YAML config file" do |arg|
380
+ opts[:config_file] = arg
381
+ end
382
+
383
+ o.on "-V", "--version", "Print version and exit" do
384
+ puts "Sidekiq #{Sidekiq::VERSION}"
385
+ die(0)
386
+ end
387
+ }
388
+
389
+ parser.banner = "sidekiq [options]"
390
+ parser.on_tail "-h", "--help", "Show help" do
391
+ logger.info parser
392
+ die 1
393
+ end
394
+
395
+ parser
396
+ end
397
+
398
+ def initialize_logger
399
+ if @config[:verbose] || ENV["DEBUG_INVOCATION"] == "1"
400
+ # DEBUG_INVOCATION is a systemd-ism triggered by
401
+ # RestartMode=debug. We turn on debugging when the
402
+ # sidekiq process crashes and is restarted with this flag.
403
+ @config.logger.level = ::Logger::DEBUG
404
+ end
405
+ end
406
+
407
+ def parse_config(path)
408
+ erb = ERB.new(File.read(path), trim_mode: "-")
409
+ erb.filename = File.expand_path(path)
410
+ require "yaml"
411
+ opts = YAML.safe_load(erb.result, permitted_classes: [Symbol], aliases: true) || {}
412
+
413
+ if opts.respond_to? :deep_symbolize_keys!
414
+ opts.deep_symbolize_keys!
415
+ else
416
+ symbolize_keys_deep!(opts)
417
+ end
418
+
419
+ opts = opts.merge(opts.delete(environment.to_sym) || {})
420
+ opts.delete(:strict)
421
+
422
+ opts
423
+ end
424
+
425
+ def rails_app?
426
+ defined?(::Rails) && ::Rails.respond_to?(:application)
427
+ end
428
+ end
429
+ end
430
+
431
+ require "sidekiq/systemd"
432
+ require "sidekiq/metrics/tracking"
433
+ require "sidekiq/job/interrupt_handler"