rabbit_messaging 0.7.1 → 0.12.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: 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