sidekiq 3.4.1 → 7.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (235) hide show
  1. checksums.yaml +5 -5
  2. data/Changes.md +1118 -4
  3. data/LICENSE.txt +9 -0
  4. data/README.md +55 -47
  5. data/bin/multi_queue_bench +271 -0
  6. data/bin/sidekiq +26 -3
  7. data/bin/sidekiqload +247 -0
  8. data/bin/sidekiqmon +11 -0
  9. data/lib/generators/sidekiq/job_generator.rb +57 -0
  10. data/lib/generators/sidekiq/templates/{worker.rb.erb → job.rb.erb} +2 -2
  11. data/lib/generators/sidekiq/templates/job_spec.rb.erb +6 -0
  12. data/lib/generators/sidekiq/templates/job_test.rb.erb +8 -0
  13. data/lib/sidekiq/api.rb +714 -312
  14. data/lib/sidekiq/capsule.rb +130 -0
  15. data/lib/sidekiq/cli.rb +275 -241
  16. data/lib/sidekiq/client.rb +141 -110
  17. data/lib/sidekiq/component.rb +68 -0
  18. data/lib/sidekiq/config.rb +291 -0
  19. data/lib/sidekiq/deploy.rb +62 -0
  20. data/lib/sidekiq/embedded.rb +61 -0
  21. data/lib/sidekiq/fetch.rb +53 -121
  22. data/lib/sidekiq/iterable_job.rb +53 -0
  23. data/lib/sidekiq/job/interrupt_handler.rb +22 -0
  24. data/lib/sidekiq/job/iterable/active_record_enumerator.rb +53 -0
  25. data/lib/sidekiq/job/iterable/csv_enumerator.rb +47 -0
  26. data/lib/sidekiq/job/iterable/enumerators.rb +135 -0
  27. data/lib/sidekiq/job/iterable.rb +231 -0
  28. data/lib/sidekiq/job.rb +385 -0
  29. data/lib/sidekiq/job_logger.rb +64 -0
  30. data/lib/sidekiq/job_retry.rb +305 -0
  31. data/lib/sidekiq/job_util.rb +107 -0
  32. data/lib/sidekiq/launcher.rb +241 -66
  33. data/lib/sidekiq/logger.rb +131 -0
  34. data/lib/sidekiq/manager.rb +91 -192
  35. data/lib/sidekiq/metrics/query.rb +156 -0
  36. data/lib/sidekiq/metrics/shared.rb +95 -0
  37. data/lib/sidekiq/metrics/tracking.rb +140 -0
  38. data/lib/sidekiq/middleware/chain.rb +114 -56
  39. data/lib/sidekiq/middleware/current_attributes.rb +111 -0
  40. data/lib/sidekiq/middleware/i18n.rb +8 -7
  41. data/lib/sidekiq/middleware/modules.rb +21 -0
  42. data/lib/sidekiq/monitor.rb +146 -0
  43. data/lib/sidekiq/paginator.rb +29 -16
  44. data/lib/sidekiq/processor.rb +248 -112
  45. data/lib/sidekiq/rails.rb +61 -27
  46. data/lib/sidekiq/redis_client_adapter.rb +114 -0
  47. data/lib/sidekiq/redis_connection.rb +68 -48
  48. data/lib/sidekiq/ring_buffer.rb +29 -0
  49. data/lib/sidekiq/scheduled.rb +173 -52
  50. data/lib/sidekiq/sd_notify.rb +149 -0
  51. data/lib/sidekiq/systemd.rb +24 -0
  52. data/lib/sidekiq/testing/inline.rb +7 -5
  53. data/lib/sidekiq/testing.rb +206 -65
  54. data/lib/sidekiq/transaction_aware_client.rb +51 -0
  55. data/lib/sidekiq/version.rb +4 -1
  56. data/lib/sidekiq/web/action.rb +99 -0
  57. data/lib/sidekiq/web/application.rb +479 -0
  58. data/lib/sidekiq/web/csrf_protection.rb +183 -0
  59. data/lib/sidekiq/web/helpers.rb +415 -0
  60. data/lib/sidekiq/web/router.rb +104 -0
  61. data/lib/sidekiq/web.rb +158 -200
  62. data/lib/sidekiq/worker_compatibility_alias.rb +13 -0
  63. data/lib/sidekiq.rb +100 -132
  64. data/sidekiq.gemspec +27 -23
  65. data/web/assets/images/apple-touch-icon.png +0 -0
  66. data/web/assets/images/favicon.ico +0 -0
  67. data/web/assets/javascripts/application.js +177 -72
  68. data/web/assets/javascripts/base-charts.js +106 -0
  69. data/web/assets/javascripts/chart.min.js +13 -0
  70. data/web/assets/javascripts/chartjs-plugin-annotation.min.js +7 -0
  71. data/web/assets/javascripts/dashboard-charts.js +192 -0
  72. data/web/assets/javascripts/dashboard.js +37 -286
  73. data/web/assets/javascripts/metrics.js +298 -0
  74. data/web/assets/stylesheets/application-dark.css +147 -0
  75. data/web/assets/stylesheets/application-rtl.css +163 -0
  76. data/web/assets/stylesheets/application.css +228 -247
  77. data/web/assets/stylesheets/bootstrap-rtl.min.css +9 -0
  78. data/web/assets/stylesheets/bootstrap.css +4 -8
  79. data/web/locales/ar.yml +87 -0
  80. data/web/locales/cs.yml +62 -52
  81. data/web/locales/da.yml +60 -53
  82. data/web/locales/de.yml +65 -53
  83. data/web/locales/el.yml +43 -24
  84. data/web/locales/en.yml +86 -61
  85. data/web/locales/es.yml +70 -53
  86. data/web/locales/fa.yml +80 -0
  87. data/web/locales/fr.yml +86 -56
  88. data/web/locales/gd.yml +99 -0
  89. data/web/locales/he.yml +80 -0
  90. data/web/locales/hi.yml +59 -59
  91. data/web/locales/it.yml +53 -53
  92. data/web/locales/ja.yml +78 -56
  93. data/web/locales/ko.yml +52 -52
  94. data/web/locales/lt.yml +83 -0
  95. data/web/locales/{no.yml → nb.yml} +62 -54
  96. data/web/locales/nl.yml +52 -52
  97. data/web/locales/pl.yml +45 -45
  98. data/web/locales/pt-br.yml +83 -55
  99. data/web/locales/pt.yml +51 -51
  100. data/web/locales/ru.yml +68 -60
  101. data/web/locales/sv.yml +53 -53
  102. data/web/locales/ta.yml +60 -60
  103. data/web/locales/tr.yml +101 -0
  104. data/web/locales/uk.yml +77 -0
  105. data/web/locales/ur.yml +80 -0
  106. data/web/locales/vi.yml +83 -0
  107. data/web/locales/zh-cn.yml +43 -16
  108. data/web/locales/zh-tw.yml +42 -8
  109. data/web/views/_footer.erb +22 -9
  110. data/web/views/_job_info.erb +27 -6
  111. data/web/views/_metrics_period_select.erb +12 -0
  112. data/web/views/_nav.erb +8 -22
  113. data/web/views/_paging.erb +3 -1
  114. data/web/views/_poll_link.erb +4 -0
  115. data/web/views/_summary.erb +7 -7
  116. data/web/views/busy.erb +91 -31
  117. data/web/views/dashboard.erb +52 -22
  118. data/web/views/dead.erb +5 -4
  119. data/web/views/filtering.erb +7 -0
  120. data/web/views/layout.erb +19 -7
  121. data/web/views/metrics.erb +91 -0
  122. data/web/views/metrics_for_job.erb +59 -0
  123. data/web/views/morgue.erb +26 -20
  124. data/web/views/queue.erb +36 -25
  125. data/web/views/queues.erb +24 -7
  126. data/web/views/retries.erb +29 -21
  127. data/web/views/retry.erb +6 -5
  128. data/web/views/scheduled.erb +20 -17
  129. data/web/views/scheduled_job_info.erb +2 -1
  130. metadata +101 -232
  131. data/.gitignore +0 -12
  132. data/.travis.yml +0 -16
  133. data/3.0-Upgrade.md +0 -70
  134. data/COMM-LICENSE +0 -85
  135. data/Contributing.md +0 -32
  136. data/Gemfile +0 -22
  137. data/LICENSE +0 -9
  138. data/Pro-2.0-Upgrade.md +0 -138
  139. data/Pro-Changes.md +0 -412
  140. data/Rakefile +0 -9
  141. data/bin/sidekiqctl +0 -93
  142. data/lib/generators/sidekiq/templates/worker_spec.rb.erb +0 -6
  143. data/lib/generators/sidekiq/templates/worker_test.rb.erb +0 -8
  144. data/lib/generators/sidekiq/worker_generator.rb +0 -49
  145. data/lib/sidekiq/actor.rb +0 -39
  146. data/lib/sidekiq/core_ext.rb +0 -105
  147. data/lib/sidekiq/exception_handler.rb +0 -30
  148. data/lib/sidekiq/extensions/action_mailer.rb +0 -56
  149. data/lib/sidekiq/extensions/active_record.rb +0 -39
  150. data/lib/sidekiq/extensions/class_methods.rb +0 -39
  151. data/lib/sidekiq/extensions/generic_proxy.rb +0 -24
  152. data/lib/sidekiq/logging.rb +0 -104
  153. data/lib/sidekiq/middleware/server/active_record.rb +0 -13
  154. data/lib/sidekiq/middleware/server/logging.rb +0 -35
  155. data/lib/sidekiq/middleware/server/retry_jobs.rb +0 -206
  156. data/lib/sidekiq/util.rb +0 -55
  157. data/lib/sidekiq/web_helpers.rb +0 -234
  158. data/lib/sidekiq/worker.rb +0 -89
  159. data/test/config.yml +0 -9
  160. data/test/env_based_config.yml +0 -11
  161. data/test/fake_env.rb +0 -0
  162. data/test/fixtures/en.yml +0 -2
  163. data/test/helper.rb +0 -39
  164. data/test/test_api.rb +0 -494
  165. data/test/test_cli.rb +0 -365
  166. data/test/test_client.rb +0 -269
  167. data/test/test_exception_handler.rb +0 -55
  168. data/test/test_extensions.rb +0 -120
  169. data/test/test_fetch.rb +0 -104
  170. data/test/test_logging.rb +0 -34
  171. data/test/test_manager.rb +0 -164
  172. data/test/test_middleware.rb +0 -159
  173. data/test/test_processor.rb +0 -166
  174. data/test/test_redis_connection.rb +0 -127
  175. data/test/test_retry.rb +0 -373
  176. data/test/test_scheduled.rb +0 -120
  177. data/test/test_scheduling.rb +0 -71
  178. data/test/test_sidekiq.rb +0 -69
  179. data/test/test_testing.rb +0 -82
  180. data/test/test_testing_fake.rb +0 -271
  181. data/test/test_testing_inline.rb +0 -93
  182. data/test/test_web.rb +0 -594
  183. data/test/test_web_helpers.rb +0 -52
  184. data/test/test_worker_generator.rb +0 -17
  185. data/web/assets/images/bootstrap/glyphicons-halflings-white.png +0 -0
  186. data/web/assets/images/bootstrap/glyphicons-halflings.png +0 -0
  187. data/web/assets/images/status/active.png +0 -0
  188. data/web/assets/images/status/idle.png +0 -0
  189. data/web/assets/javascripts/locales/README.md +0 -27
  190. data/web/assets/javascripts/locales/jquery.timeago.ar.js +0 -96
  191. data/web/assets/javascripts/locales/jquery.timeago.bg.js +0 -18
  192. data/web/assets/javascripts/locales/jquery.timeago.bs.js +0 -49
  193. data/web/assets/javascripts/locales/jquery.timeago.ca.js +0 -18
  194. data/web/assets/javascripts/locales/jquery.timeago.cs.js +0 -18
  195. data/web/assets/javascripts/locales/jquery.timeago.cy.js +0 -20
  196. data/web/assets/javascripts/locales/jquery.timeago.da.js +0 -18
  197. data/web/assets/javascripts/locales/jquery.timeago.de.js +0 -18
  198. data/web/assets/javascripts/locales/jquery.timeago.el.js +0 -18
  199. data/web/assets/javascripts/locales/jquery.timeago.en-short.js +0 -20
  200. data/web/assets/javascripts/locales/jquery.timeago.en.js +0 -20
  201. data/web/assets/javascripts/locales/jquery.timeago.es.js +0 -18
  202. data/web/assets/javascripts/locales/jquery.timeago.et.js +0 -18
  203. data/web/assets/javascripts/locales/jquery.timeago.fa.js +0 -22
  204. data/web/assets/javascripts/locales/jquery.timeago.fi.js +0 -28
  205. data/web/assets/javascripts/locales/jquery.timeago.fr-short.js +0 -16
  206. data/web/assets/javascripts/locales/jquery.timeago.fr.js +0 -17
  207. data/web/assets/javascripts/locales/jquery.timeago.he.js +0 -18
  208. data/web/assets/javascripts/locales/jquery.timeago.hr.js +0 -49
  209. data/web/assets/javascripts/locales/jquery.timeago.hu.js +0 -18
  210. data/web/assets/javascripts/locales/jquery.timeago.hy.js +0 -18
  211. data/web/assets/javascripts/locales/jquery.timeago.id.js +0 -18
  212. data/web/assets/javascripts/locales/jquery.timeago.it.js +0 -16
  213. data/web/assets/javascripts/locales/jquery.timeago.ja.js +0 -19
  214. data/web/assets/javascripts/locales/jquery.timeago.ko.js +0 -17
  215. data/web/assets/javascripts/locales/jquery.timeago.lt.js +0 -20
  216. data/web/assets/javascripts/locales/jquery.timeago.mk.js +0 -20
  217. data/web/assets/javascripts/locales/jquery.timeago.nl.js +0 -20
  218. data/web/assets/javascripts/locales/jquery.timeago.no.js +0 -18
  219. data/web/assets/javascripts/locales/jquery.timeago.pl.js +0 -31
  220. data/web/assets/javascripts/locales/jquery.timeago.pt-br.js +0 -16
  221. data/web/assets/javascripts/locales/jquery.timeago.pt.js +0 -16
  222. data/web/assets/javascripts/locales/jquery.timeago.ro.js +0 -18
  223. data/web/assets/javascripts/locales/jquery.timeago.rs.js +0 -49
  224. data/web/assets/javascripts/locales/jquery.timeago.ru.js +0 -34
  225. data/web/assets/javascripts/locales/jquery.timeago.sk.js +0 -18
  226. data/web/assets/javascripts/locales/jquery.timeago.sl.js +0 -44
  227. data/web/assets/javascripts/locales/jquery.timeago.sv.js +0 -18
  228. data/web/assets/javascripts/locales/jquery.timeago.th.js +0 -20
  229. data/web/assets/javascripts/locales/jquery.timeago.tr.js +0 -16
  230. data/web/assets/javascripts/locales/jquery.timeago.uk.js +0 -34
  231. data/web/assets/javascripts/locales/jquery.timeago.uz.js +0 -19
  232. data/web/assets/javascripts/locales/jquery.timeago.zh-cn.js +0 -20
  233. data/web/assets/javascripts/locales/jquery.timeago.zh-tw.js +0 -20
  234. data/web/views/_poll.erb +0 -10
  235. /data/web/assets/images/{status-sd8051fd480.png → status.png} +0 -0
@@ -1,206 +0,0 @@
1
- require 'sidekiq/scheduled'
2
- require 'sidekiq/api'
3
-
4
- module Sidekiq
5
- module Middleware
6
- module Server
7
- ##
8
- # Automatically retry jobs that fail in Sidekiq.
9
- # Sidekiq's retry support assumes a typical development lifecycle:
10
- #
11
- # 0. push some code changes with a bug in it
12
- # 1. bug causes job processing to fail, sidekiq's middleware captures
13
- # the job and pushes it onto a retry queue
14
- # 2. sidekiq retries jobs in the retry queue multiple times with
15
- # an exponential delay, the job continues to fail
16
- # 3. after a few days, a developer deploys a fix. the job is
17
- # reprocessed successfully.
18
- # 4. once retries are exhausted, sidekiq will give up and move the
19
- # job to the Dead Job Queue (aka morgue) where it must be dealt with
20
- # manually in the Web UI.
21
- # 5. After 6 months on the DJQ, Sidekiq will discard the job.
22
- #
23
- # A job looks like:
24
- #
25
- # { 'class' => 'HardWorker', 'args' => [1, 2, 'foo'], 'retry' => true }
26
- #
27
- # The 'retry' option also accepts a number (in place of 'true'):
28
- #
29
- # { 'class' => 'HardWorker', 'args' => [1, 2, 'foo'], 'retry' => 5 }
30
- #
31
- # The job will be retried this number of times before giving up. (If simply
32
- # 'true', Sidekiq retries 25 times)
33
- #
34
- # We'll add a bit more data to the job to support retries:
35
- #
36
- # * 'queue' - the queue to use
37
- # * 'retry_count' - number of times we've retried so far.
38
- # * 'error_message' - the message from the exception
39
- # * 'error_class' - the exception class
40
- # * 'failed_at' - the first time it failed
41
- # * 'retried_at' - the last time it was retried
42
- # * 'backtrace' - the number of lines of error backtrace to store
43
- #
44
- # We don't store the backtrace by default as that can add a lot of overhead
45
- # to the job and everyone is using an error service, right?
46
- #
47
- # The default number of retry attempts is 25 which works out to about 3 weeks
48
- # of retries. You can pass a value for the max number of retry attempts when
49
- # adding the middleware using the options hash:
50
- #
51
- # Sidekiq.configure_server do |config|
52
- # config.server_middleware do |chain|
53
- # chain.add Sidekiq::Middleware::Server::RetryJobs, :max_retries => 7
54
- # end
55
- # end
56
- #
57
- # or limit the number of retries for a particular worker with:
58
- #
59
- # class MyWorker
60
- # include Sidekiq::Worker
61
- # sidekiq_options :retry => 10
62
- # end
63
- #
64
- class RetryJobs
65
- include Sidekiq::Util
66
-
67
- DEFAULT_MAX_RETRY_ATTEMPTS = 25
68
-
69
- def initialize(options = {})
70
- @max_retries = options.fetch(:max_retries, DEFAULT_MAX_RETRY_ATTEMPTS)
71
- end
72
-
73
- def call(worker, msg, queue)
74
- yield
75
- rescue Sidekiq::Shutdown
76
- # ignore, will be pushed back onto queue during hard_shutdown
77
- raise
78
- rescue Exception => e
79
- # ignore, will be pushed back onto queue during hard_shutdown
80
- raise Sidekiq::Shutdown if exception_caused_by_shutdown?(e)
81
-
82
- raise e unless msg['retry']
83
- attempt_retry(worker, msg, queue, e)
84
- end
85
-
86
- private
87
-
88
- def attempt_retry(worker, msg, queue, exception)
89
- max_retry_attempts = retry_attempts_from(msg['retry'], @max_retries)
90
-
91
- msg['queue'] = if msg['retry_queue']
92
- msg['retry_queue']
93
- else
94
- queue
95
- end
96
-
97
- # App code can stuff all sorts of crazy binary data into the error message
98
- # that won't convert to JSON.
99
- m = exception.message[0..10_000]
100
- if m.respond_to?(:scrub!)
101
- m.force_encoding("utf-8")
102
- m.scrub!
103
- end
104
-
105
- msg['error_message'] = m
106
- msg['error_class'] = exception.class.name
107
- count = if msg['retry_count']
108
- msg['retried_at'] = Time.now.to_f
109
- msg['retry_count'] += 1
110
- else
111
- msg['failed_at'] = Time.now.to_f
112
- msg['retry_count'] = 0
113
- end
114
-
115
- if msg['backtrace'] == true
116
- msg['error_backtrace'] = exception.backtrace
117
- elsif !msg['backtrace']
118
- # do nothing
119
- elsif msg['backtrace'].to_i != 0
120
- msg['error_backtrace'] = exception.backtrace[0...msg['backtrace'].to_i]
121
- end
122
-
123
- if count < max_retry_attempts
124
- delay = delay_for(worker, count)
125
- logger.debug { "Failure! Retry #{count} in #{delay} seconds" }
126
- retry_at = Time.now.to_f + delay
127
- payload = Sidekiq.dump_json(msg)
128
- Sidekiq.redis do |conn|
129
- conn.zadd('retry', retry_at.to_s, payload)
130
- end
131
- else
132
- # Goodbye dear message, you (re)tried your best I'm sure.
133
- retries_exhausted(worker, msg)
134
- end
135
-
136
- raise exception
137
- end
138
-
139
- def retries_exhausted(worker, msg)
140
- logger.debug { "Dropping message after hitting the retry maximum: #{msg}" }
141
- begin
142
- if worker.sidekiq_retries_exhausted_block?
143
- worker.sidekiq_retries_exhausted_block.call(msg)
144
- end
145
- rescue => e
146
- handle_exception(e, { context: "Error calling retries_exhausted for #{worker.class}", job: msg })
147
- end
148
-
149
- send_to_morgue(msg) unless msg['dead'] == false
150
- end
151
-
152
- def send_to_morgue(msg)
153
- Sidekiq.logger.info { "Adding dead #{msg['class']} job #{msg['jid']}" }
154
- payload = Sidekiq.dump_json(msg)
155
- now = Time.now.to_f
156
- Sidekiq.redis do |conn|
157
- conn.multi do
158
- conn.zadd('dead', now, payload)
159
- conn.zremrangebyscore('dead', '-inf', now - DeadSet.timeout)
160
- conn.zremrangebyrank('dead', 0, -DeadSet.max_jobs)
161
- end
162
- end
163
- end
164
-
165
- def retry_attempts_from(msg_retry, default)
166
- if msg_retry.is_a?(Fixnum)
167
- msg_retry
168
- else
169
- default
170
- end
171
- end
172
-
173
- def delay_for(worker, count)
174
- worker.sidekiq_retry_in_block? && retry_in(worker, count) || seconds_to_delay(count)
175
- end
176
-
177
- # delayed_job uses the same basic formula
178
- def seconds_to_delay(count)
179
- (count ** 4) + 15 + (rand(30)*(count+1))
180
- end
181
-
182
- def retry_in(worker, count)
183
- begin
184
- worker.sidekiq_retry_in_block.call(count)
185
- rescue Exception => e
186
- handle_exception(e, { context: "Failure scheduling retry using the defined `sidekiq_retry_in` in #{worker.class.name}, falling back to default" })
187
- nil
188
- end
189
- end
190
-
191
- def exception_caused_by_shutdown?(e, checked_causes = [])
192
- # In Ruby 2.1.0 only, check if exception is a result of shutdown.
193
- return false unless defined?(e.cause)
194
-
195
- # Handle circular causes
196
- checked_causes << e.object_id
197
- return false if checked_causes.include?(e.cause.object_id)
198
-
199
- e.cause.instance_of?(Sidekiq::Shutdown) ||
200
- exception_caused_by_shutdown?(e.cause, checked_causes)
201
- end
202
-
203
- end
204
- end
205
- end
206
- end
data/lib/sidekiq/util.rb DELETED
@@ -1,55 +0,0 @@
1
- require 'socket'
2
- require 'securerandom'
3
- require 'sidekiq/exception_handler'
4
- require 'sidekiq/core_ext'
5
-
6
- module Sidekiq
7
- ##
8
- # This module is part of Sidekiq core and not intended for extensions.
9
- #
10
- module Util
11
- include ExceptionHandler
12
-
13
- EXPIRY = 60 * 60 * 24
14
-
15
- def watchdog(last_words)
16
- yield
17
- rescue Exception => ex
18
- handle_exception(ex, { context: last_words })
19
- raise ex
20
- end
21
-
22
- def logger
23
- Sidekiq.logger
24
- end
25
-
26
- def redis(&block)
27
- Sidekiq.redis(&block)
28
- end
29
-
30
- def hostname
31
- ENV['DYNO'] || Socket.gethostname
32
- end
33
-
34
- def process_nonce
35
- @@process_nonce ||= SecureRandom.hex(6)
36
- end
37
-
38
- def identity
39
- @@identity ||= "#{hostname}:#{$$}:#{process_nonce}"
40
- end
41
-
42
- def fire_event(event, reverse=false)
43
- arr = Sidekiq.options[:lifecycle_events][event]
44
- arr.reverse! if reverse
45
- arr.each do |block|
46
- begin
47
- block.call
48
- rescue => ex
49
- handle_exception(ex, { event: event })
50
- end
51
- end
52
- end
53
-
54
- end
55
- end
@@ -1,234 +0,0 @@
1
- require 'uri'
2
-
3
- module Sidekiq
4
- # This is not a public API
5
- module WebHelpers
6
- def strings(lang)
7
- @@strings ||= {}
8
- @@strings[lang] ||= begin
9
- # Allow sidekiq-web extensions to add locale paths
10
- # so extensions can be localized
11
- settings.locales.each_with_object({}) do |path, global|
12
- find_locale_files(lang).each do |file|
13
- strs = YAML.load(File.open(file))
14
- global.deep_merge!(strs[lang])
15
- end
16
- end
17
- end
18
- end
19
-
20
- def locale_files
21
- @@locale_files = settings.locales.flat_map do |path|
22
- Dir["#{path}/*.yml"]
23
- end
24
- end
25
-
26
- def find_locale_files(lang)
27
- locale_files.select { |file| file =~ /\/#{lang}\.yml$/ }
28
- end
29
-
30
- # This is a hook for a Sidekiq Pro feature. Please don't touch.
31
- def filtering(*)
32
- end
33
-
34
- # This view helper provide ability display you html code in
35
- # to head of page. Example:
36
- #
37
- # <% add_to_head do %>
38
- # <link rel="stylesheet" .../>
39
- # <meta .../>
40
- # <% end %>
41
- #
42
- def add_to_head(&block)
43
- @head_html ||= []
44
- @head_html << block if block_given?
45
- end
46
-
47
- def display_custom_head
48
- return unless @head_html
49
- @head_html.map { |block| capture(&block) }.join
50
- end
51
-
52
- # Simple capture method for erb templates. The origin was
53
- # capture method from sinatra-contrib library.
54
- def capture(&block)
55
- block.call
56
- eval('', block.binding)
57
- end
58
-
59
- # Given a browser request Accept-Language header like
60
- # "fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4,ru;q=0.2", this function
61
- # will return "fr" since that's the first code with a matching
62
- # locale in web/locales
63
- def locale
64
- @locale ||= begin
65
- locale = 'en'.freeze
66
- languages = request.env['HTTP_ACCEPT_LANGUAGE'.freeze] || 'en'.freeze
67
- languages.downcase.split(','.freeze).each do |lang|
68
- next if lang == '*'.freeze
69
- lang = lang.split(';'.freeze)[0]
70
- break locale = lang if find_locale_files(lang).any?
71
- end
72
- locale
73
- end
74
- end
75
-
76
- def get_locale
77
- strings(locale)
78
- end
79
-
80
- def t(msg, options={})
81
- string = get_locale[msg] || msg
82
- if options.empty?
83
- string
84
- else
85
- string % options
86
- end
87
- end
88
-
89
- def workers
90
- @workers ||= Sidekiq::Workers.new
91
- end
92
-
93
- def processes
94
- @processes ||= Sidekiq::ProcessSet.new
95
- end
96
-
97
- def stats
98
- @stats ||= Sidekiq::Stats.new
99
- end
100
-
101
- def retries_with_score(score)
102
- Sidekiq.redis do |conn|
103
- conn.zrangebyscore('retry', score, score)
104
- end.map { |msg| Sidekiq.load_json(msg) }
105
- end
106
-
107
- def location
108
- Sidekiq.redis { |conn| conn.client.location }
109
- end
110
-
111
- def redis_connection
112
- Sidekiq.redis { |conn| conn.client.id }
113
- end
114
-
115
- def namespace
116
- @@ns ||= Sidekiq.redis { |conn| conn.respond_to?(:namespace) ? conn.namespace : nil }
117
- end
118
-
119
- def redis_info
120
- Sidekiq.redis do |conn|
121
- # admin commands can't go through redis-namespace starting
122
- # in redis-namespace 2.0
123
- if conn.respond_to?(:namespace)
124
- conn.redis.info
125
- else
126
- conn.info
127
- end
128
- end
129
- end
130
-
131
- def root_path
132
- "#{env['SCRIPT_NAME']}/"
133
- end
134
-
135
- def current_path
136
- @current_path ||= request.path_info.gsub(/^\//,'')
137
- end
138
-
139
- def current_status
140
- workers.size == 0 ? 'idle' : 'active'
141
- end
142
-
143
- def relative_time(time)
144
- %{<time datetime="#{time.getutc.iso8601}">#{time}</time>}
145
- end
146
-
147
- def job_params(job, score)
148
- "#{score}-#{job['jid']}"
149
- end
150
-
151
- def parse_params(params)
152
- score, jid = params.split("-")
153
- [score.to_f, jid]
154
- end
155
-
156
- SAFE_QPARAMS = %w(page poll)
157
-
158
- # Merge options with current params, filter safe params, and stringify to query string
159
- def qparams(options)
160
- options = options.stringify_keys
161
- params.merge(options).map do |key, value|
162
- SAFE_QPARAMS.include?(key) ? "#{key}=#{value}" : next
163
- end.join("&")
164
- end
165
-
166
- def truncate(text, truncate_after_chars = 2000)
167
- truncate_after_chars && text.size > truncate_after_chars ? "#{text[0..truncate_after_chars]}..." : text
168
- end
169
-
170
- def display_args(args, truncate_after_chars = 2000)
171
- args.map do |arg|
172
- a = arg.inspect
173
- h(truncate(a))
174
- end.join(", ")
175
- end
176
-
177
- RETRY_JOB_KEYS = Set.new(%w(
178
- queue class args retry_count retried_at failed_at
179
- jid error_message error_class backtrace
180
- error_backtrace enqueued_at retry wrapped
181
- ))
182
-
183
- def retry_extra_items(retry_job)
184
- @retry_extra_items ||= {}.tap do |extra|
185
- retry_job.item.each do |key, value|
186
- extra[key] = value unless RETRY_JOB_KEYS.include?(key)
187
- end
188
- end
189
- end
190
-
191
- def number_with_delimiter(number)
192
- begin
193
- Float(number)
194
- rescue ArgumentError, TypeError
195
- return number
196
- end
197
-
198
- options = {delimiter: ',', separator: '.'}
199
- parts = number.to_s.to_str.split('.')
200
- parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{options[:delimiter]}")
201
- parts.join(options[:separator])
202
- end
203
-
204
- def h(text)
205
- ::Rack::Utils.escape_html(text)
206
- rescue ArgumentError => e
207
- raise unless e.message.eql?('invalid byte sequence in UTF-8')
208
- text.encode!('UTF-16', 'UTF-8', invalid: :replace, replace: '').encode!('UTF-8', 'UTF-16')
209
- retry
210
- end
211
-
212
- # Any paginated list that performs an action needs to redirect
213
- # back to the proper page after performing that action.
214
- def redirect_with_query(url)
215
- r = request.referer
216
- if r && r =~ /\?/
217
- ref = URI(r)
218
- redirect("#{url}?#{ref.query}")
219
- else
220
- redirect url
221
- end
222
- end
223
-
224
- def environment_title_prefix
225
- environment = Sidekiq.options[:environment] || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
226
-
227
- "[#{environment.upcase}] " unless environment == "production"
228
- end
229
-
230
- def product_version
231
- "Sidekiq v#{Sidekiq::VERSION}"
232
- end
233
- end
234
- end
@@ -1,89 +0,0 @@
1
- require 'sidekiq/client'
2
- require 'sidekiq/core_ext'
3
-
4
- module Sidekiq
5
-
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
- attr_accessor :jid
25
-
26
- def self.included(base)
27
- base.extend(ClassMethods)
28
- base.class_attribute :sidekiq_options_hash
29
- base.class_attribute :sidekiq_retry_in_block
30
- base.class_attribute :sidekiq_retries_exhausted_block
31
- end
32
-
33
- def logger
34
- Sidekiq.logger
35
- end
36
-
37
- module ClassMethods
38
-
39
- def perform_async(*args)
40
- client_push('class' => self, 'args' => args)
41
- end
42
-
43
- def perform_in(interval, *args)
44
- int = interval.to_f
45
- now = Time.now
46
- ts = (int < 1_000_000_000 ? (now + interval).to_f : int)
47
-
48
- item = { 'class' => self, 'args' => args, 'at' => ts }
49
-
50
- # Optimization to enqueue something now that is scheduled to go out now or in the past
51
- item.delete('at'.freeze) if ts <= now.to_f
52
-
53
- client_push(item)
54
- end
55
- alias_method :perform_at, :perform_in
56
-
57
- ##
58
- # Allows customization for this type of Worker.
59
- # Legal options:
60
- #
61
- # :queue - use a named queue for this Worker, default 'default'
62
- # :retry - enable the RetryJobs middleware for this Worker, default *true*
63
- # :backtrace - whether to save any error backtrace in the retry payload to display in web UI,
64
- # can be true, false or an integer number of lines to save, default *false*
65
- # :pool - use the given Redis connection pool to push this type of job to a given shard.
66
- def sidekiq_options(opts={})
67
- self.sidekiq_options_hash = get_sidekiq_options.merge(opts.stringify_keys)
68
- end
69
-
70
- def sidekiq_retry_in(&block)
71
- self.sidekiq_retry_in_block = block
72
- end
73
-
74
- def sidekiq_retries_exhausted(&block)
75
- self.sidekiq_retries_exhausted_block = block
76
- end
77
-
78
- def get_sidekiq_options # :nodoc:
79
- self.sidekiq_options_hash ||= Sidekiq.default_worker_options
80
- end
81
-
82
- def client_push(item) # :nodoc:
83
- pool = Thread.current[:sidekiq_via_pool] || get_sidekiq_options['pool'] || Sidekiq.redis_pool
84
- Sidekiq::Client.new(pool).push(item.stringify_keys)
85
- end
86
-
87
- end
88
- end
89
- end
data/test/config.yml DELETED
@@ -1,9 +0,0 @@
1
- ---
2
- :verbose: false
3
- :require: ./test/fake_env.rb
4
- :pidfile: /tmp/sidekiq-config-test.pid
5
- :logfile: /tmp/sidekiq.log
6
- :concurrency: 50
7
- :queues:
8
- - [<%="very_"%>often, 2]
9
- - [seldom, 1]
@@ -1,11 +0,0 @@
1
- ---
2
- :pidfile: /tmp/sidekiq-config-test.pid
3
- :concurrency: 50
4
- staging:
5
- :verbose: false
6
- :require: ./test/fake_env.rb
7
- :logfile: /tmp/sidekiq.log
8
- :concurrency: 5
9
- :queues:
10
- - [<%="very_"%>often, 2]
11
- - [seldom, 1]
data/test/fake_env.rb DELETED
File without changes
data/test/fixtures/en.yml DELETED
@@ -1,2 +0,0 @@
1
- en:
2
- translated_text: 'Changed text from add locals'
data/test/helper.rb DELETED
@@ -1,39 +0,0 @@
1
- $TESTING = true
2
- require 'coveralls'
3
- Coveralls.wear! do
4
- add_filter "/test/"
5
- add_filter "/myapp/"
6
- end
7
-
8
- ENV['RACK_ENV'] = ENV['RAILS_ENV'] = 'test'
9
- if ENV.has_key?("SIMPLECOV")
10
- require 'simplecov'
11
- SimpleCov.start do
12
- add_filter "/test/"
13
- add_filter "/myapp/"
14
- end
15
- end
16
-
17
- begin
18
- require 'pry-byebug'
19
- rescue LoadError
20
- end
21
-
22
- require 'minitest/autorun'
23
- require 'minitest/pride'
24
-
25
- require 'celluloid/test'
26
- Celluloid.boot
27
- require 'sidekiq'
28
- require 'sidekiq/util'
29
- Sidekiq.logger.level = Logger::ERROR
30
-
31
- Sidekiq::Test = Minitest::Test
32
-
33
- require 'sidekiq/redis_connection'
34
- REDIS_URL = ENV['REDIS_URL'] || 'redis://localhost/15'
35
- REDIS = Sidekiq::RedisConnection.create(:url => REDIS_URL, :namespace => 'testy')
36
-
37
- Sidekiq.configure_client do |config|
38
- config.redis = { :url => REDIS_URL, :namespace => 'testy' }
39
- end