lepus 0.0.1.beta2 → 0.1.0
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.
- checksums.yaml +4 -4
- data/.github/workflows/linter.yml +21 -0
- data/.github/workflows/specs.yml +93 -13
- data/.gitignore +2 -0
- data/.rubocop.yml +10 -0
- data/.tool-versions +1 -1
- data/Gemfile +7 -0
- data/Gemfile.lock +36 -9
- data/Makefile +19 -0
- data/README.md +562 -7
- data/bin/setup +5 -2
- data/config.ru +14 -0
- data/docker-compose.yml +5 -3
- data/docs/README.md +80 -0
- data/docs/cli.md +108 -0
- data/docs/configuration.md +171 -0
- data/docs/consumers.md +168 -0
- data/docs/getting-started.md +136 -0
- data/docs/images/lepus-web.png +0 -0
- data/docs/middleware.md +240 -0
- data/docs/producers.md +173 -0
- data/docs/prometheus.md +112 -0
- data/docs/rails.md +161 -0
- data/docs/supervisor.md +112 -0
- data/docs/testing.md +141 -0
- data/docs/web.md +85 -0
- data/examples/grafana-dashboard.json +450 -0
- data/gemfiles/Gemfile.rails-5.2 +7 -0
- data/gemfiles/{rails52.gemfile.lock → Gemfile.rails-5.2.lock} +102 -69
- data/gemfiles/Gemfile.rails-6.1 +7 -0
- data/gemfiles/{rails61.gemfile.lock → Gemfile.rails-6.1.lock} +113 -79
- data/gemfiles/{rails52.gemfile → Gemfile.rails-7.2} +1 -1
- data/gemfiles/Gemfile.rails-7.2.lock +321 -0
- data/gemfiles/{rails61.gemfile → Gemfile.rails-8.0} +1 -1
- data/gemfiles/Gemfile.rails-8.0.lock +322 -0
- data/lepus.gemspec +7 -1
- data/lib/lepus/cli.rb +35 -4
- data/lib/lepus/configuration.rb +107 -0
- data/lib/lepus/connection_pool.rb +135 -0
- data/lib/lepus/consumer.rb +59 -41
- data/lib/lepus/consumers/config.rb +183 -0
- data/lib/lepus/consumers/handler.rb +56 -0
- data/lib/lepus/consumers/middleware_chain.rb +22 -0
- data/lib/lepus/consumers/middlewares/exception_logger.rb +27 -0
- data/lib/lepus/consumers/middlewares/honeybadger.rb +33 -0
- data/lib/lepus/consumers/middlewares/json.rb +37 -0
- data/lib/lepus/consumers/middlewares/max_retry.rb +83 -0
- data/lib/lepus/consumers/middlewares/unique.rb +65 -0
- data/lib/lepus/consumers/stats.rb +70 -0
- data/lib/lepus/consumers/stats_registry.rb +29 -0
- data/lib/lepus/consumers/worker.rb +141 -0
- data/lib/lepus/consumers/worker_factory.rb +124 -0
- data/lib/lepus/consumers.rb +6 -0
- data/lib/lepus/message/delivery_info.rb +72 -0
- data/lib/lepus/message/metadata.rb +99 -0
- data/lib/lepus/message.rb +88 -5
- data/lib/lepus/middleware_chain.rb +83 -0
- data/lib/lepus/primitive/hash.rb +29 -0
- data/lib/lepus/process.rb +24 -24
- data/lib/lepus/process_registry/backend.rb +49 -0
- data/lib/lepus/process_registry/file_backend.rb +108 -0
- data/lib/lepus/process_registry/message_builder.rb +72 -0
- data/lib/lepus/process_registry/rabbitmq_backend.rb +153 -0
- data/lib/lepus/process_registry.rb +56 -23
- data/lib/lepus/processes/base.rb +0 -5
- data/lib/lepus/processes/callbacks.rb +3 -0
- data/lib/lepus/processes/interruptible.rb +4 -8
- data/lib/lepus/processes/procline.rb +1 -1
- data/lib/lepus/processes/registrable.rb +1 -1
- data/lib/lepus/processes/runnable.rb +1 -1
- data/lib/lepus/processes.rb +15 -0
- data/lib/lepus/producer.rb +141 -30
- data/lib/lepus/producers/config.rb +46 -0
- data/lib/lepus/producers/definition.rb +48 -0
- data/lib/lepus/producers/hooks.rb +170 -0
- data/lib/lepus/producers/middleware_chain.rb +22 -0
- data/lib/lepus/producers/middlewares/correlation_id.rb +37 -0
- data/lib/lepus/producers/middlewares/header.rb +47 -0
- data/lib/lepus/producers/middlewares/instrumentation.rb +30 -0
- data/lib/lepus/producers/middlewares/json.rb +47 -0
- data/lib/lepus/producers/middlewares/unique.rb +67 -0
- data/lib/lepus/producers.rb +7 -0
- data/lib/lepus/prometheus/collector.rb +149 -0
- data/lib/lepus/prometheus/instrumentation.rb +168 -0
- data/lib/lepus/prometheus.rb +48 -0
- data/lib/lepus/publisher.rb +67 -0
- data/lib/lepus/supervisor/children_pipes.rb +25 -0
- data/lib/lepus/supervisor/lifecycle_hooks.rb +50 -0
- data/lib/lepus/supervisor/pidfiled.rb +1 -1
- data/lib/lepus/supervisor/registry_cleaner.rb +22 -0
- data/lib/lepus/supervisor.rb +129 -25
- data/lib/lepus/testing/exchange.rb +95 -0
- data/lib/lepus/testing/message_builder.rb +177 -0
- data/lib/lepus/testing/rspec_matchers.rb +258 -0
- data/lib/lepus/testing.rb +210 -0
- data/lib/lepus/unique.rb +18 -0
- data/lib/lepus/version.rb +1 -1
- data/lib/lepus/web/aggregator.rb +154 -0
- data/lib/lepus/web/api.rb +132 -0
- data/lib/lepus/web/app.rb +37 -0
- data/lib/lepus/web/management_api.rb +192 -0
- data/lib/lepus/web/respond_with.rb +28 -0
- data/lib/lepus/web.rb +238 -0
- data/lib/lepus.rb +39 -28
- data/test_offline.html +189 -0
- data/web/assets/css/styles.css +635 -0
- data/web/assets/js/app.js +6 -0
- data/web/assets/js/bootstrap.js +20 -0
- data/web/assets/js/controllers/connection_controller.js +44 -0
- data/web/assets/js/controllers/dashboard_controller.js +499 -0
- data/web/assets/js/controllers/queue_controller.js +17 -0
- data/web/assets/js/controllers/theme_controller.js +31 -0
- data/web/assets/js/offline-manager.js +233 -0
- data/web/assets/js/service-worker-manager.js +65 -0
- data/web/index.html +159 -0
- data/web/sw.js +144 -0
- metadata +177 -18
- data/lib/lepus/consumer_config.rb +0 -149
- data/lib/lepus/consumer_wrapper.rb +0 -46
- data/lib/lepus/lifecycle_hooks.rb +0 -49
- data/lib/lepus/middlewares/honeybadger.rb +0 -23
- data/lib/lepus/middlewares/json.rb +0 -35
- data/lib/lepus/middlewares/max_retry.rb +0 -57
- data/lib/lepus/processes/consumer.rb +0 -113
- data/lib/lepus/supervisor/config.rb +0 -45
metadata
CHANGED
|
@@ -1,15 +1,29 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lepus
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Marcos G. Zimmermann
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exec
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-04-27 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: base64
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: 0.0.0
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: 0.0.0
|
|
13
27
|
- !ruby/object:Gem::Dependency
|
|
14
28
|
name: bunny
|
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -108,6 +122,34 @@ dependencies:
|
|
|
108
122
|
- - ">="
|
|
109
123
|
- !ruby/object:Gem::Version
|
|
110
124
|
version: '0'
|
|
125
|
+
- !ruby/object:Gem::Dependency
|
|
126
|
+
name: rack
|
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
|
128
|
+
requirements:
|
|
129
|
+
- - ">="
|
|
130
|
+
- !ruby/object:Gem::Version
|
|
131
|
+
version: '2.2'
|
|
132
|
+
type: :development
|
|
133
|
+
prerelease: false
|
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
135
|
+
requirements:
|
|
136
|
+
- - ">="
|
|
137
|
+
- !ruby/object:Gem::Version
|
|
138
|
+
version: '2.2'
|
|
139
|
+
- !ruby/object:Gem::Dependency
|
|
140
|
+
name: rack-test
|
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
|
142
|
+
requirements:
|
|
143
|
+
- - ">="
|
|
144
|
+
- !ruby/object:Gem::Version
|
|
145
|
+
version: '0'
|
|
146
|
+
type: :development
|
|
147
|
+
prerelease: false
|
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
149
|
+
requirements:
|
|
150
|
+
- - ">="
|
|
151
|
+
- !ruby/object:Gem::Version
|
|
152
|
+
version: '0'
|
|
111
153
|
- !ruby/object:Gem::Dependency
|
|
112
154
|
name: rspec
|
|
113
155
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -192,7 +234,49 @@ dependencies:
|
|
|
192
234
|
- - ">="
|
|
193
235
|
- !ruby/object:Gem::Version
|
|
194
236
|
version: '0'
|
|
195
|
-
|
|
237
|
+
- !ruby/object:Gem::Dependency
|
|
238
|
+
name: simplecov
|
|
239
|
+
requirement: !ruby/object:Gem::Requirement
|
|
240
|
+
requirements:
|
|
241
|
+
- - ">="
|
|
242
|
+
- !ruby/object:Gem::Version
|
|
243
|
+
version: '0'
|
|
244
|
+
type: :development
|
|
245
|
+
prerelease: false
|
|
246
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
247
|
+
requirements:
|
|
248
|
+
- - ">="
|
|
249
|
+
- !ruby/object:Gem::Version
|
|
250
|
+
version: '0'
|
|
251
|
+
- !ruby/object:Gem::Dependency
|
|
252
|
+
name: de-dupe
|
|
253
|
+
requirement: !ruby/object:Gem::Requirement
|
|
254
|
+
requirements:
|
|
255
|
+
- - ">="
|
|
256
|
+
- !ruby/object:Gem::Version
|
|
257
|
+
version: '0'
|
|
258
|
+
type: :development
|
|
259
|
+
prerelease: false
|
|
260
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
261
|
+
requirements:
|
|
262
|
+
- - ">="
|
|
263
|
+
- !ruby/object:Gem::Version
|
|
264
|
+
version: '0'
|
|
265
|
+
- !ruby/object:Gem::Dependency
|
|
266
|
+
name: prometheus_exporter
|
|
267
|
+
requirement: !ruby/object:Gem::Requirement
|
|
268
|
+
requirements:
|
|
269
|
+
- - ">="
|
|
270
|
+
- !ruby/object:Gem::Version
|
|
271
|
+
version: '0'
|
|
272
|
+
type: :development
|
|
273
|
+
prerelease: false
|
|
274
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
275
|
+
requirements:
|
|
276
|
+
- - ">="
|
|
277
|
+
- !ruby/object:Gem::Version
|
|
278
|
+
version: '0'
|
|
279
|
+
description: 'RabbitMQ consumers/producer for ruby applications
|
|
196
280
|
|
|
197
281
|
'
|
|
198
282
|
email:
|
|
@@ -202,6 +286,7 @@ executables:
|
|
|
202
286
|
extensions: []
|
|
203
287
|
extra_rdoc_files: []
|
|
204
288
|
files:
|
|
289
|
+
- ".github/workflows/linter.yml"
|
|
205
290
|
- ".github/workflows/specs.yml"
|
|
206
291
|
- ".gitignore"
|
|
207
292
|
- ".rspec"
|
|
@@ -211,55 +296,129 @@ files:
|
|
|
211
296
|
- Gemfile
|
|
212
297
|
- Gemfile.lock
|
|
213
298
|
- LICENSE.txt
|
|
299
|
+
- Makefile
|
|
214
300
|
- README.md
|
|
215
301
|
- Rakefile
|
|
216
302
|
- bin/console
|
|
217
303
|
- bin/setup
|
|
304
|
+
- config.ru
|
|
218
305
|
- docker-compose.yml
|
|
306
|
+
- docs/README.md
|
|
307
|
+
- docs/cli.md
|
|
308
|
+
- docs/configuration.md
|
|
309
|
+
- docs/consumers.md
|
|
310
|
+
- docs/getting-started.md
|
|
311
|
+
- docs/images/lepus-web.png
|
|
312
|
+
- docs/middleware.md
|
|
313
|
+
- docs/producers.md
|
|
314
|
+
- docs/prometheus.md
|
|
315
|
+
- docs/rails.md
|
|
316
|
+
- docs/supervisor.md
|
|
317
|
+
- docs/testing.md
|
|
318
|
+
- docs/web.md
|
|
319
|
+
- examples/grafana-dashboard.json
|
|
219
320
|
- exec/lepus
|
|
220
|
-
- gemfiles/
|
|
221
|
-
- gemfiles/
|
|
222
|
-
- gemfiles/
|
|
223
|
-
- gemfiles/
|
|
321
|
+
- gemfiles/Gemfile.rails-5.2
|
|
322
|
+
- gemfiles/Gemfile.rails-5.2.lock
|
|
323
|
+
- gemfiles/Gemfile.rails-6.1
|
|
324
|
+
- gemfiles/Gemfile.rails-6.1.lock
|
|
325
|
+
- gemfiles/Gemfile.rails-7.2
|
|
326
|
+
- gemfiles/Gemfile.rails-7.2.lock
|
|
327
|
+
- gemfiles/Gemfile.rails-8.0
|
|
328
|
+
- gemfiles/Gemfile.rails-8.0.lock
|
|
224
329
|
- lepus.gemspec
|
|
225
330
|
- lib/lepus.rb
|
|
226
331
|
- lib/lepus/app_executor.rb
|
|
227
332
|
- lib/lepus/cli.rb
|
|
228
333
|
- lib/lepus/configuration.rb
|
|
334
|
+
- lib/lepus/connection_pool.rb
|
|
229
335
|
- lib/lepus/consumer.rb
|
|
230
|
-
- lib/lepus/
|
|
231
|
-
- lib/lepus/
|
|
232
|
-
- lib/lepus/
|
|
336
|
+
- lib/lepus/consumers.rb
|
|
337
|
+
- lib/lepus/consumers/config.rb
|
|
338
|
+
- lib/lepus/consumers/handler.rb
|
|
339
|
+
- lib/lepus/consumers/middleware_chain.rb
|
|
340
|
+
- lib/lepus/consumers/middlewares/exception_logger.rb
|
|
341
|
+
- lib/lepus/consumers/middlewares/honeybadger.rb
|
|
342
|
+
- lib/lepus/consumers/middlewares/json.rb
|
|
343
|
+
- lib/lepus/consumers/middlewares/max_retry.rb
|
|
344
|
+
- lib/lepus/consumers/middlewares/unique.rb
|
|
345
|
+
- lib/lepus/consumers/stats.rb
|
|
346
|
+
- lib/lepus/consumers/stats_registry.rb
|
|
347
|
+
- lib/lepus/consumers/worker.rb
|
|
348
|
+
- lib/lepus/consumers/worker_factory.rb
|
|
233
349
|
- lib/lepus/message.rb
|
|
350
|
+
- lib/lepus/message/delivery_info.rb
|
|
351
|
+
- lib/lepus/message/metadata.rb
|
|
234
352
|
- lib/lepus/middleware.rb
|
|
235
|
-
- lib/lepus/
|
|
236
|
-
- lib/lepus/
|
|
237
|
-
- lib/lepus/middlewares/max_retry.rb
|
|
353
|
+
- lib/lepus/middleware_chain.rb
|
|
354
|
+
- lib/lepus/primitive/hash.rb
|
|
238
355
|
- lib/lepus/primitive/string.rb
|
|
239
356
|
- lib/lepus/process.rb
|
|
240
357
|
- lib/lepus/process_registry.rb
|
|
358
|
+
- lib/lepus/process_registry/backend.rb
|
|
359
|
+
- lib/lepus/process_registry/file_backend.rb
|
|
360
|
+
- lib/lepus/process_registry/message_builder.rb
|
|
361
|
+
- lib/lepus/process_registry/rabbitmq_backend.rb
|
|
241
362
|
- lib/lepus/processes.rb
|
|
242
363
|
- lib/lepus/processes/base.rb
|
|
243
364
|
- lib/lepus/processes/callbacks.rb
|
|
244
|
-
- lib/lepus/processes/consumer.rb
|
|
245
365
|
- lib/lepus/processes/interruptible.rb
|
|
246
366
|
- lib/lepus/processes/procline.rb
|
|
247
367
|
- lib/lepus/processes/registrable.rb
|
|
248
368
|
- lib/lepus/processes/runnable.rb
|
|
249
369
|
- lib/lepus/processes/supervised.rb
|
|
250
370
|
- lib/lepus/producer.rb
|
|
371
|
+
- lib/lepus/producers.rb
|
|
372
|
+
- lib/lepus/producers/config.rb
|
|
373
|
+
- lib/lepus/producers/definition.rb
|
|
374
|
+
- lib/lepus/producers/hooks.rb
|
|
375
|
+
- lib/lepus/producers/middleware_chain.rb
|
|
376
|
+
- lib/lepus/producers/middlewares/correlation_id.rb
|
|
377
|
+
- lib/lepus/producers/middlewares/header.rb
|
|
378
|
+
- lib/lepus/producers/middlewares/instrumentation.rb
|
|
379
|
+
- lib/lepus/producers/middlewares/json.rb
|
|
380
|
+
- lib/lepus/producers/middlewares/unique.rb
|
|
381
|
+
- lib/lepus/prometheus.rb
|
|
382
|
+
- lib/lepus/prometheus/collector.rb
|
|
383
|
+
- lib/lepus/prometheus/instrumentation.rb
|
|
384
|
+
- lib/lepus/publisher.rb
|
|
251
385
|
- lib/lepus/rails.rb
|
|
252
386
|
- lib/lepus/rails/log_subscriber.rb
|
|
253
387
|
- lib/lepus/rails/railtie.rb
|
|
254
388
|
- lib/lepus/supervisor.rb
|
|
255
|
-
- lib/lepus/supervisor/
|
|
389
|
+
- lib/lepus/supervisor/children_pipes.rb
|
|
390
|
+
- lib/lepus/supervisor/lifecycle_hooks.rb
|
|
256
391
|
- lib/lepus/supervisor/maintenance.rb
|
|
257
392
|
- lib/lepus/supervisor/pidfile.rb
|
|
258
393
|
- lib/lepus/supervisor/pidfiled.rb
|
|
394
|
+
- lib/lepus/supervisor/registry_cleaner.rb
|
|
259
395
|
- lib/lepus/supervisor/signals.rb
|
|
396
|
+
- lib/lepus/testing.rb
|
|
397
|
+
- lib/lepus/testing/exchange.rb
|
|
398
|
+
- lib/lepus/testing/message_builder.rb
|
|
399
|
+
- lib/lepus/testing/rspec_matchers.rb
|
|
260
400
|
- lib/lepus/timer.rb
|
|
401
|
+
- lib/lepus/unique.rb
|
|
261
402
|
- lib/lepus/version.rb
|
|
403
|
+
- lib/lepus/web.rb
|
|
404
|
+
- lib/lepus/web/aggregator.rb
|
|
405
|
+
- lib/lepus/web/api.rb
|
|
406
|
+
- lib/lepus/web/app.rb
|
|
407
|
+
- lib/lepus/web/management_api.rb
|
|
408
|
+
- lib/lepus/web/respond_with.rb
|
|
262
409
|
- lib/puma/plugin/lepus.rb
|
|
410
|
+
- test_offline.html
|
|
411
|
+
- web/assets/css/styles.css
|
|
412
|
+
- web/assets/js/app.js
|
|
413
|
+
- web/assets/js/bootstrap.js
|
|
414
|
+
- web/assets/js/controllers/connection_controller.js
|
|
415
|
+
- web/assets/js/controllers/dashboard_controller.js
|
|
416
|
+
- web/assets/js/controllers/queue_controller.js
|
|
417
|
+
- web/assets/js/controllers/theme_controller.js
|
|
418
|
+
- web/assets/js/offline-manager.js
|
|
419
|
+
- web/assets/js/service-worker-manager.js
|
|
420
|
+
- web/index.html
|
|
421
|
+
- web/sw.js
|
|
263
422
|
homepage: https://github.com/marcosgz/lepus
|
|
264
423
|
licenses:
|
|
265
424
|
- MIT
|
|
@@ -279,11 +438,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
279
438
|
version: 2.7.0
|
|
280
439
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
281
440
|
requirements:
|
|
282
|
-
- - "
|
|
441
|
+
- - ">="
|
|
283
442
|
- !ruby/object:Gem::Version
|
|
284
|
-
version:
|
|
443
|
+
version: '0'
|
|
285
444
|
requirements: []
|
|
286
|
-
rubygems_version: 3.
|
|
445
|
+
rubygems_version: 3.4.10
|
|
287
446
|
signing_key:
|
|
288
447
|
specification_version: 4
|
|
289
448
|
summary: RabbitMQ consumers/producer for ruby applications
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
require "bunny"
|
|
2
|
-
|
|
3
|
-
module Lepus
|
|
4
|
-
# Parse the list of options for the consumer.
|
|
5
|
-
class ConsumerConfig
|
|
6
|
-
DEFAULT_EXCHANGE_OPTIONS = {
|
|
7
|
-
name: nil,
|
|
8
|
-
type: :topic, # The type of the exchange (:direct, :fanout, :topic or :headers).
|
|
9
|
-
durable: true
|
|
10
|
-
}.freeze
|
|
11
|
-
|
|
12
|
-
DEFAULT_QUEUE_OPTIONS = {
|
|
13
|
-
name: nil,
|
|
14
|
-
durable: true
|
|
15
|
-
}.freeze
|
|
16
|
-
|
|
17
|
-
DEFAULT_RETRY_QUEUE_OPTIONS = {
|
|
18
|
-
name: nil,
|
|
19
|
-
durable: true,
|
|
20
|
-
delay: 5000,
|
|
21
|
-
arguments: {}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
DEFAULT_ERROR_QUEUE_OPTIONS = DEFAULT_QUEUE_OPTIONS
|
|
25
|
-
|
|
26
|
-
attr_reader :options
|
|
27
|
-
|
|
28
|
-
def initialize(options = {})
|
|
29
|
-
opts = HashUtil.deep_symbolize_keys(options)
|
|
30
|
-
|
|
31
|
-
@exchange_opts = DEFAULT_EXCHANGE_OPTIONS.merge(
|
|
32
|
-
declaration_config(opts.delete(:exchange))
|
|
33
|
-
)
|
|
34
|
-
@queue_opts = DEFAULT_QUEUE_OPTIONS.merge(
|
|
35
|
-
declaration_config(opts.delete(:queue))
|
|
36
|
-
)
|
|
37
|
-
if (value = opts.delete(:retry_queue))
|
|
38
|
-
@retry_queue_opts = DEFAULT_RETRY_QUEUE_OPTIONS.merge(
|
|
39
|
-
declaration_config(value)
|
|
40
|
-
)
|
|
41
|
-
end
|
|
42
|
-
if (value = opts.delete(:error_queue))
|
|
43
|
-
@error_queue_opts = DEFAULT_ERROR_QUEUE_OPTIONS.merge(
|
|
44
|
-
declaration_config(value)
|
|
45
|
-
)
|
|
46
|
-
end
|
|
47
|
-
@bind_opts = opts.delete(:bind) || {}
|
|
48
|
-
if (routing_key = opts.delete(:routing_key))
|
|
49
|
-
@bind_opts[:routing_key] ||= routing_key
|
|
50
|
-
end
|
|
51
|
-
@options = opts
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def channel_args
|
|
55
|
-
@channel_opts.values_at(
|
|
56
|
-
:consumer_pool_size,
|
|
57
|
-
:consumer_pool_abort_on_exception,
|
|
58
|
-
:consumer_pool_shutdown_timeout
|
|
59
|
-
)
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def exchange_args
|
|
63
|
-
[exchange_name, @exchange_opts.reject { |k, v| k == :name }]
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def consumer_queue_args
|
|
67
|
-
opts = @queue_opts.reject { |k, v| k == :name }
|
|
68
|
-
return [queue_name, opts] unless retry_queue_args
|
|
69
|
-
|
|
70
|
-
opts[:arguments] ||= {}
|
|
71
|
-
opts[:arguments]["x-dead-letter-exchange"] = ""
|
|
72
|
-
opts[:arguments]["x-dead-letter-routing-key"] = retry_queue_name
|
|
73
|
-
|
|
74
|
-
[queue_name, opts]
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def retry_queue_args
|
|
78
|
-
return unless @retry_queue_opts
|
|
79
|
-
|
|
80
|
-
delay = @retry_queue_opts[:delay]
|
|
81
|
-
args = (@retry_queue_opts[:arguments] || {}).merge(
|
|
82
|
-
"x-dead-letter-exchange" => "",
|
|
83
|
-
"x-dead-letter-routing-key" => queue_name,
|
|
84
|
-
"x-message-ttl" => delay
|
|
85
|
-
)
|
|
86
|
-
extra_keys = %i[name delay]
|
|
87
|
-
opts = @retry_queue_opts.reject { |k, v| extra_keys.include?(k) }
|
|
88
|
-
[retry_queue_name, opts.merge(arguments: args)]
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
def error_queue_args
|
|
92
|
-
return unless @error_queue_opts
|
|
93
|
-
|
|
94
|
-
name = @error_queue_opts[:name]
|
|
95
|
-
name ||= "#{queue_name}.error"
|
|
96
|
-
[name, @error_queue_opts.reject { |k, v| k == :name }]
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
def binds_args
|
|
100
|
-
arguments = @bind_opts.fetch(:arguments, {}).transform_keys(&:to_s)
|
|
101
|
-
opts = {}
|
|
102
|
-
opts[:arguments] = arguments unless arguments.empty?
|
|
103
|
-
if (routing_keys = @bind_opts[:routing_key]).is_a?(Array)
|
|
104
|
-
routing_keys.map { |key| opts.merge(routing_key: key) }
|
|
105
|
-
elsif (routing_key = @bind_opts[:routing_key])
|
|
106
|
-
[opts.merge(routing_key: routing_key)]
|
|
107
|
-
else
|
|
108
|
-
[opts]
|
|
109
|
-
end
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
protected
|
|
113
|
-
|
|
114
|
-
def exchange_name
|
|
115
|
-
@exchange_opts[:name] || raise(InvalidConsumerConfigError, "Exchange name is required")
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
def queue_name
|
|
119
|
-
@queue_opts[:name] || raise(InvalidConsumerConfigError, "Queue name is required")
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
def retry_queue_name
|
|
123
|
-
name = @retry_queue_opts[:name]
|
|
124
|
-
name ||= "#{queue_name}.retry"
|
|
125
|
-
name
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
# Normalizes a declaration config (for exchanges and queues) into a configuration Hash.
|
|
129
|
-
#
|
|
130
|
-
# If the given `value` is a String, convert it to a Hash with the key `:name` and the value.
|
|
131
|
-
# If the given `value` is a Hash, leave it as is.
|
|
132
|
-
def declaration_config(value)
|
|
133
|
-
case value
|
|
134
|
-
when Hash then value
|
|
135
|
-
when String then {name: value}
|
|
136
|
-
when NilClass then {}
|
|
137
|
-
when TrueClass then {}
|
|
138
|
-
end
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
class HashUtil
|
|
142
|
-
def self.deep_symbolize_keys(hash)
|
|
143
|
-
hash.each_with_object({}) do |(k, v), memo|
|
|
144
|
-
memo[k.to_sym] = v.is_a?(Hash) ? deep_symbolize_keys(v) : v
|
|
145
|
-
end
|
|
146
|
-
end
|
|
147
|
-
end
|
|
148
|
-
end
|
|
149
|
-
end
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
require "bunny"
|
|
2
|
-
|
|
3
|
-
module Lepus
|
|
4
|
-
# Wraps the user-defined consumer to provide the expected interface to Bunny.
|
|
5
|
-
class ConsumerWrapper < Bunny::Consumer
|
|
6
|
-
# @param [Lepus::Consumer] consumer The user-defined consumer implementation derived from {Lepus::Consumer}.
|
|
7
|
-
# @param [Bunny::Channel] channel The channel used for the consumer.
|
|
8
|
-
# @param [Bunny::Queue] queue The queue the consumer is subscribed to.
|
|
9
|
-
# @param [String] consumer_tag A string identifying the consumer instance.
|
|
10
|
-
# @param [Hash] arguments Arguments that are passed on to +Bunny::Consumer.new+.
|
|
11
|
-
def initialize(consumer, channel, queue, consumer_tag, arguments = {})
|
|
12
|
-
@consumer = consumer
|
|
13
|
-
super(channel, queue, consumer_tag, false, false, arguments)
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
# Called when a message is received from the subscribed queue.
|
|
17
|
-
#
|
|
18
|
-
# @param [Bunny::DeliveryInfo] delivery_info The delivery info of the received message.
|
|
19
|
-
# @param [Bunny::MessageProperties] metadata The metadata of the received message.
|
|
20
|
-
# @param [String] payload The payload of the received message.
|
|
21
|
-
def process_delivery(delivery_info, metadata, payload)
|
|
22
|
-
consumer
|
|
23
|
-
.process_delivery(delivery_info, metadata, payload)
|
|
24
|
-
.tap { |result| process_result(result, delivery_info.delivery_tag) }
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
private
|
|
28
|
-
|
|
29
|
-
attr_reader :consumer
|
|
30
|
-
|
|
31
|
-
def process_result(result, delivery_tag)
|
|
32
|
-
case result
|
|
33
|
-
when :ack
|
|
34
|
-
channel.ack(delivery_tag, false)
|
|
35
|
-
when :reject
|
|
36
|
-
channel.reject(delivery_tag)
|
|
37
|
-
when :requeue
|
|
38
|
-
channel.reject(delivery_tag, true)
|
|
39
|
-
when :nack
|
|
40
|
-
channel.nack(delivery_tag, false, true)
|
|
41
|
-
else
|
|
42
|
-
raise Lepus::InvalidConsumerReturnError, result
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Lepus
|
|
4
|
-
# @TODO: Move after/before fork hooks to this module
|
|
5
|
-
module LifecycleHooks
|
|
6
|
-
def self.included(base)
|
|
7
|
-
base.extend ClassMethods
|
|
8
|
-
base.send :include, InstanceMethods
|
|
9
|
-
base.instance_variable_set(:@lifecycle_hooks, {start: [], stop: []})
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
module ClassMethods
|
|
13
|
-
attr_reader :lifecycle_hooks
|
|
14
|
-
|
|
15
|
-
def on_start(&block)
|
|
16
|
-
lifecycle_hooks[:start] << block
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def on_stop(&block)
|
|
20
|
-
lifecycle_hooks[:stop] << block
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def clear_hooks
|
|
24
|
-
lifecycle_hooks[:start] = []
|
|
25
|
-
lifecycle_hooks[:stop] = []
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
module InstanceMethods
|
|
30
|
-
private
|
|
31
|
-
|
|
32
|
-
def run_start_hooks
|
|
33
|
-
run_hooks_for :start
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def run_stop_hooks
|
|
37
|
-
run_hooks_for :stop
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def run_hooks_for(event)
|
|
41
|
-
self.class.lifecycle_hooks.fetch(event, []).each do |block|
|
|
42
|
-
block.call
|
|
43
|
-
rescue Exception => exception # rubocop:disable Lint/RescueException
|
|
44
|
-
handle_thread_error(exception)
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
end
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Lepus
|
|
4
|
-
module Middlewares
|
|
5
|
-
# A middleware that automatically wraps {Lepus::Consumer#perform]} in an Honeybadger transaction.
|
|
6
|
-
class Honeybadger < Lepus::Middleware
|
|
7
|
-
# @param [Hash] opts The options for the middleware.
|
|
8
|
-
# @option opts [String] :class_name The name of the class you want to monitor.
|
|
9
|
-
def initialize(class_name:, **)
|
|
10
|
-
super
|
|
11
|
-
|
|
12
|
-
@class_name = class_name
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def call(message, app)
|
|
16
|
-
app.call(message)
|
|
17
|
-
rescue => err
|
|
18
|
-
::Honeybadger.notify(err, context: {class_name: @class_name})
|
|
19
|
-
raise err
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "multi_json"
|
|
4
|
-
|
|
5
|
-
module Lepus
|
|
6
|
-
module Middlewares
|
|
7
|
-
# A middleware that automatically parses your JSON payload.
|
|
8
|
-
class JSON < Lepus::Middleware
|
|
9
|
-
# @param [Hash] opts The options for the middleware.
|
|
10
|
-
# @option opts [Proc] :on_error (Proc.new { :reject }) A Proc to be called when an error occurs during processing.
|
|
11
|
-
# @option opts [Boolean] :symbolize_keys (false) Whether to symbolize the keys of your payload.
|
|
12
|
-
def initialize(**opts)
|
|
13
|
-
super
|
|
14
|
-
|
|
15
|
-
@on_error = opts.fetch(:on_error, proc { :reject })
|
|
16
|
-
@symbolize_keys = opts.fetch(:symbolize_keys, false)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def call(message, app)
|
|
20
|
-
begin
|
|
21
|
-
parsed_payload =
|
|
22
|
-
MultiJson.load(message.payload, symbolize_keys: symbolize_keys)
|
|
23
|
-
rescue => e
|
|
24
|
-
return on_error.call(e)
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
app.call(message.mutate(payload: parsed_payload))
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
private
|
|
31
|
-
|
|
32
|
-
attr_reader :symbolize_keys, :on_error
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
module Lepus
|
|
2
|
-
module Middlewares
|
|
3
|
-
# A middleware that automatically puts messages on an error queue when the specified number of retries are exceeded.
|
|
4
|
-
class MaxRetry < Lepus::Middleware
|
|
5
|
-
include Lepus::AppExecutor
|
|
6
|
-
|
|
7
|
-
# @param [Hash] opts The options for the middleware.
|
|
8
|
-
# @option opts [Integer] :retries The number of retries before the message is sent to the error queue.
|
|
9
|
-
# @option opts [String] :error_queue The name of the queue where messages should be sent to when the max retries are reached.
|
|
10
|
-
def initialize(retries:, error_queue:)
|
|
11
|
-
super
|
|
12
|
-
|
|
13
|
-
@retries = retries
|
|
14
|
-
@error_queue = error_queue
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def call(message, app)
|
|
18
|
-
return handle_exceeded(message) if retries_exceeded?(message.metadata)
|
|
19
|
-
|
|
20
|
-
app.call(message)
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
private
|
|
24
|
-
|
|
25
|
-
attr_reader :retries, :error_queue
|
|
26
|
-
|
|
27
|
-
def handle_exceeded(message)
|
|
28
|
-
payload = message.payload
|
|
29
|
-
payload = MultiJson.dump(payload) if payload.is_a?(Hash)
|
|
30
|
-
::Bunny::Exchange.default(message.delivery_info.channel).publish(
|
|
31
|
-
payload,
|
|
32
|
-
routing_key: error_queue
|
|
33
|
-
)
|
|
34
|
-
:ack
|
|
35
|
-
rescue => err
|
|
36
|
-
handle_thread_error(err)
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def retries_exceeded?(metadata)
|
|
40
|
-
return false if metadata.headers.nil?
|
|
41
|
-
|
|
42
|
-
rejected_deaths =
|
|
43
|
-
metadata
|
|
44
|
-
.headers
|
|
45
|
-
.fetch("x-death", [])
|
|
46
|
-
.select { |death| death["reason"] == "rejected" }
|
|
47
|
-
|
|
48
|
-
return false unless rejected_deaths.any?
|
|
49
|
-
|
|
50
|
-
retry_count = rejected_deaths.map { |death| death["count"] }.compact.max
|
|
51
|
-
return false unless retry_count
|
|
52
|
-
|
|
53
|
-
retry_count > @retries
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
end
|