rabbit_messaging 0.7.1 → 0.12.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3f1b038de91f05a992e1c8cd26cd2fbffc3eacff6876b53399ec48452dbdd57d
4
- data.tar.gz: b1c5c72e4486dad8150b5c96e0e84dcd170362267addb5126a4b41a15442c7d1
3
+ metadata.gz: 7bc319672450b1eac69256139e858e4c2d3d1f26e3427d727bebd48713990b97
4
+ data.tar.gz: 927a86a73c692dde6610000b62ef008e6eb1bbc9a425dac655f12d1f95d380f7
5
5
  SHA512:
6
- metadata.gz: af0bdacb84ef30a921b8feb3037d0a09ad989ad869fed8b21a213e5be990181fe9c96367c3e5ca601935c9b135a0b3bb3ad1f2a021047df3ccc1548ce8452883
7
- data.tar.gz: e1e4250eb88622b1c0f27aa8abac6d117cfd0672fc75750b2f6f76c357459298fd115a11cf45d29812bcc9decc032ab91dee00251d0dff7b52ef4d9efc0a92e1
6
+ metadata.gz: fb7d00985eb4964c6e1588591ed61d024b78a273b571dde4a3cccabfe8c4aeb798b45aec8290dc86eb3e140afa076c9bf75d21344873fda8084e3465ad670235
7
+ data.tar.gz: 943a61798405d733309df200bca51615fdc3653b4d546dfb2ef77a3642f02de413b2ce56af7f2b724d7f77b49e075198d0e540a891f71fbe108aa6cd096796f9
@@ -0,0 +1,55 @@
1
+ name: Test
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ full-check:
7
+ runs-on: ubuntu-latest
8
+
9
+ # We want to run on external PRs, but not on our own internal PRs as they'll be run on push event
10
+ if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != 'umbrellio/rabbit_messaging'
11
+
12
+ steps:
13
+ - uses: actions/checkout@v2
14
+ - uses: ruby/setup-ruby@v1
15
+ with:
16
+ ruby-version: "3.0"
17
+ bundler-cache: true
18
+ - name: Create log dir
19
+ run: mkdir -p log
20
+ - name: Run Linter
21
+ run: bundle exec rubocop
22
+ - name: Run audit
23
+ run: bundle exec rake bundle:audit
24
+ - name: Run specs
25
+ run: bundle exec rspec
26
+ - name: Coveralls
27
+ uses: coverallsapp/github-action@master
28
+ with:
29
+ github-token: ${{ secrets.GITHUB_TOKEN }}
30
+ specs:
31
+ runs-on: ubuntu-latest
32
+ continue-on-error: ${{ matrix.experimental }}
33
+
34
+ # We want to run on external PRs, but not on our own internal PRs as they'll be run on push event
35
+ if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != 'umbrellio/rabbit_messaging'
36
+
37
+ strategy:
38
+ fail-fast: false
39
+ matrix:
40
+ ruby: ["2.5", "2.6", "2.7"]
41
+ experimental: [false]
42
+ include:
43
+ - ruby: head
44
+ experimental: true
45
+
46
+ steps:
47
+ - uses: actions/checkout@v2
48
+ - uses: ruby/setup-ruby@v1
49
+ with:
50
+ ruby-version: ${{ matrix.ruby }}
51
+ bundler-cache: true
52
+ - name: Create log dir
53
+ run: mkdir -p log
54
+ - name: Run specs
55
+ run: bundle exec rspec
data/.gitignore CHANGED
@@ -6,7 +6,6 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
- Gemfile.lock
10
9
  .ruby-version
11
10
  /log/
12
11
  *.gem
data/.rubocop.yml CHANGED
@@ -3,7 +3,7 @@ inherit_gem:
3
3
 
4
4
  AllCops:
5
5
  DisplayCopNames: true
6
- TargetRubyVersion: 2.3
6
+ TargetRubyVersion: 2.5
7
7
  Include:
8
8
  - lib/**/*.rb
9
9
  - spec/**/*.rb
@@ -15,3 +15,7 @@ AllCops:
15
15
 
16
16
  Style/Alias:
17
17
  EnforcedStyle: prefer_alias_method
18
+
19
+ Style/HashConversion:
20
+ Exclude:
21
+ - spec/**/*
data/CHANGELOG.md CHANGED
@@ -1,6 +1,44 @@
1
1
  # Changelog
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ ## [0.11.0] - 2021-05-05
5
+ ### Added
6
+ - `Rabbit.config.receiving_job_class_callable` now receives the full message context (with `message`, `delivery_info` and `arguments` (see the `Rabbit::Receiving::Receive`));
7
+
8
+ ## [0.10.0] - 2021-03-05
9
+ ### Added
10
+ - logging message headers
11
+
12
+ ## [0.9.0] - 2020-11-18
13
+ ### Added
14
+ - configurable publish skipping (previous iteration just skipped in development)
15
+
16
+ ### Fixed
17
+ - fix for receiving (delivery_info and args to hashes)
18
+ - fix for requiring receiving job
19
+
20
+ ## [0.8.1] - 2020-11-05
21
+ ### Added
22
+ - channels pool for manage channels on Publisher connection
23
+ ### Changed
24
+ - Publisher use channels pool for access to channel
25
+
26
+ ## [0.8.0] - 2020-10-28
27
+ ### Added
28
+ - class Rabbit::Recieving::Receive for message processing
29
+ - class Rabbit::Recieving::Queue for queue name determination when receiving
30
+ - message_id argument in published and received messages
31
+ - before and after hooks when processing message
32
+ - specs for new functionality
33
+ - arguments attribute in received message and handler (contain raw message arguments with exchange and routing_key from the delivery_info)
34
+
35
+ ### Changed
36
+ - Rabbit::Receiving::Worker refactoring (message processing moved to a separate class)
37
+ - ruby version upped to 2.5
38
+ - rubocop ruby target version set to 2.5
39
+ - some fixes of updated rubocop and ruby warnings
40
+ - heavy refactoring of old specs for receiving
41
+
4
42
  ## [0.7.1] - 2020-06-09
5
43
  ### Changed
6
44
  - (Partially Fixed) Support for pre-defined logger injection on Sneakers moudle;
data/Gemfile.lock ADDED
@@ -0,0 +1,256 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ rabbit_messaging (0.11.0)
5
+ bunny (~> 2.0)
6
+ exception_notification
7
+ lamian
8
+ rails (>= 5.2)
9
+ sneakers (~> 2.0)
10
+ tainbox
11
+
12
+ GEM
13
+ remote: https://rubygems.org/
14
+ specs:
15
+ actioncable (6.1.3.2)
16
+ actionpack (= 6.1.3.2)
17
+ activesupport (= 6.1.3.2)
18
+ nio4r (~> 2.0)
19
+ websocket-driver (>= 0.6.1)
20
+ actionmailbox (6.1.3.2)
21
+ actionpack (= 6.1.3.2)
22
+ activejob (= 6.1.3.2)
23
+ activerecord (= 6.1.3.2)
24
+ activestorage (= 6.1.3.2)
25
+ activesupport (= 6.1.3.2)
26
+ mail (>= 2.7.1)
27
+ actionmailer (6.1.3.2)
28
+ actionpack (= 6.1.3.2)
29
+ actionview (= 6.1.3.2)
30
+ activejob (= 6.1.3.2)
31
+ activesupport (= 6.1.3.2)
32
+ mail (~> 2.5, >= 2.5.4)
33
+ rails-dom-testing (~> 2.0)
34
+ actionpack (6.1.3.2)
35
+ actionview (= 6.1.3.2)
36
+ activesupport (= 6.1.3.2)
37
+ rack (~> 2.0, >= 2.0.9)
38
+ rack-test (>= 0.6.3)
39
+ rails-dom-testing (~> 2.0)
40
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
41
+ actiontext (6.1.3.2)
42
+ actionpack (= 6.1.3.2)
43
+ activerecord (= 6.1.3.2)
44
+ activestorage (= 6.1.3.2)
45
+ activesupport (= 6.1.3.2)
46
+ nokogiri (>= 1.8.5)
47
+ actionview (6.1.3.2)
48
+ activesupport (= 6.1.3.2)
49
+ builder (~> 3.1)
50
+ erubi (~> 1.4)
51
+ rails-dom-testing (~> 2.0)
52
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
53
+ activejob (6.1.3.2)
54
+ activesupport (= 6.1.3.2)
55
+ globalid (>= 0.3.6)
56
+ activemodel (6.1.3.2)
57
+ activesupport (= 6.1.3.2)
58
+ activerecord (6.1.3.2)
59
+ activemodel (= 6.1.3.2)
60
+ activesupport (= 6.1.3.2)
61
+ activestorage (6.1.3.2)
62
+ actionpack (= 6.1.3.2)
63
+ activejob (= 6.1.3.2)
64
+ activerecord (= 6.1.3.2)
65
+ activesupport (= 6.1.3.2)
66
+ marcel (~> 1.0.0)
67
+ mini_mime (~> 1.0.2)
68
+ activesupport (6.1.3.2)
69
+ concurrent-ruby (~> 1.0, >= 1.0.2)
70
+ i18n (>= 1.6, < 2)
71
+ minitest (>= 5.1)
72
+ tzinfo (~> 2.0)
73
+ zeitwerk (~> 2.3)
74
+ amq-protocol (2.3.2)
75
+ ast (2.4.2)
76
+ builder (3.2.4)
77
+ bundler-audit (0.8.0)
78
+ bundler (>= 1.2.0, < 3)
79
+ thor (~> 1.0)
80
+ bunny (2.18.0)
81
+ amq-protocol (~> 2.3, >= 2.3.1)
82
+ sorted_set (~> 1, >= 1.0.2)
83
+ coderay (1.1.3)
84
+ concurrent-ruby (1.1.8)
85
+ crass (1.0.6)
86
+ diff-lcs (1.4.4)
87
+ docile (1.4.0)
88
+ erubi (1.10.0)
89
+ exception_notification (4.4.3)
90
+ actionmailer (>= 4.0, < 7)
91
+ activesupport (>= 4.0, < 7)
92
+ globalid (0.4.2)
93
+ activesupport (>= 4.2.0)
94
+ i18n (1.8.10)
95
+ concurrent-ruby (~> 1.0)
96
+ lamian (1.2.0)
97
+ rails (>= 4.2)
98
+ loofah (2.9.1)
99
+ crass (~> 1.0.2)
100
+ nokogiri (>= 1.5.9)
101
+ mail (2.7.1)
102
+ mini_mime (>= 0.1.1)
103
+ marcel (1.0.1)
104
+ method_source (1.0.0)
105
+ mini_mime (1.0.3)
106
+ mini_portile2 (2.5.1)
107
+ minitest (5.14.4)
108
+ nio4r (2.5.7)
109
+ nokogiri (1.11.6)
110
+ mini_portile2 (~> 2.5.0)
111
+ racc (~> 1.4)
112
+ parallel (1.20.1)
113
+ parser (3.0.1.1)
114
+ ast (~> 2.4.1)
115
+ pry (0.14.1)
116
+ coderay (~> 1.1)
117
+ method_source (~> 1.0)
118
+ racc (1.5.2)
119
+ rack (2.2.3)
120
+ rack-test (1.1.0)
121
+ rack (>= 1.0, < 3)
122
+ rails (6.1.3.2)
123
+ actioncable (= 6.1.3.2)
124
+ actionmailbox (= 6.1.3.2)
125
+ actionmailer (= 6.1.3.2)
126
+ actionpack (= 6.1.3.2)
127
+ actiontext (= 6.1.3.2)
128
+ actionview (= 6.1.3.2)
129
+ activejob (= 6.1.3.2)
130
+ activemodel (= 6.1.3.2)
131
+ activerecord (= 6.1.3.2)
132
+ activestorage (= 6.1.3.2)
133
+ activesupport (= 6.1.3.2)
134
+ bundler (>= 1.15.0)
135
+ railties (= 6.1.3.2)
136
+ sprockets-rails (>= 2.0.0)
137
+ rails-dom-testing (2.0.3)
138
+ activesupport (>= 4.2.0)
139
+ nokogiri (>= 1.6)
140
+ rails-html-sanitizer (1.3.0)
141
+ loofah (~> 2.3)
142
+ railties (6.1.3.2)
143
+ actionpack (= 6.1.3.2)
144
+ activesupport (= 6.1.3.2)
145
+ method_source
146
+ rake (>= 0.8.7)
147
+ thor (~> 1.0)
148
+ rainbow (3.0.0)
149
+ rake (13.0.3)
150
+ rbtree (0.4.4)
151
+ regexp_parser (2.1.1)
152
+ rexml (3.2.5)
153
+ rspec (3.10.0)
154
+ rspec-core (~> 3.10.0)
155
+ rspec-expectations (~> 3.10.0)
156
+ rspec-mocks (~> 3.10.0)
157
+ rspec-core (3.10.1)
158
+ rspec-support (~> 3.10.0)
159
+ rspec-expectations (3.10.1)
160
+ diff-lcs (>= 1.2.0, < 2.0)
161
+ rspec-support (~> 3.10.0)
162
+ rspec-its (1.3.0)
163
+ rspec-core (>= 3.0.0)
164
+ rspec-expectations (>= 3.0.0)
165
+ rspec-mocks (3.10.2)
166
+ diff-lcs (>= 1.2.0, < 2.0)
167
+ rspec-support (~> 3.10.0)
168
+ rspec-support (3.10.2)
169
+ rubocop (1.11.0)
170
+ parallel (~> 1.10)
171
+ parser (>= 3.0.0.0)
172
+ rainbow (>= 2.2.2, < 4.0)
173
+ regexp_parser (>= 1.8, < 3.0)
174
+ rexml
175
+ rubocop-ast (>= 1.2.0, < 2.0)
176
+ ruby-progressbar (~> 1.7)
177
+ unicode-display_width (>= 1.4.0, < 3.0)
178
+ rubocop-ast (1.6.0)
179
+ parser (>= 3.0.1.1)
180
+ rubocop-config-umbrellio (1.11.0.40)
181
+ rubocop (= 1.11.0)
182
+ rubocop-performance (= 1.10.0)
183
+ rubocop-rails (= 2.9.1)
184
+ rubocop-rake (= 0.5.1)
185
+ rubocop-rspec (= 2.2.0)
186
+ rubocop-sequel (= 0.2.0)
187
+ rubocop-performance (1.10.0)
188
+ rubocop (>= 0.90.0, < 2.0)
189
+ rubocop-ast (>= 0.4.0)
190
+ rubocop-rails (2.9.1)
191
+ activesupport (>= 4.2.0)
192
+ rack (>= 1.1)
193
+ rubocop (>= 0.90.0, < 2.0)
194
+ rubocop-rake (0.5.1)
195
+ rubocop
196
+ rubocop-rspec (2.2.0)
197
+ rubocop (~> 1.0)
198
+ rubocop-ast (>= 1.1.0)
199
+ rubocop-sequel (0.2.0)
200
+ rubocop (~> 1.0)
201
+ ruby-progressbar (1.11.0)
202
+ serverengine (2.0.7)
203
+ sigdump (~> 0.2.2)
204
+ set (1.0.1)
205
+ sigdump (0.2.4)
206
+ simplecov (0.21.2)
207
+ docile (~> 1.1)
208
+ simplecov-html (~> 0.11)
209
+ simplecov_json_formatter (~> 0.1)
210
+ simplecov-html (0.12.3)
211
+ simplecov-lcov (0.8.0)
212
+ simplecov_json_formatter (0.1.3)
213
+ sneakers (2.11.0)
214
+ bunny (~> 2.12)
215
+ concurrent-ruby (~> 1.0)
216
+ rake
217
+ serverengine (~> 2.0.5)
218
+ thor
219
+ sorted_set (1.0.3)
220
+ rbtree
221
+ set (~> 1.0)
222
+ sprockets (4.0.2)
223
+ concurrent-ruby (~> 1.0)
224
+ rack (> 1, < 3)
225
+ sprockets-rails (3.2.2)
226
+ actionpack (>= 4.0)
227
+ activesupport (>= 4.0)
228
+ sprockets (>= 3.0.0)
229
+ tainbox (2.1.2)
230
+ activesupport
231
+ thor (1.1.0)
232
+ tzinfo (2.0.4)
233
+ concurrent-ruby (~> 1.0)
234
+ unicode-display_width (2.0.0)
235
+ websocket-driver (0.7.4)
236
+ websocket-extensions (>= 0.1.0)
237
+ websocket-extensions (0.1.5)
238
+ zeitwerk (2.4.2)
239
+
240
+ PLATFORMS
241
+ ruby
242
+
243
+ DEPENDENCIES
244
+ bundler
245
+ bundler-audit
246
+ pry
247
+ rabbit_messaging!
248
+ rake
249
+ rspec
250
+ rspec-its
251
+ rubocop-config-umbrellio
252
+ simplecov (>= 0.21)
253
+ simplecov-lcov
254
+
255
+ BUNDLED WITH
256
+ 2.2.17
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Rabbit (Rabbit Messaging) &middot; [![Gem Version](https://badge.fury.io/rb/rabbit_messaging.svg)](https://badge.fury.io/rb/rabbit_messaging) [![Build Status](https://travis-ci.org/umbrellio/rabbit_messaging.svg?branch=master)](https://travis-ci.org/umbrellio/rabbit_messaging) [![Coverage Status](https://coveralls.io/repos/github/umbrellio/rabbit_messaging/badge.svg?branch=master)](https://coveralls.io/github/umbrellio/rabbit_messaging?branch=master)
1
+ # Rabbit (Rabbit Messaging) &middot; [![Gem Version](https://badge.fury.io/rb/rabbit_messaging.svg)](https://badge.fury.io/rb/rabbit_messaging) [![Coverage Status](https://coveralls.io/repos/github/umbrellio/rabbit_messaging/badge.svg?branch=master)](https://coveralls.io/github/umbrellio/rabbit_messaging?branch=master)
2
2
 
3
3
  Provides client and server support for RabbitMQ
4
4
 
@@ -58,9 +58,32 @@ require "rabbit_messaging"
58
58
  * `:development` environment auto-creates queues and uses default exchange
59
59
  * `:production` environment enables handlers caching and gets maximum strictness
60
60
 
61
+ By default gem skips publishing in test and development environments.
62
+ If you want to change that then manually set `Rabbit.skip_publishing_in` with an array of environments.
63
+
64
+ ```ruby
65
+ Rabbit.skip_publishing_in = %i[test]
66
+ ```
67
+
61
68
  * `receiving_job_class_callable` (`Proc`)
62
69
 
63
- Custom ActiveJob subclass to work with received messages.
70
+ Custom ActiveJob subclass to work with received messages. Receives the following attributes as `kwarg`-arguments:
71
+
72
+ * `:arguments` - information about message type (`type`), application id (`app_id`), message id (`message_id`);
73
+ * `:delivery_info` - information about `exchange`, `routing_key`, etc;
74
+ * `:message` - received RabbitMQ message (often in a `string` format);
75
+
76
+ ```ruby
77
+ {
78
+ message: '{"hello":"world","foo":"bar"}',
79
+ delivery_info: { exchange: "some exchange", routing_key: "some_key" },
80
+ arguments: {
81
+ type: "some_successful_event",
82
+ app_id: "some_group.some_app",
83
+ message_id: "uuid",
84
+ }
85
+ }
86
+ ```
64
87
 
65
88
  * `exception_notifier` (`Proc`)
66
89
 
@@ -71,6 +94,22 @@ require "rabbit_messaging"
71
94
  config.exception_notifier = proc { |e| MyCoolNotifier.notify!(e) }
72
95
  ```
73
96
 
97
+ * `before_receiving_hooks, after_receiving_hooks` (`Array of Procs`)
98
+
99
+ Before and after hooks with message processing in the middle. Where `before_receiving_hooks` and `after_receiving_hooks` are empty arrays by default.
100
+
101
+ It's advised to NOT place procs with long execution time inside.
102
+
103
+ Setup:
104
+
105
+ ```ruby
106
+ config.before_receiving_hooks.append(proc { |message, arguments| do_stuff_1 })
107
+ config.before_receiving_hooks.append(proc { |message, arguments| do_stuff_2 })
108
+
109
+ config.after_receiving_hooks.append(proc { |message, arguments| do_stuff_3 })
110
+ config.after_receiving_hooks.append(proc { |message, arguments| do_stuff_4 })
111
+
112
+ ```
74
113
  ---
75
114
 
76
115
  ### Client
@@ -83,6 +122,7 @@ Rabbit.publish(
83
122
  exchange_name: 'fanout', # default is fine too
84
123
  confirm_select: true, # setting this to false grants you great speed up and absolutelly no guarantees
85
124
  headers: { "foo" => "bar" }, # custom arguments for routing, default is {}
125
+ message_id: "asdadsadsad", # A unique identifier such as a UUID that your application can use to identify the message.
86
126
  )
87
127
  ```
88
128
 
data/lib/rabbit.rb CHANGED
@@ -23,6 +23,9 @@ module Rabbit
23
23
  attribute :queue_name_conversion
24
24
  attribute :receiving_job_class_callable
25
25
  attribute :exception_notifier, default: -> { default_exception_notifier }
26
+ attribute :before_receiving_hooks, default: []
27
+ attribute :after_receiving_hooks, default: []
28
+ attribute :skip_publishing_in, default: %i[test development]
26
29
 
27
30
  attribute :receive_logger, default: lambda {
28
31
  Logger.new(Rails.root.join("log", "incoming_rabbit_messages.log"))
@@ -45,6 +48,10 @@ module Rabbit
45
48
  end
46
49
  end
47
50
 
51
+ def skip_publish?
52
+ skip_publishing_in.include?(environment)
53
+ end
54
+
48
55
  def app_name
49
56
  [group_id, project_id].join(".")
50
57
  end
data/lib/rabbit/daemon.rb CHANGED
@@ -11,30 +11,18 @@ module Rabbit
11
11
  module Daemon
12
12
  extend self
13
13
 
14
- def run
15
- Sneakers.configure(
16
- connection: connection,
17
- env: Rails.env,
18
- exchange_type: :direct,
19
- exchange: Rabbit.config.app_name,
20
- hooks: Rabbit.config.hooks,
21
- supervisor: true,
22
- daemonize: false,
23
- exit_on_detach: true,
24
- **config,
25
- )
26
-
27
- unless Sneakers.logger
28
- Sneakers.logger = Logger.new(Rails.root.join("log", "sneakers.log"))
29
- Sneakers.logger.level = Logger::DEBUG
30
- Lamian.extend_logger(Sneakers.logger)
31
- end
32
-
14
+ def run(logger: Sneakers.logger)
15
+ unless logger
16
+ logger = Logger.new(Rails.root.join("log", "sneakers.log"))
17
+ logger.level = Logger::DEBUG
18
+ Lamian.extend_logger(logger)
19
+ end
20
+
21
+ Sneakers.configure(**sneakers_config(logger: logger))
33
22
  Sneakers.server = true
34
23
 
35
24
  Rabbit.config.validate!
36
25
  Receiving::Worker.from_queue(Rabbit.config.read_queue)
37
-
38
26
  Sneakers::Runner.new([Receiving::Worker]).run
39
27
  end
40
28
 
@@ -46,5 +34,22 @@ module Rabbit
46
34
  bunny_config = config.delete(:bunny_options).to_h.symbolize_keys
47
35
  Bunny.new(bunny_config)
48
36
  end
37
+
38
+ private
39
+
40
+ def sneakers_config(logger:)
41
+ {
42
+ connection: connection,
43
+ env: Rails.env,
44
+ exchange_type: :direct,
45
+ exchange: Rabbit.config.app_name,
46
+ hooks: Rabbit.config.hooks,
47
+ supervisor: true,
48
+ daemonize: false,
49
+ exit_on_detach: true,
50
+ log: logger,
51
+ **config,
52
+ }
53
+ end
49
54
  end
50
55
  end
@@ -7,7 +7,9 @@ class Rabbit::EventHandler
7
7
  include Tainbox
8
8
 
9
9
  attribute :project_id
10
- attr_accessor :data
10
+ attribute :data
11
+ attribute :message_info
12
+
11
13
  class_attribute :queue
12
14
  class_attribute :ignore_queue_conversion, default: false
13
15
 
@@ -20,8 +22,9 @@ class Rabbit::EventHandler
20
22
  end
21
23
 
22
24
  def initialize(message)
23
- self.attributes = message.data
24
- self.data = message.data
25
- self.project_id = message.project_id
25
+ self.attributes = message.data
26
+ self.data = message.data
27
+ self.project_id = message.project_id
28
+ self.message_info = message.arguments
26
29
  end
27
30
  end
@@ -5,39 +5,32 @@ require "rabbit/publishing/message"
5
5
  module Rabbit
6
6
  module Publishing
7
7
  autoload :Job, "rabbit/publishing/job"
8
+ autoload :ChannelsPool, "rabbit/publishing/channels_pool"
9
+ extend self
8
10
 
9
11
  MUTEX = Mutex.new
10
12
 
11
- extend self
13
+ def publish(msg)
14
+ return if Rabbit.config.skip_publish?
12
15
 
13
- def publish(message)
14
- return unless client
16
+ pool.with_channel msg.confirm_select? do |ch|
17
+ ch.basic_publish *msg.basic_publish_args
15
18
 
16
- channel = channel(message.confirm_select?)
17
- channel.basic_publish(*message.basic_publish_args)
19
+ raise MessageNotDelivered, "RabbitMQ message not delivered: #{msg}" \
20
+ if msg.confirm_select? && !ch.wait_for_confirms
18
21
 
19
- if message.confirm_select? && !channel.wait_for_confirms
20
- raise MessageNotDelivered, "RabbitMQ message not delivered: #{message}"
21
- else
22
- log(message)
22
+ log msg
23
23
  end
24
24
  rescue Timeout::Error
25
25
  raise MessageNotDelivered, <<~MESSAGE
26
- Timeout while sending message #{message}. Possible reasons:
27
- - #{message.real_exchange_name} exchange is not found
26
+ Timeout while sending message #{msg}. Possible reasons:
27
+ - #{msg.real_exchange_name} exchange is not found
28
28
  - RabbitMQ is extremely high loaded
29
29
  MESSAGE
30
30
  end
31
31
 
32
- def client
33
- MUTEX.synchronize { @client ||= create_client }
34
- end
35
-
36
- def channel(confirm)
37
- Thread.current[:bunny_channels] ||= {}
38
- channel = Thread.current[:bunny_channels][confirm]
39
- Thread.current[:bunny_channels][confirm] = create_channel(confirm) unless channel&.open?
40
- Thread.current[:bunny_channels][confirm]
32
+ def pool
33
+ MUTEX.synchronize { @pool ||= ChannelsPool.new(create_client) }
41
34
  end
42
35
 
43
36
  private
@@ -47,33 +40,21 @@ module Rabbit
47
40
  end
48
41
 
49
42
  def create_client
50
- return if Rabbit.config.environment == :test
51
-
52
43
  config = Rails.application.config_for("sneakers") rescue {}
53
44
  config = config["bunny_options"].to_h.symbolize_keys
54
45
 
55
- begin
56
- Bunny.new(config).start
57
- rescue
58
- raise unless Rabbit.config.environment == :development
59
- end
60
- end
61
-
62
- def create_channel(confirm)
63
- channel = client.create_channel
64
- channel.confirm_select if confirm
65
- channel
46
+ Bunny.new(config).start
66
47
  end
67
48
 
68
49
  def log(message)
69
50
  @logger ||= Rabbit.config.publish_logger
70
51
 
71
- headers = [
72
- message.real_exchange_name, message.routing_key, message.event,
73
- message.confirm_select? ? "confirm" : "no-confirm"
52
+ metadata = [
53
+ message.real_exchange_name, message.routing_key, message.headers,
54
+ message.event, message.confirm_select? ? "confirm" : "no-confirm"
74
55
  ]
75
56
 
76
- @logger.debug "#{headers.join ' / '}: #{message.data}"
57
+ @logger.debug "#{metadata.join ' / '}: #{message.data}"
77
58
  end
78
59
  end
79
60
  end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rabbit
4
+ module Publishing
5
+ class ChannelsPool
6
+ class BaseQueue < Queue
7
+ def initialize(session, max_size)
8
+ super()
9
+
10
+ @session = session
11
+ @max_size = max_size - 1
12
+ @ch_size = 0
13
+ @create_mon = Mutex.new
14
+ @ch_dec_mon = Mutex.new
15
+ end
16
+
17
+ def pop
18
+ add_channel if size.zero?
19
+
20
+ super
21
+ end
22
+ alias_method :deq, :pop
23
+
24
+ def push(channel)
25
+ return @ch_dec_mon.synchronize { @ch_size -= 1 } unless channel&.open?
26
+
27
+ super
28
+ end
29
+ alias_method :enq, :push
30
+
31
+ def add_channel
32
+ @create_mon.synchronize do
33
+ return unless @ch_size < @max_size
34
+
35
+ push create_channel
36
+ @ch_size += 1
37
+ end
38
+ end
39
+
40
+ protected
41
+
42
+ def create_channel
43
+ @session.create_channel
44
+ end
45
+ end
46
+
47
+ class ConfirmQueue < BaseQueue
48
+ def create_channel
49
+ ch = @session.create_channel
50
+ ch.confirm_select
51
+
52
+ ch
53
+ end
54
+ end
55
+
56
+ def initialize(session)
57
+ max_size = session.channel_max
58
+
59
+ @pools = {
60
+ true => ConfirmQueue.new(session, max_size / 2),
61
+ false => BaseQueue.new(session, max_size / 2),
62
+ }.freeze
63
+ end
64
+
65
+ def with_channel(confirm)
66
+ pool = @pools[confirm]
67
+ ch = pool.deq
68
+ yield ch
69
+ ensure
70
+ pool.enq ch
71
+ end
72
+ end
73
+ end
74
+ end
@@ -6,13 +6,14 @@ module Rabbit::Publishing
6
6
  class Message
7
7
  include Tainbox
8
8
 
9
- attribute :routing_key, String
10
- attribute :event, String
11
- attribute :data, default: {}
12
- attribute :exchange_name, default: []
9
+ attribute :routing_key, String
10
+ attribute :event, String
11
+ attribute :data, default: {}
12
+ attribute :exchange_name, default: []
13
13
  attribute :confirm_select, default: true
14
- attribute :realtime, default: false
14
+ attribute :realtime, default: false
15
15
  attribute :headers
16
+ attribute :message_id
16
17
 
17
18
  alias_method :confirm_select?, :confirm_select
18
19
  alias_method :realtime?, :realtime
@@ -41,6 +42,7 @@ module Rabbit::Publishing
41
42
  content_type: "application/json",
42
43
  app_id: Rabbit.config.app_name,
43
44
  headers: headers,
45
+ message_id: message_id,
44
46
  }
45
47
 
46
48
  [JSON.dump(data), real_exchange_name, routing_key.to_s, options]
@@ -54,8 +56,6 @@ module Rabbit::Publishing
54
56
  [Rabbit.config.group_id, Rabbit.config.project_id, *exchange_name].join(".")
55
57
  end
56
58
 
57
- private
58
-
59
59
  def headers
60
60
  super || {}
61
61
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "lamian"
4
+ require "active_job"
4
5
 
5
6
  require "rabbit"
6
7
  require "rabbit/receiving"
@@ -11,14 +12,12 @@ require "rabbit/receiving/malformed_message"
11
12
  class Rabbit::Receiving::Job < ActiveJob::Base
12
13
  def perform(message, arguments)
13
14
  Lamian.run do
14
- begin
15
- message = Rabbit::Receiving::Message.build(message, arguments)
16
- handler = Rabbit::Receiving::HandlerResolver.handler_for(message)
17
- handler.new(message).call
18
- rescue Rabbit::Receiving::MalformedMessage => error
19
- raise if Rabbit.config.environment == :test
20
- Rabbit.config.exception_notifier.call(error)
21
- end
15
+ message = Rabbit::Receiving::Message.build(message, arguments)
16
+ handler = Rabbit::Receiving::HandlerResolver.handler_for(message)
17
+ handler.new(message).call
18
+ rescue Rabbit::Receiving::MalformedMessage => error
19
+ raise if Rabbit.config.environment == :test
20
+ Rabbit.config.exception_notifier.call(error)
22
21
  end
23
22
  end
24
23
  end
@@ -10,16 +10,23 @@ module Rabbit::Receiving
10
10
 
11
11
  attribute :group_id
12
12
  attribute :project_id
13
+ attribute :message_id
13
14
  attribute :event
14
15
  attribute :data
16
+ attribute :arguments
15
17
  attribute :original_message
16
18
 
17
- attr_accessor :original_message
18
-
19
- def self.build(message, type:, app_id:, **)
20
- group_id, project_id = app_id.split(".")
21
-
22
- new(group_id: group_id, project_id: project_id, event: type, data: message)
19
+ def self.build(message, arguments)
20
+ group_id, project_id = arguments.fetch(:app_id).split(".")
21
+
22
+ new(
23
+ group_id: group_id,
24
+ project_id: project_id,
25
+ event: arguments.fetch(:type),
26
+ data: message,
27
+ message_id: arguments.fetch(:message_id, nil),
28
+ arguments: arguments,
29
+ )
23
30
  end
24
31
 
25
32
  def data=(value)
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rabbit"
4
+ require "rabbit/receiving/message"
5
+ require "rabbit/receiving/handler_resolver"
6
+
7
+ class Rabbit::Receiving::Queue
8
+ attr_reader :message, :arguments, :handler, :queue_name, :ignore_conversion
9
+
10
+ delegate :queue, to: :handler
11
+
12
+ def initialize(raw_message, arguments)
13
+ @message = Rabbit::Receiving::Message.build(raw_message, arguments)
14
+ @handler = Rabbit::Receiving::HandlerResolver.handler_for(message)
15
+ @arguments = arguments
16
+ @queue_name = resolved_queue_name
17
+ @ignore_conversion = handler.ignore_queue_conversion
18
+ end
19
+
20
+ def name
21
+ if queue_name
22
+ calculated_queue_name
23
+ else
24
+ Rabbit.default_queue_name(ignore_conversion: ignore_conversion)
25
+ end
26
+ rescue
27
+ Rabbit.default_queue_name
28
+ end
29
+
30
+ private
31
+
32
+ def resolved_queue_name
33
+ queue.is_a?(Proc) ? queue.call(message, arguments) : queue
34
+ end
35
+
36
+ def calculated_queue_name
37
+ Rabbit.queue_name(queue_name, ignore_conversion: ignore_conversion)
38
+ end
39
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tainbox"
4
+
5
+ require "rabbit"
6
+ require "rabbit/receiving/queue"
7
+ require "rabbit/receiving/job"
8
+
9
+ class Rabbit::Receiving::Receive
10
+ include Tainbox
11
+
12
+ attribute :message
13
+ attribute :delivery_info
14
+ attribute :arguments
15
+
16
+ def call
17
+ log!
18
+ call_hooks(before_hooks)
19
+ process_message
20
+ call_hooks(after_hooks)
21
+ end
22
+
23
+ def log!
24
+ Rabbit.config.receive_logger.debug(
25
+ [message, delivery_info, arguments].join(" / "),
26
+ )
27
+ end
28
+
29
+ def process_message
30
+ job_class
31
+ .set(queue: queue)
32
+ .perform_later(message, message_info)
33
+ end
34
+
35
+ def call_hooks(hooks)
36
+ hooks.each do |hook_proc|
37
+ hook_proc.call(message, message_info)
38
+ end
39
+ end
40
+
41
+ def before_hooks
42
+ Rabbit.config.before_receiving_hooks || []
43
+ end
44
+
45
+ def after_hooks
46
+ Rabbit.config.after_receiving_hooks || []
47
+ end
48
+
49
+ def message_info
50
+ arguments.merge(
51
+ delivery_info.slice(:exchange, :routing_key),
52
+ )
53
+ end
54
+
55
+ def queue
56
+ Rabbit::Receiving::Queue.new(message, arguments).name
57
+ end
58
+
59
+ def job_class
60
+ Rabbit.config.receiving_job_class_callable&.call(
61
+ message: message,
62
+ delivery_info: delivery_info,
63
+ arguments: arguments,
64
+ ) || Rabbit::Receiving::Job
65
+ end
66
+ end
@@ -3,52 +3,30 @@
3
3
  require "sneakers"
4
4
 
5
5
  require "rabbit"
6
- require "rabbit/receiving/message"
7
- require "rabbit/receiving/malformed_message"
8
- require "rabbit/receiving/handler_resolver"
6
+ require "rabbit/receiving/receive"
9
7
 
10
- module Rabbit::Receiving
11
- autoload :Job, "rabbit/receiving/job"
8
+ class Rabbit::Receiving::Worker
9
+ include Sneakers::Worker
12
10
 
13
- class Worker
14
- include Sneakers::Worker
15
-
16
- def self.logger
17
- @logger ||= Rabbit.config.receive_logger
18
- end
19
-
20
- def work_with_params(message, delivery_info, arguments)
21
- message = message.dup.force_encoding("UTF-8")
22
- self.class.logger.debug([message, delivery_info, arguments].join(" / "))
23
- job_class.set(queue: queue(message, arguments)).perform_later(message, arguments.to_h)
24
- ack!
25
- rescue => error
26
- raise if Rabbit.config.environment == :test
27
- Rabbit.config.exception_notifier.call(error)
28
- requeue!
29
- end
30
-
31
- private
32
-
33
- def queue(message, arguments)
34
- message = Rabbit::Receiving::Message.build(message, arguments)
35
- handler = Rabbit::Receiving::HandlerResolver.handler_for(message)
36
- queue_name = handler.queue
37
- ignore_conversion = handler.ignore_queue_conversion
38
-
39
- return Rabbit.default_queue_name(ignore_conversion: ignore_conversion) unless queue_name
40
-
41
- calculated_queue = begin
42
- queue_name.is_a?(Proc) ? queue_name.call(message, arguments) : queue_name
43
- end
11
+ def work_with_params(message, delivery_info, arguments)
12
+ # args and info have custom rabbit classes, have to convert them to hash
13
+ receive_message(message, delivery_info.to_h, arguments.to_h)
14
+ ack!
15
+ rescue => error
16
+ handle_error!(error)
17
+ end
44
18
 
45
- Rabbit.queue_name(calculated_queue, ignore_conversion: ignore_conversion)
46
- rescue
47
- Rabbit.default_queue_name
48
- end
19
+ def receive_message(message, delivery_info, arguments)
20
+ Rabbit::Receiving::Receive.new(
21
+ message: message.dup.force_encoding("UTF-8"),
22
+ delivery_info: delivery_info,
23
+ arguments: arguments,
24
+ ).call
25
+ end
49
26
 
50
- def job_class
51
- Rabbit.config.receiving_job_class_callable&.call || Job
52
- end
27
+ def handle_error!(error)
28
+ raise if Rabbit.config.environment == :test
29
+ Rabbit.config.exception_notifier.call(error)
30
+ requeue!
53
31
  end
54
32
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rabbit
4
- VERSION = "0.7.1"
4
+ VERSION = "0.12.0"
5
5
  end
@@ -5,7 +5,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
  require "rabbit/version"
6
6
 
7
7
  Gem::Specification.new do |spec|
8
- spec.required_ruby_version = ">= 2.3.8"
8
+ spec.required_ruby_version = ">= 2.5"
9
9
 
10
10
  spec.name = "rabbit_messaging"
11
11
  spec.version = Rabbit::VERSION
@@ -22,17 +22,17 @@ Gem::Specification.new do |spec|
22
22
  spec.add_runtime_dependency "bunny", "~> 2.0"
23
23
  spec.add_runtime_dependency "exception_notification"
24
24
  spec.add_runtime_dependency "lamian"
25
- spec.add_runtime_dependency "rails"
25
+ spec.add_runtime_dependency "rails", ">= 5.2"
26
26
  spec.add_runtime_dependency "sneakers", "~> 2.0"
27
27
  spec.add_runtime_dependency "tainbox"
28
28
 
29
29
  spec.add_development_dependency "bundler"
30
30
  spec.add_development_dependency "bundler-audit"
31
- spec.add_development_dependency "coveralls"
32
31
  spec.add_development_dependency "pry"
33
32
  spec.add_development_dependency "rake"
34
33
  spec.add_development_dependency "rspec"
35
34
  spec.add_development_dependency "rspec-its"
36
35
  spec.add_development_dependency "rubocop-config-umbrellio"
37
- spec.add_development_dependency "simplecov"
36
+ spec.add_development_dependency "simplecov", ">= 0.21"
37
+ spec.add_development_dependency "simplecov-lcov"
38
38
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rabbit_messaging
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Umbrellio
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-09 00:00:00.000000000 Z
11
+ date: 2021-06-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bunny
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: '5.2'
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: '0'
68
+ version: '5.2'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: sneakers
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -123,7 +123,7 @@ dependencies:
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
125
  - !ruby/object:Gem::Dependency
126
- name: coveralls
126
+ name: pry
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - ">="
@@ -137,7 +137,7 @@ dependencies:
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
139
  - !ruby/object:Gem::Dependency
140
- name: pry
140
+ name: rake
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
143
  - - ">="
@@ -151,7 +151,7 @@ dependencies:
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0'
153
153
  - !ruby/object:Gem::Dependency
154
- name: rake
154
+ name: rspec
155
155
  requirement: !ruby/object:Gem::Requirement
156
156
  requirements:
157
157
  - - ">="
@@ -165,7 +165,7 @@ dependencies:
165
165
  - !ruby/object:Gem::Version
166
166
  version: '0'
167
167
  - !ruby/object:Gem::Dependency
168
- name: rspec
168
+ name: rspec-its
169
169
  requirement: !ruby/object:Gem::Requirement
170
170
  requirements:
171
171
  - - ">="
@@ -179,7 +179,7 @@ dependencies:
179
179
  - !ruby/object:Gem::Version
180
180
  version: '0'
181
181
  - !ruby/object:Gem::Dependency
182
- name: rspec-its
182
+ name: rubocop-config-umbrellio
183
183
  requirement: !ruby/object:Gem::Requirement
184
184
  requirements:
185
185
  - - ">="
@@ -193,21 +193,21 @@ dependencies:
193
193
  - !ruby/object:Gem::Version
194
194
  version: '0'
195
195
  - !ruby/object:Gem::Dependency
196
- name: rubocop-config-umbrellio
196
+ name: simplecov
197
197
  requirement: !ruby/object:Gem::Requirement
198
198
  requirements:
199
199
  - - ">="
200
200
  - !ruby/object:Gem::Version
201
- version: '0'
201
+ version: '0.21'
202
202
  type: :development
203
203
  prerelease: false
204
204
  version_requirements: !ruby/object:Gem::Requirement
205
205
  requirements:
206
206
  - - ">="
207
207
  - !ruby/object:Gem::Version
208
- version: '0'
208
+ version: '0.21'
209
209
  - !ruby/object:Gem::Dependency
210
- name: simplecov
210
+ name: simplecov-lcov
211
211
  requirement: !ruby/object:Gem::Requirement
212
212
  requirements:
213
213
  - - ">="
@@ -227,12 +227,13 @@ executables: []
227
227
  extensions: []
228
228
  extra_rdoc_files: []
229
229
  files:
230
+ - ".github/workflows/test.yml"
230
231
  - ".gitignore"
231
232
  - ".rspec"
232
233
  - ".rubocop.yml"
233
- - ".travis.yml"
234
234
  - CHANGELOG.md
235
235
  - Gemfile
236
+ - Gemfile.lock
236
237
  - LICENSE.md
237
238
  - README.md
238
239
  - Rakefile
@@ -244,6 +245,7 @@ files:
244
245
  - lib/rabbit/event_handler.rb
245
246
  - lib/rabbit/extensions/bunny/channel.rb
246
247
  - lib/rabbit/publishing.rb
248
+ - lib/rabbit/publishing/channels_pool.rb
247
249
  - lib/rabbit/publishing/job.rb
248
250
  - lib/rabbit/publishing/message.rb
249
251
  - lib/rabbit/receiving.rb
@@ -251,6 +253,8 @@ files:
251
253
  - lib/rabbit/receiving/job.rb
252
254
  - lib/rabbit/receiving/malformed_message.rb
253
255
  - lib/rabbit/receiving/message.rb
256
+ - lib/rabbit/receiving/queue.rb
257
+ - lib/rabbit/receiving/receive.rb
254
258
  - lib/rabbit/receiving/worker.rb
255
259
  - lib/rabbit/test_helpers.rb
256
260
  - lib/rabbit/version.rb
@@ -259,7 +263,7 @@ files:
259
263
  homepage: https://github.com/umbrellio/rabbit_messaging
260
264
  licenses: []
261
265
  metadata: {}
262
- post_install_message:
266
+ post_install_message:
263
267
  rdoc_options: []
264
268
  require_paths:
265
269
  - lib
@@ -267,15 +271,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
267
271
  requirements:
268
272
  - - ">="
269
273
  - !ruby/object:Gem::Version
270
- version: 2.3.8
274
+ version: '2.5'
271
275
  required_rubygems_version: !ruby/object:Gem::Requirement
272
276
  requirements:
273
277
  - - ">="
274
278
  - !ruby/object:Gem::Version
275
279
  version: '0'
276
280
  requirements: []
277
- rubygems_version: 3.1.2
278
- signing_key:
281
+ rubygems_version: 3.2.17
282
+ signing_key:
279
283
  specification_version: 4
280
284
  summary: Rabbit (Rabbit Messaging)
281
285
  test_files: []
data/.travis.yml DELETED
@@ -1,19 +0,0 @@
1
- language: ruby
2
- matrix:
3
- fast_finish: true
4
- include:
5
- - rvm: 2.3
6
- - rvm: 2.4
7
- - rvm: 2.5
8
- - rvm: 2.6
9
- - rvm: ruby-head
10
- allow_failures:
11
- - rvm: ruby-head
12
- sudo: false
13
- cache: bundler
14
- before_install: gem install bundler
15
- script:
16
- - mkdir log
17
- - bundle exec rake bundle:audit
18
- - bundle exec rubocop
19
- - bundle exec rspec