sidekiq 6.2.2 → 8.1.5

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 (181) hide show
  1. checksums.yaml +4 -4
  2. data/Changes.md +726 -11
  3. data/LICENSE.txt +9 -0
  4. data/README.md +70 -39
  5. data/bin/kiq +17 -0
  6. data/bin/lint-herb +13 -0
  7. data/bin/multi_queue_bench +271 -0
  8. data/bin/sidekiq +4 -9
  9. data/bin/sidekiqload +214 -115
  10. data/bin/sidekiqmon +4 -1
  11. data/bin/webload +69 -0
  12. data/lib/active_job/queue_adapters/sidekiq_adapter.rb +124 -0
  13. data/lib/generators/sidekiq/job_generator.rb +71 -0
  14. data/lib/generators/sidekiq/templates/{worker.rb.erb → job.rb.erb} +3 -3
  15. data/lib/generators/sidekiq/templates/{worker_spec.rb.erb → job_spec.rb.erb} +1 -1
  16. data/lib/generators/sidekiq/templates/{worker_test.rb.erb → job_test.rb.erb} +1 -1
  17. data/lib/sidekiq/api.rb +729 -264
  18. data/lib/sidekiq/capsule.rb +135 -0
  19. data/lib/sidekiq/cli.rb +124 -100
  20. data/lib/sidekiq/client.rb +153 -106
  21. data/lib/sidekiq/component.rb +132 -0
  22. data/lib/sidekiq/config.rb +320 -0
  23. data/lib/sidekiq/deploy.rb +64 -0
  24. data/lib/sidekiq/embedded.rb +64 -0
  25. data/lib/sidekiq/fetch.rb +27 -26
  26. data/lib/sidekiq/iterable_job.rb +56 -0
  27. data/lib/sidekiq/job/interrupt_handler.rb +24 -0
  28. data/lib/sidekiq/job/iterable/active_record_enumerator.rb +53 -0
  29. data/lib/sidekiq/job/iterable/csv_enumerator.rb +47 -0
  30. data/lib/sidekiq/job/iterable/enumerators.rb +135 -0
  31. data/lib/sidekiq/job/iterable.rb +322 -0
  32. data/lib/sidekiq/job.rb +397 -5
  33. data/lib/sidekiq/job_logger.rb +23 -32
  34. data/lib/sidekiq/job_retry.rb +141 -68
  35. data/lib/sidekiq/job_util.rb +113 -0
  36. data/lib/sidekiq/launcher.rb +122 -98
  37. data/lib/sidekiq/loader.rb +57 -0
  38. data/lib/sidekiq/logger.rb +27 -106
  39. data/lib/sidekiq/manager.rb +41 -43
  40. data/lib/sidekiq/metrics/query.rb +184 -0
  41. data/lib/sidekiq/metrics/shared.rb +109 -0
  42. data/lib/sidekiq/metrics/tracking.rb +153 -0
  43. data/lib/sidekiq/middleware/chain.rb +96 -51
  44. data/lib/sidekiq/middleware/current_attributes.rb +120 -0
  45. data/lib/sidekiq/middleware/i18n.rb +8 -4
  46. data/lib/sidekiq/middleware/modules.rb +23 -0
  47. data/lib/sidekiq/monitor.rb +16 -6
  48. data/lib/sidekiq/paginator.rb +37 -10
  49. data/lib/sidekiq/processor.rb +105 -87
  50. data/lib/sidekiq/profiler.rb +73 -0
  51. data/lib/sidekiq/rails.rb +49 -36
  52. data/lib/sidekiq/redis_client_adapter.rb +117 -0
  53. data/lib/sidekiq/redis_connection.rb +55 -86
  54. data/lib/sidekiq/ring_buffer.rb +32 -0
  55. data/lib/sidekiq/scheduled.rb +106 -50
  56. data/lib/sidekiq/systemd.rb +2 -0
  57. data/lib/sidekiq/test_api.rb +331 -0
  58. data/lib/sidekiq/testing/inline.rb +2 -30
  59. data/lib/sidekiq/testing.rb +2 -342
  60. data/lib/sidekiq/transaction_aware_client.rb +59 -0
  61. data/lib/sidekiq/tui/controls.rb +53 -0
  62. data/lib/sidekiq/tui/filtering.rb +53 -0
  63. data/lib/sidekiq/tui/tabs/base_tab.rb +204 -0
  64. data/lib/sidekiq/tui/tabs/busy.rb +118 -0
  65. data/lib/sidekiq/tui/tabs/dead.rb +19 -0
  66. data/lib/sidekiq/tui/tabs/home.rb +144 -0
  67. data/lib/sidekiq/tui/tabs/metrics.rb +131 -0
  68. data/lib/sidekiq/tui/tabs/queues.rb +95 -0
  69. data/lib/sidekiq/tui/tabs/retries.rb +19 -0
  70. data/lib/sidekiq/tui/tabs/scheduled.rb +19 -0
  71. data/lib/sidekiq/tui/tabs/set_tab.rb +96 -0
  72. data/lib/sidekiq/tui/tabs.rb +15 -0
  73. data/lib/sidekiq/tui.rb +382 -0
  74. data/lib/sidekiq/version.rb +6 -1
  75. data/lib/sidekiq/web/action.rb +149 -64
  76. data/lib/sidekiq/web/application.rb +376 -268
  77. data/lib/sidekiq/web/config.rb +117 -0
  78. data/lib/sidekiq/web/helpers.rb +213 -87
  79. data/lib/sidekiq/web/router.rb +61 -74
  80. data/lib/sidekiq/web.rb +71 -100
  81. data/lib/sidekiq/worker_compatibility_alias.rb +13 -0
  82. data/lib/sidekiq.rb +95 -196
  83. data/sidekiq.gemspec +14 -11
  84. data/web/assets/images/logo.png +0 -0
  85. data/web/assets/images/status.png +0 -0
  86. data/web/assets/javascripts/application.js +171 -57
  87. data/web/assets/javascripts/base-charts.js +120 -0
  88. data/web/assets/javascripts/chart.min.js +13 -0
  89. data/web/assets/javascripts/chartjs-adapter-date-fns.min.js +7 -0
  90. data/web/assets/javascripts/chartjs-plugin-annotation.min.js +7 -0
  91. data/web/assets/javascripts/dashboard-charts.js +194 -0
  92. data/web/assets/javascripts/dashboard.js +41 -274
  93. data/web/assets/javascripts/metrics.js +280 -0
  94. data/web/assets/stylesheets/style.css +776 -0
  95. data/web/locales/ar.yml +72 -70
  96. data/web/locales/cs.yml +64 -62
  97. data/web/locales/da.yml +62 -53
  98. data/web/locales/de.yml +67 -65
  99. data/web/locales/el.yml +45 -24
  100. data/web/locales/en.yml +93 -69
  101. data/web/locales/es.yml +91 -68
  102. data/web/locales/fa.yml +67 -65
  103. data/web/locales/fr.yml +82 -67
  104. data/web/locales/gd.yml +110 -0
  105. data/web/locales/he.yml +67 -64
  106. data/web/locales/hi.yml +61 -59
  107. data/web/locales/it.yml +94 -54
  108. data/web/locales/ja.yml +74 -68
  109. data/web/locales/ko.yml +54 -52
  110. data/web/locales/lt.yml +68 -66
  111. data/web/locales/nb.yml +63 -61
  112. data/web/locales/nl.yml +54 -52
  113. data/web/locales/pl.yml +47 -45
  114. data/web/locales/{pt-br.yml → pt-BR.yml} +85 -56
  115. data/web/locales/pt.yml +53 -51
  116. data/web/locales/ru.yml +69 -66
  117. data/web/locales/sv.yml +55 -53
  118. data/web/locales/ta.yml +62 -60
  119. data/web/locales/tr.yml +102 -0
  120. data/web/locales/uk.yml +87 -61
  121. data/web/locales/ur.yml +66 -64
  122. data/web/locales/vi.yml +69 -67
  123. data/web/locales/zh-CN.yml +107 -0
  124. data/web/locales/{zh-tw.yml → zh-TW.yml} +44 -9
  125. data/web/views/_footer.html.erb +32 -0
  126. data/web/views/_job_info.html.erb +115 -0
  127. data/web/views/_metrics_period_select.html.erb +15 -0
  128. data/web/views/_nav.html.erb +45 -0
  129. data/web/views/_paging.html.erb +26 -0
  130. data/web/views/_poll_link.html.erb +4 -0
  131. data/web/views/_summary.html.erb +40 -0
  132. data/web/views/busy.html.erb +151 -0
  133. data/web/views/dashboard.html.erb +104 -0
  134. data/web/views/dead.html.erb +38 -0
  135. data/web/views/filtering.html.erb +6 -0
  136. data/web/views/layout.html.erb +26 -0
  137. data/web/views/metrics.html.erb +85 -0
  138. data/web/views/metrics_for_job.html.erb +58 -0
  139. data/web/views/morgue.html.erb +69 -0
  140. data/web/views/profiles.html.erb +43 -0
  141. data/web/views/queue.html.erb +57 -0
  142. data/web/views/queues.html.erb +46 -0
  143. data/web/views/retries.html.erb +77 -0
  144. data/web/views/retry.html.erb +39 -0
  145. data/web/views/scheduled.html.erb +64 -0
  146. data/web/views/{scheduled_job_info.erb → scheduled_job_info.html.erb} +3 -3
  147. metadata +130 -61
  148. data/LICENSE +0 -9
  149. data/lib/generators/sidekiq/worker_generator.rb +0 -57
  150. data/lib/sidekiq/delay.rb +0 -41
  151. data/lib/sidekiq/exception_handler.rb +0 -27
  152. data/lib/sidekiq/extensions/action_mailer.rb +0 -48
  153. data/lib/sidekiq/extensions/active_record.rb +0 -43
  154. data/lib/sidekiq/extensions/class_methods.rb +0 -43
  155. data/lib/sidekiq/extensions/generic_proxy.rb +0 -33
  156. data/lib/sidekiq/util.rb +0 -95
  157. data/lib/sidekiq/web/csrf_protection.rb +0 -180
  158. data/lib/sidekiq/worker.rb +0 -244
  159. data/web/assets/stylesheets/application-dark.css +0 -147
  160. data/web/assets/stylesheets/application-rtl.css +0 -246
  161. data/web/assets/stylesheets/application.css +0 -1053
  162. data/web/assets/stylesheets/bootstrap-rtl.min.css +0 -9
  163. data/web/assets/stylesheets/bootstrap.css +0 -5
  164. data/web/locales/zh-cn.yml +0 -68
  165. data/web/views/_footer.erb +0 -20
  166. data/web/views/_job_info.erb +0 -89
  167. data/web/views/_nav.erb +0 -52
  168. data/web/views/_paging.erb +0 -23
  169. data/web/views/_poll_link.erb +0 -7
  170. data/web/views/_status.erb +0 -4
  171. data/web/views/_summary.erb +0 -40
  172. data/web/views/busy.erb +0 -132
  173. data/web/views/dashboard.erb +0 -83
  174. data/web/views/dead.erb +0 -34
  175. data/web/views/layout.erb +0 -42
  176. data/web/views/morgue.erb +0 -78
  177. data/web/views/queue.erb +0 -55
  178. data/web/views/queues.erb +0 -38
  179. data/web/views/retries.erb +0 -83
  180. data/web/views/retry.erb +0 -34
  181. data/web/views/scheduled.erb +0 -57
data/lib/sidekiq/util.rb DELETED
@@ -1,95 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "forwardable"
4
- require "socket"
5
- require "securerandom"
6
- require "sidekiq/exception_handler"
7
-
8
- module Sidekiq
9
- ##
10
- # This module is part of Sidekiq core and not intended for extensions.
11
- #
12
-
13
- class RingBuffer
14
- include Enumerable
15
- extend Forwardable
16
- def_delegators :@buf, :[], :each, :size
17
-
18
- def initialize(size, default = 0)
19
- @size = size
20
- @buf = Array.new(size, default)
21
- @index = 0
22
- end
23
-
24
- def <<(element)
25
- @buf[@index % @size] = element
26
- @index += 1
27
- element
28
- end
29
-
30
- def buffer
31
- @buf
32
- end
33
-
34
- def reset(default = 0)
35
- @buf.fill(default)
36
- end
37
- end
38
-
39
- module Util
40
- include ExceptionHandler
41
-
42
- def watchdog(last_words)
43
- yield
44
- rescue Exception => ex
45
- handle_exception(ex, {context: last_words})
46
- raise ex
47
- end
48
-
49
- def safe_thread(name, &block)
50
- Thread.new do
51
- Thread.current.name = name
52
- watchdog(name, &block)
53
- end
54
- end
55
-
56
- def logger
57
- Sidekiq.logger
58
- end
59
-
60
- def redis(&block)
61
- Sidekiq.redis(&block)
62
- end
63
-
64
- def tid
65
- Thread.current["sidekiq_tid"] ||= (Thread.current.object_id ^ ::Process.pid).to_s(36)
66
- end
67
-
68
- def hostname
69
- ENV["DYNO"] || Socket.gethostname
70
- end
71
-
72
- def process_nonce
73
- @@process_nonce ||= SecureRandom.hex(6)
74
- end
75
-
76
- def identity
77
- @@identity ||= "#{hostname}:#{::Process.pid}:#{process_nonce}"
78
- end
79
-
80
- def fire_event(event, options = {})
81
- reverse = options[:reverse]
82
- reraise = options[:reraise]
83
-
84
- arr = Sidekiq.options[:lifecycle_events][event]
85
- arr.reverse! if reverse
86
- arr.each do |block|
87
- block.call
88
- rescue => ex
89
- handle_exception(ex, {context: "Exception during Sidekiq lifecycle event.", event: event})
90
- raise ex if reraise
91
- end
92
- arr.clear
93
- end
94
- end
95
- end
@@ -1,180 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # this file originally based on authenticity_token.rb from the sinatra/rack-protection project
4
- #
5
- # The MIT License (MIT)
6
- #
7
- # Copyright (c) 2011-2017 Konstantin Haase
8
- # Copyright (c) 2015-2017 Zachary Scott
9
- #
10
- # Permission is hereby granted, free of charge, to any person obtaining
11
- # a copy of this software and associated documentation files (the
12
- # 'Software'), to deal in the Software without restriction, including
13
- # without limitation the rights to use, copy, modify, merge, publish,
14
- # distribute, sublicense, and/or sell copies of the Software, and to
15
- # permit persons to whom the Software is furnished to do so, subject to
16
- # the following conditions:
17
- #
18
- # The above copyright notice and this permission notice shall be
19
- # included in all copies or substantial portions of the Software.
20
- #
21
- # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
22
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24
- # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
25
- # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26
- # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27
- # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
-
29
- require "securerandom"
30
- require "base64"
31
- require "rack/request"
32
-
33
- module Sidekiq
34
- class Web
35
- class CsrfProtection
36
- def initialize(app, options = nil)
37
- @app = app
38
- end
39
-
40
- def call(env)
41
- accept?(env) ? admit(env) : deny(env)
42
- end
43
-
44
- private
45
-
46
- def admit(env)
47
- # On each successful request, we create a fresh masked token
48
- # which will be used in any forms rendered for this request.
49
- s = session(env)
50
- s[:csrf] ||= SecureRandom.base64(TOKEN_LENGTH)
51
- env[:csrf_token] = mask_token(s[:csrf])
52
- @app.call(env)
53
- end
54
-
55
- def safe?(env)
56
- %w[GET HEAD OPTIONS TRACE].include? env["REQUEST_METHOD"]
57
- end
58
-
59
- def logger(env)
60
- @logger ||= (env["rack.logger"] || ::Logger.new(env["rack.errors"]))
61
- end
62
-
63
- def deny(env)
64
- logger(env).warn "attack prevented by #{self.class}"
65
- [403, {"Content-Type" => "text/plain"}, ["Forbidden"]]
66
- end
67
-
68
- def session(env)
69
- env["rack.session"] || fail(<<~EOM)
70
- Sidekiq::Web needs a valid Rack session for CSRF protection. If this is a Rails app,
71
- make sure you mount Sidekiq::Web *inside* your application routes:
72
-
73
-
74
- Rails.application.routes.draw do
75
- mount Sidekiq::Web => "/sidekiq"
76
- ....
77
- end
78
-
79
-
80
- If this is a Rails app in API mode, you need to enable sessions.
81
-
82
- https://guides.rubyonrails.org/api_app.html#using-session-middlewares
83
-
84
- If this is a bare Rack app, use a session middleware before Sidekiq::Web:
85
-
86
- # first, use IRB to create a shared secret key for sessions and commit it
87
- require 'securerandom'; File.open(".session.key", "w") {|f| f.write(SecureRandom.hex(32)) }
88
-
89
- # now use the secret with a session cookie middleware
90
- use Rack::Session::Cookie, secret: File.read(".session.key"), same_site: true, max_age: 86400
91
- run Sidekiq::Web
92
-
93
- EOM
94
- end
95
-
96
- def accept?(env)
97
- return true if safe?(env)
98
-
99
- giventoken = ::Rack::Request.new(env).params["authenticity_token"]
100
- valid_token?(env, giventoken)
101
- end
102
-
103
- TOKEN_LENGTH = 32
104
-
105
- # Checks that the token given to us as a parameter matches
106
- # the token stored in the session.
107
- def valid_token?(env, giventoken)
108
- return false if giventoken.nil? || giventoken.empty?
109
-
110
- begin
111
- token = decode_token(giventoken)
112
- rescue ArgumentError # client input is invalid
113
- return false
114
- end
115
-
116
- sess = session(env)
117
- localtoken = sess[:csrf]
118
-
119
- # Checks that Rack::Session::Cookie actualy contains the csrf toekn
120
- return false if localtoken.nil?
121
-
122
- # Rotate the session token after every use
123
- sess[:csrf] = SecureRandom.base64(TOKEN_LENGTH)
124
-
125
- # See if it's actually a masked token or not. We should be able
126
- # to handle any unmasked tokens that we've issued without error.
127
-
128
- if unmasked_token?(token)
129
- compare_with_real_token token, localtoken
130
- elsif masked_token?(token)
131
- unmasked = unmask_token(token)
132
- compare_with_real_token unmasked, localtoken
133
- else
134
- false # Token is malformed
135
- end
136
- end
137
-
138
- # Creates a masked version of the authenticity token that varies
139
- # on each request. The masking is used to mitigate SSL attacks
140
- # like BREACH.
141
- def mask_token(token)
142
- token = decode_token(token)
143
- one_time_pad = SecureRandom.random_bytes(token.length)
144
- encrypted_token = xor_byte_strings(one_time_pad, token)
145
- masked_token = one_time_pad + encrypted_token
146
- Base64.strict_encode64(masked_token)
147
- end
148
-
149
- # Essentially the inverse of +mask_token+.
150
- def unmask_token(masked_token)
151
- # Split the token into the one-time pad and the encrypted
152
- # value and decrypt it
153
- token_length = masked_token.length / 2
154
- one_time_pad = masked_token[0...token_length]
155
- encrypted_token = masked_token[token_length..-1]
156
- xor_byte_strings(one_time_pad, encrypted_token)
157
- end
158
-
159
- def unmasked_token?(token)
160
- token.length == TOKEN_LENGTH
161
- end
162
-
163
- def masked_token?(token)
164
- token.length == TOKEN_LENGTH * 2
165
- end
166
-
167
- def compare_with_real_token(token, local)
168
- ::Rack::Utils.secure_compare(token.to_s, decode_token(local).to_s)
169
- end
170
-
171
- def decode_token(token)
172
- Base64.strict_decode64(token)
173
- end
174
-
175
- def xor_byte_strings(s1, s2)
176
- s1.bytes.zip(s2.bytes).map { |(c1, c2)| c1 ^ c2 }.pack("c*")
177
- end
178
- end
179
- end
180
- end
@@ -1,244 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "sidekiq/client"
4
-
5
- module Sidekiq
6
- ##
7
- # Include this module in your worker class and you can easily create
8
- # asynchronous jobs:
9
- #
10
- # class HardWorker
11
- # include Sidekiq::Worker
12
- #
13
- # def perform(*args)
14
- # # do some work
15
- # end
16
- # end
17
- #
18
- # Then in your Rails app, you can do this:
19
- #
20
- # HardWorker.perform_async(1, 2, 3)
21
- #
22
- # Note that perform_async is a class method, perform is an instance method.
23
- module Worker
24
- ##
25
- # The Options module is extracted so we can include it in ActiveJob::Base
26
- # and allow native AJs to configure Sidekiq features/internals.
27
- module Options
28
- def self.included(base)
29
- base.extend(ClassMethods)
30
- base.sidekiq_class_attribute :sidekiq_options_hash
31
- base.sidekiq_class_attribute :sidekiq_retry_in_block
32
- base.sidekiq_class_attribute :sidekiq_retries_exhausted_block
33
- end
34
-
35
- module ClassMethods
36
- ACCESSOR_MUTEX = Mutex.new
37
-
38
- ##
39
- # Allows customization for this type of Worker.
40
- # Legal options:
41
- #
42
- # queue - name of queue to use for this job type, default *default*
43
- # retry - enable retries for this Worker in case of error during execution,
44
- # *true* to use the default or *Integer* count
45
- # backtrace - whether to save any error backtrace in the retry payload to display in web UI,
46
- # can be true, false or an integer number of lines to save, default *false*
47
- #
48
- # In practice, any option is allowed. This is the main mechanism to configure the
49
- # options for a specific job.
50
- def sidekiq_options(opts = {})
51
- opts = opts.transform_keys(&:to_s) # stringify
52
- self.sidekiq_options_hash = get_sidekiq_options.merge(opts)
53
- end
54
-
55
- def sidekiq_retry_in(&block)
56
- self.sidekiq_retry_in_block = block
57
- end
58
-
59
- def sidekiq_retries_exhausted(&block)
60
- self.sidekiq_retries_exhausted_block = block
61
- end
62
-
63
- def get_sidekiq_options # :nodoc:
64
- self.sidekiq_options_hash ||= Sidekiq.default_worker_options
65
- end
66
-
67
- def sidekiq_class_attribute(*attrs)
68
- instance_reader = true
69
- instance_writer = true
70
-
71
- attrs.each do |name|
72
- synchronized_getter = "__synchronized_#{name}"
73
-
74
- singleton_class.instance_eval do
75
- undef_method(name) if method_defined?(name) || private_method_defined?(name)
76
- end
77
-
78
- define_singleton_method(synchronized_getter) { nil }
79
- singleton_class.class_eval do
80
- private(synchronized_getter)
81
- end
82
-
83
- define_singleton_method(name) { ACCESSOR_MUTEX.synchronize { send synchronized_getter } }
84
-
85
- ivar = "@#{name}"
86
-
87
- singleton_class.instance_eval do
88
- m = "#{name}="
89
- undef_method(m) if method_defined?(m) || private_method_defined?(m)
90
- end
91
- define_singleton_method("#{name}=") do |val|
92
- singleton_class.class_eval do
93
- ACCESSOR_MUTEX.synchronize do
94
- undef_method(synchronized_getter) if method_defined?(synchronized_getter) || private_method_defined?(synchronized_getter)
95
- define_method(synchronized_getter) { val }
96
- end
97
- end
98
-
99
- if singleton_class?
100
- class_eval do
101
- undef_method(name) if method_defined?(name) || private_method_defined?(name)
102
- define_method(name) do
103
- if instance_variable_defined? ivar
104
- instance_variable_get ivar
105
- else
106
- singleton_class.send name
107
- end
108
- end
109
- end
110
- end
111
- val
112
- end
113
-
114
- if instance_reader
115
- undef_method(name) if method_defined?(name) || private_method_defined?(name)
116
- define_method(name) do
117
- if instance_variable_defined?(ivar)
118
- instance_variable_get ivar
119
- else
120
- self.class.public_send name
121
- end
122
- end
123
- end
124
-
125
- if instance_writer
126
- m = "#{name}="
127
- undef_method(m) if method_defined?(m) || private_method_defined?(m)
128
- attr_writer name
129
- end
130
- end
131
- end
132
- end
133
- end
134
-
135
- attr_accessor :jid
136
-
137
- def self.included(base)
138
- raise ArgumentError, "Sidekiq::Worker cannot be included in an ActiveJob: #{base.name}" if base.ancestors.any? { |c| c.name == "ActiveJob::Base" }
139
-
140
- base.include(Options)
141
- base.extend(ClassMethods)
142
- end
143
-
144
- def logger
145
- Sidekiq.logger
146
- end
147
-
148
- # This helper class encapsulates the set options for `set`, e.g.
149
- #
150
- # SomeWorker.set(queue: 'foo').perform_async(....)
151
- #
152
- class Setter
153
- def initialize(klass, opts)
154
- @klass = klass
155
- @opts = opts
156
- end
157
-
158
- def set(options)
159
- @opts.merge!(options)
160
- self
161
- end
162
-
163
- def perform_async(*args)
164
- @klass.client_push(@opts.merge("args" => args, "class" => @klass))
165
- end
166
-
167
- # +interval+ must be a timestamp, numeric or something that acts
168
- # numeric (like an activesupport time interval).
169
- def perform_in(interval, *args)
170
- int = interval.to_f
171
- now = Time.now.to_f
172
- ts = (int < 1_000_000_000 ? now + int : int)
173
-
174
- payload = @opts.merge("class" => @klass, "args" => args)
175
- # Optimization to enqueue something now that is scheduled to go out now or in the past
176
- payload["at"] = ts if ts > now
177
- @klass.client_push(payload)
178
- end
179
- alias_method :perform_at, :perform_in
180
- end
181
-
182
- module ClassMethods
183
- def delay(*args)
184
- raise ArgumentError, "Do not call .delay on a Sidekiq::Worker class, call .perform_async"
185
- end
186
-
187
- def delay_for(*args)
188
- raise ArgumentError, "Do not call .delay_for on a Sidekiq::Worker class, call .perform_in"
189
- end
190
-
191
- def delay_until(*args)
192
- raise ArgumentError, "Do not call .delay_until on a Sidekiq::Worker class, call .perform_at"
193
- end
194
-
195
- def set(options)
196
- Setter.new(self, options)
197
- end
198
-
199
- def perform_async(*args)
200
- client_push("class" => self, "args" => args)
201
- end
202
-
203
- # +interval+ must be a timestamp, numeric or something that acts
204
- # numeric (like an activesupport time interval).
205
- def perform_in(interval, *args)
206
- int = interval.to_f
207
- now = Time.now.to_f
208
- ts = (int < 1_000_000_000 ? now + int : int)
209
-
210
- item = {"class" => self, "args" => args}
211
-
212
- # Optimization to enqueue something now that is scheduled to go out now or in the past
213
- item["at"] = ts if ts > now
214
-
215
- client_push(item)
216
- end
217
- alias_method :perform_at, :perform_in
218
-
219
- ##
220
- # Allows customization for this type of Worker.
221
- # Legal options:
222
- #
223
- # queue - use a named queue for this Worker, default 'default'
224
- # retry - enable the RetryJobs middleware for this Worker, *true* to use the default
225
- # or *Integer* count
226
- # backtrace - whether to save any error backtrace in the retry payload to display in web UI,
227
- # can be true, false or an integer number of lines to save, default *false*
228
- # pool - use the given Redis connection pool to push this type of job to a given shard.
229
- #
230
- # In practice, any option is allowed. This is the main mechanism to configure the
231
- # options for a specific job.
232
- def sidekiq_options(opts = {})
233
- super
234
- end
235
-
236
- def client_push(item) # :nodoc:
237
- pool = Thread.current[:sidekiq_via_pool] || get_sidekiq_options["pool"] || Sidekiq.redis_pool
238
- stringified_item = item.transform_keys(&:to_s)
239
-
240
- Sidekiq::Client.new(pool).push(stringified_item)
241
- end
242
- end
243
- end
244
- end
@@ -1,147 +0,0 @@
1
- html, body {
2
- background-color: #333 !important;
3
- color: #ddd;
4
- }
5
-
6
- a,
7
- .title,
8
- .summary_bar ul .count,
9
- span.current-interval,
10
- .navbar .navbar-brand {
11
- color: #c04;
12
- }
13
-
14
- .history-graph + .active,
15
- .beacon .dot {
16
- background-color: #c04;
17
- }
18
-
19
- .navbar .navbar-brand:hover {
20
- color: #ddd;
21
- }
22
-
23
- .navbar .navbar-brand .status {
24
- color: #ddd;
25
- }
26
-
27
- .navbar-default .navbar-nav > li > a {
28
- color: #ddd;
29
- }
30
-
31
- .navbar-inverse {
32
- background-color: #222;
33
- border-color: #555;
34
- }
35
-
36
- table {
37
- background-color: #282828;
38
- }
39
-
40
- .table-striped > tbody > tr:nth-of-type(odd) {
41
- background-color: #333;
42
- }
43
-
44
- .table-bordered,
45
- .table-bordered > tbody > tr > td,
46
- .table-bordered > tbody > tr > th,
47
- .table-bordered > tfoot > tr > td,
48
- .table-bordered > tfoot > tr > th,
49
- .table-bordered > thead > tr > td,
50
- .table-bordered > thead > tr > th {
51
- border: 1px solid #555;
52
- }
53
-
54
- .table-hover > tbody > tr:hover {
55
- background-color: #444;
56
- }
57
-
58
- .alert {
59
- border: none;
60
- color: #ddd;
61
- }
62
-
63
- .alert-success {
64
- background-color: #484;
65
- }
66
-
67
- .alert-danger {
68
- background-color: #980035;
69
- }
70
-
71
- .alert-info {
72
- background-color: #31708f;
73
- }
74
-
75
- a:link,
76
- a:active,
77
- a:hover {
78
- color: #ddd;
79
- }
80
-
81
- input {
82
- background-color: #444;
83
- color: #ccc;
84
- padding: 3px;
85
- }
86
-
87
- .summary_bar .summary {
88
- background-color: #222;
89
- border: 1px solid #555;
90
-
91
- box-shadow: 0 0 5px rgba(255, 255, 255, 0.1);
92
- }
93
-
94
- .navbar-default {
95
- background-color: #222;
96
- border-color: #555;
97
- }
98
-
99
- .navbar-default .navbar-nav > .active > a,
100
- .navbar-default .navbar-nav > .active > a:focus,
101
- .navbar-default .navbar-nav > .active > a:hover {
102
- color: #ddd;
103
- background-color: #333;
104
- }
105
-
106
- .navbar-default .navbar-nav > li > a:hover {
107
- color: #ddd;
108
- }
109
-
110
- .pagination > li > a,
111
- .pagination > li > a:hover,
112
- .pagination > li > span {
113
- color: #ddd;
114
- background-color: #333;
115
- border-color: #555;
116
- }
117
- .pagination > .disabled > a,
118
- .pagination > .disabled > a:focus,
119
- .pagination > .disabled > a:hover,
120
- .pagination > .disabled > span,
121
- .pagination > .disabled > span:focus,
122
- .pagination > .disabled > span:hover {
123
- color: #ddd;
124
- background-color: #333;
125
- border-color: #555;
126
- }
127
-
128
- .stat {
129
- border: 1px solid rgba(255, 255, 255, 0.1);
130
- }
131
-
132
- .rickshaw_graph .detail {
133
- background: rgba(255, 255, 255, .1)
134
- }
135
- .rickshaw_graph .x_tick {
136
- border-color: rgba(255, 255, 255, .2);
137
- }
138
-
139
- .rickshaw_graph .y_ticks.glow text {
140
- fill: #ddd;
141
- color: #ddd;
142
- }
143
-
144
- .info-circle {
145
- color: #222;
146
- background-color: #888;
147
- }