rabbit_messaging 1.0.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: adcd319db8ad3bcb74289ff4bd1f0f3d2d7015044ade65ac73a016fd09cf87a4
4
- data.tar.gz: 2b426a968cf747ce0cd9eeada6a288b62a4e82bd60e76d7ba5c8b2dd5fd2da17
3
+ metadata.gz: 56d7ea296071a64801f4a2728f6178dc479504c5ea4185b7ec2ac78276489740
4
+ data.tar.gz: fdd63b118cd167087636dd7f0079849336e28c88fbacb8fb526720e4448f0118
5
5
  SHA512:
6
- metadata.gz: 98564c255873239d0da6a01442c72041c1e12d1d9839ffad98bb04ed5e0bb450e3fbb007db7562d362e34be7e47160f53263430ff46d9f57115d1de89001548b
7
- data.tar.gz: f12dc92841506cbdf959bbdca6b3f8d6739591aec6eb83cc4f3275074725b91ee2ad56890489c9e311e6551de1a4ac867fb6fabd55d1addbd18f79a1739d3a02
6
+ metadata.gz: ffd3d472c535d2b128e7006a4da8378f7ce845825aae09dcbd788663de1633fd18b90b13749bf412615940ef26ab3b929f27ee91efaaa502e15624a77ac0e562
7
+ data.tar.gz: 269eb1e196069f9e8cfa68292b78d7a03a04d71baaf13fe0595565346cf48c92a9ada9e00959ab0e97643c972f424537057f182004dc553447367541e67a8b2d
@@ -13,12 +13,10 @@ jobs:
13
13
  - uses: actions/checkout@v2
14
14
  - uses: ruby/setup-ruby@v1
15
15
  with:
16
- ruby-version: "3.0"
16
+ ruby-version: "3.4"
17
17
  bundler-cache: true
18
18
  - name: Run Linter
19
19
  run: bundle exec rubocop
20
- - name: Run audit
21
- run: bundle exec rake bundle:audit
22
20
  - name: Run specs
23
21
  run: bundle exec rspec
24
22
  - name: Coveralls
@@ -34,7 +32,7 @@ jobs:
34
32
  strategy:
35
33
  fail-fast: false
36
34
  matrix:
37
- ruby: ["3.0", "3.1", "3.2", "3.3"]
35
+ ruby: ["3.1", "3.2", "3.3", "3.4"]
38
36
 
39
37
  steps:
40
38
  - uses: actions/checkout@v2
data/.rubocop.yml CHANGED
@@ -26,3 +26,6 @@ Style/Alias:
26
26
  Style/HashConversion:
27
27
  Exclude:
28
28
  - spec/**/*
29
+
30
+ RSpec/ExampleLength:
31
+ Max: 50
data/CHANGELOG.md CHANGED
@@ -1,6 +1,16 @@
1
1
  # Changelog
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ ## [1.2.0] - 2025-02-10
5
+ ### Added
6
+ - Add `ExponentialBackoffHandler` for handling errors in rabbit messages
7
+ - Optional `queue_suffix` config for read queues
8
+
9
+ ## [1.1.0] - 2024-12-06
10
+ ### Added
11
+ - **Receiving**
12
+ - Support for custom receiving job config which is placed in receiving event handler;
13
+
4
14
  ## [1.0.0] - 2024-10-23
5
15
  ### Changed
6
16
  - Remove `sneakers` gem in favour of [kicks](https://github.com/ruby-amqp/kicks)
data/Gemfile CHANGED
@@ -3,8 +3,9 @@
3
3
  source "https://rubygems.org"
4
4
  gemspec
5
5
 
6
+ gem "benchmark"
6
7
  gem "bundler"
7
- gem "bundler-audit"
8
+ gem "ostruct"
8
9
  gem "pry"
9
10
  gem "rails"
10
11
  gem "rake"
@@ -13,3 +14,4 @@ gem "rspec-its"
13
14
  gem "rubocop-config-umbrellio"
14
15
  gem "simplecov"
15
16
  gem "simplecov-lcov"
17
+ gem "sneakers_handlers", github: "umbrellio/sneakers_handlers"
data/Gemfile.lock CHANGED
@@ -1,7 +1,14 @@
1
+ GIT
2
+ remote: https://github.com/umbrellio/sneakers_handlers.git
3
+ revision: d4948218a76f2e510a14a72437f4dbd1ecdbef79
4
+ specs:
5
+ sneakers_handlers (0.1.0)
6
+ kicks
7
+
1
8
  PATH
2
9
  remote: .
3
10
  specs:
4
- rabbit_messaging (1.0.0)
11
+ rabbit_messaging (1.2.0)
5
12
  bunny (~> 2.0)
6
13
  kicks (~> 3)
7
14
  lamian
@@ -88,11 +95,9 @@ GEM
88
95
  amq-protocol (2.3.2)
89
96
  ast (2.4.2)
90
97
  base64 (0.2.0)
98
+ benchmark (0.4.0)
91
99
  bigdecimal (3.1.8)
92
100
  builder (3.3.0)
93
- bundler-audit (0.9.2)
94
- bundler (>= 1.2.0, < 3)
95
- thor (~> 1.0)
96
101
  bunny (2.23.0)
97
102
  amq-protocol (~> 2.3, >= 2.3.1)
98
103
  sorted_set (~> 1, >= 1.0.2)
@@ -124,7 +129,7 @@ GEM
124
129
  rails (>= 4.2)
125
130
  language_server-protocol (3.17.0.3)
126
131
  logger (1.6.1)
127
- loofah (2.22.0)
132
+ loofah (2.23.1)
128
133
  crass (~> 1.0.2)
129
134
  nokogiri (>= 1.12.0)
130
135
  mail (2.8.1)
@@ -135,7 +140,7 @@ GEM
135
140
  marcel (1.0.4)
136
141
  method_source (1.1.0)
137
142
  mini_mime (1.1.5)
138
- mini_portile2 (2.8.7)
143
+ mini_portile2 (2.8.8)
139
144
  minitest (5.25.1)
140
145
  mutex_m (0.2.0)
141
146
  net-imap (0.4.17)
@@ -148,9 +153,10 @@ GEM
148
153
  net-smtp (0.5.0)
149
154
  net-protocol
150
155
  nio4r (2.7.3)
151
- nokogiri (1.16.7)
156
+ nokogiri (1.16.8)
152
157
  mini_portile2 (~> 2.8.2)
153
158
  racc (~> 1.4)
159
+ ostruct (0.6.1)
154
160
  parallel (1.26.3)
155
161
  parser (3.3.5.0)
156
162
  ast (~> 2.4.1)
@@ -187,9 +193,9 @@ GEM
187
193
  activesupport (>= 5.0.0)
188
194
  minitest
189
195
  nokogiri (>= 1.6)
190
- rails-html-sanitizer (1.6.0)
196
+ rails-html-sanitizer (1.6.1)
191
197
  loofah (~> 2.21)
192
- nokogiri (~> 1.14)
198
+ nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
193
199
  railties (7.1.4.1)
194
200
  actionpack (= 7.1.4.1)
195
201
  activesupport (= 7.1.4.1)
@@ -293,8 +299,9 @@ PLATFORMS
293
299
  ruby
294
300
 
295
301
  DEPENDENCIES
302
+ benchmark
296
303
  bundler
297
- bundler-audit
304
+ ostruct
298
305
  pry
299
306
  rabbit_messaging!
300
307
  rails
@@ -304,6 +311,7 @@ DEPENDENCIES
304
311
  rubocop-config-umbrellio
305
312
  simplecov
306
313
  simplecov-lcov
314
+ sneakers_handlers!
307
315
 
308
316
  BUNDLED WITH
309
- 2.3.20
317
+ 2.6.3
data/README.md CHANGED
@@ -33,38 +33,42 @@ require "rabbit_messaging"
33
33
 
34
34
  - `Rabbit.config` provides setters for following options:
35
35
 
36
- * `group_id` (`Symbol`), *required*
36
+ - `group_id` (`Symbol`), *required*
37
37
 
38
38
  Shared identifier which used to select api. As usual, it should be same as default project_id
39
39
  (I.e. we have project 'support', which runs only one application in production.
40
40
  So on, it's group_id should be :support)
41
41
 
42
- * `project_id` (`Symbol`), *required*
42
+ - `project_id` (`Symbol`), *required*
43
43
 
44
44
  Personal identifier which used to select exact service.
45
45
  As usual, it should be same as default project_id with optional stage_id.
46
46
  (I.e. we have project 'support', in production it's project_id is :support,
47
47
  but in staging it uses :support1 and :support2 ids for corresponding stages)
48
48
 
49
+ - `queue_suffix` (`String`)
49
50
 
50
- * `exception_notifier` (`Proc`)
51
+ Optional suffix added to the read queue name. For example, in case of `group_id = "grp"`, `project_id = "prj"` and
52
+ `queue_suffix = "sfx"`, Rabbit will read from queue named `"grp.prj.sfx"`.
53
+
54
+ - `exception_notifier` (`Proc`)
51
55
  You must provide your own notifier like this to notify about exceptions:
52
-
56
+
53
57
  ```ruby
54
58
  config.exception_notifier = proc { |e| MyCoolNotifier.notify!(e) }
55
59
  ```
56
60
 
57
- * `hooks` (`Hash`)
61
+ - `hooks` (`Hash`)
58
62
 
59
63
  :before_fork and :after_fork hooks, used same way as in unicorn / puma / que / etc
60
64
 
61
- * `environment` (one of `:test`, `:development`, `:production`), *default:* `:production`
65
+ - `environment` (one of `:test`, `:development`, `:production`), *default:- `:production`
62
66
 
63
67
  Internal environment of gem.
64
68
 
65
- * `:test` environment stubs publishing and does not suppress errors
66
- * `:development` environment auto-creates queues and uses default exchange
67
- * `:production` environment enables handlers caching and gets maximum strictness
69
+ - `:test` environment stubs publishing and does not suppress errors
70
+ - `:development` environment auto-creates queues and uses default exchange
71
+ - `:production` environment enables handlers caching and gets maximum strictness
68
72
 
69
73
  By default gem skips publishing in test and development environments.
70
74
  If you want to change that then manually set `Rabbit.skip_publishing_in` with an array of environments.
@@ -73,13 +77,13 @@ require "rabbit_messaging"
73
77
  Rabbit.skip_publishing_in = %i[test]
74
78
  ```
75
79
 
76
- * `receiving_job_class_callable` (`Proc`)
80
+ - `receiving_job_class_callable` (`Proc`)
77
81
 
78
82
  Custom ActiveJob subclass to work with received messages. Receives the following attributes as `kwarg`-arguments:
79
83
 
80
- * `:arguments` - information about message type (`type`), application id (`app_id`), message id (`message_id`);
81
- * `:delivery_info` - information about `exchange`, `routing_key`, etc;
82
- * `:message` - received RabbitMQ message (often in a `string` format);
84
+ - `:arguments` - information about message type (`type`), application id (`app_id`), message id (`message_id`);
85
+ - `:delivery_info` - information about `exchange`, `routing_key`, etc;
86
+ - `:message` - received RabbitMQ message (often in a `string` format);
83
87
 
84
88
  ```ruby
85
89
  {
@@ -93,7 +97,7 @@ require "rabbit_messaging"
93
97
  }
94
98
  ```
95
99
 
96
- * `before_receiving_hooks, after_receiving_hooks` (`Array of Procs`)
100
+ - `before_receiving_hooks, after_receiving_hooks` (`Array of Procs`)
97
101
 
98
102
  Before and after hooks with message processing in the middle. Where `before_receiving_hooks` and `after_receiving_hooks` are empty arrays by default.
99
103
 
@@ -107,8 +111,22 @@ require "rabbit_messaging"
107
111
 
108
112
  config.after_receiving_hooks.append(proc { |message, arguments| do_stuff_3 })
109
113
  config.after_receiving_hooks.append(proc { |message, arguments| do_stuff_4 })
114
+ ```
115
+
116
+ - `use_backoff_handler` (`Boolean`)
117
+
118
+ If set to `true`, use `ExponentialBackoffHandler`. You will also need add the following line to your Gemfile:
110
119
 
120
+ ```ruby
121
+ gem "sneakers_handlers", github: "umbrellio/sneakers_handlers"
111
122
  ```
123
+
124
+ See https://github.com/umbrellio/sneakers_handlers for more details.
125
+
126
+
127
+ - `backoff_handler_max_retries` (`Integer`)
128
+
129
+ Number of retries that `ExponentialBackoffHandler` will use before sending job to the error queue. 5 by default.
112
130
  ---
113
131
 
114
132
  ### Client
@@ -127,16 +145,16 @@ Rabbit.publish(
127
145
 
128
146
  - This code sends messages via basic_publish with following parameters:
129
147
 
130
- * `routing_key`: `"support"`
131
- * `exchange`: `"group_id.project_id.fanout"` (default is `"group_id.poject_id"`)
132
- * `mandatory`: `true` (same as confirm_select)
148
+ - `routing_key`: `"support"`
149
+ - `exchange`: `"group_id.project_id.fanout"` (default is `"group_id.poject_id"`)
150
+ - `mandatory`: `true` (same as confirm_select)
133
151
 
134
152
  It is set to raise error if routing failed
135
153
 
136
- * `persistent`: `true`
137
- * `type`: `"ping"`
138
- * `content_type`: `"application/json"` (always)
139
- * `app_id`: `"group_id.project_id"`
154
+ - `persistent`: `true`
155
+ - `type`: `"ping"`
156
+ - `content_type`: `"application/json"` (always)
157
+ - `app_id`: `"group_id.project_id"`
140
158
 
141
159
  - Messages are logged to `/log/rabbit.log`
142
160
 
data/Rakefile CHANGED
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "bundler/gem_tasks"
4
- require "bundler/audit/task"
5
4
  require "rspec/core/rake_task"
6
5
  require "rubocop"
7
6
  require "rubocop-rspec"
@@ -17,6 +16,5 @@ RuboCop::RakeTask.new(:rubocop) do |t|
17
16
  end
18
17
 
19
18
  RSpec::Core::RakeTask.new(:rspec)
20
- Bundler::Audit::Task.new
21
19
 
22
20
  task default: :rspec
data/bin/console CHANGED
@@ -1,5 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ # Required for tainbox :(
4
+ require "active_support/deprecation"
5
+ require "active_support/deprecator"
6
+
3
7
  require "bundler/setup"
4
8
  require "rabbit_messaging"
5
9
 
data/lib/rabbit/daemon.rb CHANGED
@@ -18,25 +18,34 @@ module Rabbit
18
18
  Lamian.extend_logger(logger)
19
19
  end
20
20
 
21
+ self.logger = logger
22
+
21
23
  Sneakers.configure(**sneakers_config(logger: logger))
22
24
  Sneakers.server = true
23
25
 
24
26
  Rabbit.config.validate!
25
- Receiving::Worker.from_queue(Rabbit.config.read_queue)
27
+
28
+ Receiving::Worker.from_queue(Rabbit.config.read_queue, **worker_options)
26
29
  Sneakers::Runner.new([Receiving::Worker]).run
27
30
  end
28
31
 
29
32
  def config
30
- Rails.application.config_for("sneakers").symbolize_keys
33
+ @config ||= Rails.application.config_for("sneakers").symbolize_keys
31
34
  end
32
35
 
33
36
  def connection
34
- bunny_config = config.delete(:bunny_options).to_h.symbolize_keys
35
- Bunny.new(bunny_config)
37
+ @connection ||= begin
38
+ bunny_config = config.delete(:bunny_options).to_h.symbolize_keys
39
+ bunny_logger = logger.dup
40
+ bunny_logger.level = bunny_config.delete(:log_level) || :info
41
+ Bunny.new(**bunny_config, logger: bunny_logger)
42
+ end
36
43
  end
37
44
 
38
45
  private
39
46
 
47
+ attr_accessor :logger
48
+
40
49
  def sneakers_config(logger:)
41
50
  {
42
51
  connection: connection,
@@ -51,5 +60,20 @@ module Rabbit
51
60
  **config,
52
61
  }
53
62
  end
63
+
64
+ def worker_options
65
+ return {} unless Rabbit.config.use_backoff_handler
66
+
67
+ require "sneakers_handlers"
68
+
69
+ {
70
+ handler: SneakersHandlers::ExponentialBackoffHandler,
71
+ max_retries: Rabbit.config.backoff_handler_max_retries,
72
+ arguments: {
73
+ "x-dead-letter-exchange" => "#{Rabbit.config.read_queue}.dlx",
74
+ "x-dead-letter-routing-key" => "#{Rabbit.config.read_queue}.dlx",
75
+ },
76
+ }
77
+ end
54
78
  end
55
79
  end
@@ -12,6 +12,7 @@ class Rabbit::EventHandler
12
12
 
13
13
  class_attribute :queue
14
14
  class_attribute :ignore_queue_conversion, default: false
15
+ class_attribute :additional_job_configs, default: {}
15
16
 
16
17
  class << self
17
18
  private
@@ -19,6 +20,14 @@ class Rabbit::EventHandler
19
20
  def queue_as(queue = nil, &block)
20
21
  self.queue = queue || block
21
22
  end
23
+
24
+ def job_config(**config_opts)
25
+ additional_job_configs.merge!(config_opts)
26
+ end
27
+
28
+ def job_configs(**config_opts)
29
+ self.additional_job_configs = config_opts
30
+ end
22
31
  end
23
32
 
24
33
  def initialize(message)
@@ -50,11 +50,11 @@ module Rabbit
50
50
  @logger ||= Rabbit.config.publish_logger
51
51
 
52
52
  metadata = [
53
- message.real_exchange_name, message.routing_key, message.headers,
53
+ message.real_exchange_name, message.routing_key, JSON.dump(message.headers),
54
54
  message.event, message.confirm_select? ? "confirm" : "no-confirm"
55
55
  ]
56
56
 
57
- @logger.debug "#{metadata.join ' / '}: #{message.data}"
57
+ @logger.debug "#{metadata.join ' / '}: #{JSON.dump(message.data)}"
58
58
  end
59
59
  end
60
60
  end
@@ -28,7 +28,7 @@ class Rabbit::Receiving::Receive
28
28
 
29
29
  def process_message
30
30
  job_class
31
- .set(queue: queue)
31
+ .set(queue: queue_name, **job_configs)
32
32
  .perform_later(message, message_info)
33
33
  end
34
34
 
@@ -53,7 +53,15 @@ class Rabbit::Receiving::Receive
53
53
  end
54
54
 
55
55
  def queue
56
- Rabbit::Receiving::Queue.new(message, arguments).name
56
+ @queue ||= Rabbit::Receiving::Queue.new(message, arguments)
57
+ end
58
+
59
+ def job_configs
60
+ queue.handler.additional_job_configs
61
+ end
62
+
63
+ def queue_name
64
+ queue.name
57
65
  end
58
66
 
59
67
  def job_class
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rabbit
4
- VERSION = "1.0.0"
4
+ VERSION = "1.2.0"
5
5
  end
data/lib/rabbit.rb CHANGED
@@ -16,10 +16,11 @@ module Rabbit
16
16
  class Config
17
17
  include Tainbox
18
18
 
19
- attribute :group_id, Symbol
20
- attribute :project_id, Symbol
19
+ attribute :group_id, :Symbol
20
+ attribute :project_id, :Symbol
21
+ attribute :queue_suffix, :String
21
22
  attribute :hooks, default: {}
22
- attribute :environment, Symbol, default: :production
23
+ attribute :environment, :Symbol, default: :production
23
24
  attribute :queue_name_conversion
24
25
  attribute :receiving_job_class_callable
25
26
  attribute :handler_resolver_callable
@@ -27,6 +28,8 @@ module Rabbit
27
28
  attribute :before_receiving_hooks, default: []
28
29
  attribute :after_receiving_hooks, default: []
29
30
  attribute :skip_publishing_in, default: %i[test development]
31
+ attribute :use_backoff_handler, :Boolean, default: false
32
+ attribute :backoff_handler_max_retries, Integer, default: 6
30
33
 
31
34
  attribute :receive_logger, default: lambda {
32
35
  Logger.new(Rails.root.join("log", "incoming_rabbit_messages.log"))
@@ -58,7 +61,9 @@ module Rabbit
58
61
  [group_id, project_id].join(".")
59
62
  end
60
63
 
61
- alias_method :read_queue, :app_name
64
+ def read_queue
65
+ [app_name, queue_suffix].reject { |x| x.nil? || x.empty? }.join(".")
66
+ end
62
67
  end
63
68
 
64
69
  extend self
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rabbit_messaging
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Umbrellio
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-10-23 00:00:00.000000000 Z
10
+ date: 2025-02-10 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: bunny
@@ -124,7 +123,6 @@ files:
124
123
  homepage: https://github.com/umbrellio/rabbit_messaging
125
124
  licenses: []
126
125
  metadata: {}
127
- post_install_message:
128
126
  rdoc_options: []
129
127
  require_paths:
130
128
  - lib
@@ -139,8 +137,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
139
137
  - !ruby/object:Gem::Version
140
138
  version: '0'
141
139
  requirements: []
142
- rubygems_version: 3.5.22
143
- signing_key:
140
+ rubygems_version: 3.6.3
144
141
  specification_version: 4
145
142
  summary: Rabbit (Rabbit Messaging)
146
143
  test_files: []