queues-rabbit 0.1.0.beta

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,456 @@
1
+ # <img src="https://user-images.githubusercontent.com/50866745/156147715-d3773642-68c0-48c0-92ad-0ccc442ee881.svg" width="48"> Rails-Queues Rabbit
2
+ ![](https://img.shields.io/static/v1?label=Language&message=Ruby&color=red)
3
+ ![](https://img.shields.io/static/v1?label=Latest&message=0.1.0.beta&color=blue)
4
+
5
+ A Rails implementation of [RabbitMQ](https://www.rabbitmq.com/)
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'queues-rabbit'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ ```
18
+ bundle install
19
+ ```
20
+
21
+ ## Getting Started
22
+
23
+ The gem gets shipped with a scaffolding generator.
24
+
25
+ ```
26
+ rails generate queues_rabbit
27
+ ```
28
+
29
+ ## Table of contents
30
+
31
+ * [Architecture](#architecture)
32
+ * [Rails Queues](#rails-queues)
33
+ * [Schema](#schema)
34
+ * [Queues](#queues)
35
+ * [Definition](#queue-definition)
36
+ * [Subscribing](#subscribing-a-queue)
37
+ * [Publishing](#publishing-to-queues)
38
+ * [Purge](#purge-a-queue)
39
+ * [Delete](#delete-a-queue)
40
+ * [Exchanges](#exchanges)
41
+ * [Definition](#exchange-definition)
42
+ * [Queue Binding](#queue-binding)
43
+ * [Queue Unbinding](#queue-unbinding)
44
+ * [Exchange Binding](#exchange-binding)
45
+ * [Exchange Unbinding](#exchange-unbinding)
46
+ * [Publishing](#publishing-to-an-exchange)
47
+ * [Delete](#delete-an-exchange)
48
+ * [Logging](#logging)
49
+ * [Usage Tips](#usage-tips)
50
+
51
+
52
+ ## Architecture
53
+
54
+ The framework consists of a Schema where you can register your RabbitMQ Queues and Exchanges.
55
+
56
+ ```
57
+ app
58
+ └── queues
59
+ ├── application_queue.rb
60
+ └── rabbit
61
+ ├── exchanges
62
+ │   └── my_exchange.rb
63
+ ├── queues
64
+ │   └── my_queue.rb
65
+ └── schema.rb
66
+ ```
67
+
68
+ ## Rails-Queues
69
+
70
+ The gem belongs to the [Rails-Queues](https://github.com/LapoElisacci/queues) framework.
71
+
72
+ To initialize your RabbitMQ schema, add it to the `ApplicationQueue` class.
73
+
74
+ ```Ruby
75
+ class ApplicationQueue < Queues::API
76
+ rabbit Rabbits::Schema, 'amqp://guest:guest@localhost'
77
+ end
78
+ ```
79
+
80
+ You can have as many RabbitMQ instances to connect to as you want.
81
+
82
+ Each RabbitMQ instance must be attached to a specific Schema.
83
+
84
+ ```Ruby
85
+ class ApplicationQueue < Queues::API
86
+ rabbit Rabbits::SchemaOne, 'amqp://guest:guest@localhost1'
87
+ rabbit Rabbits::SchemaTwo, 'amqp://guest:guest@localhost2'
88
+ end
89
+ ```
90
+
91
+ ## Schema
92
+
93
+ The Schema allows you to regiter both the queues and the exchanges.
94
+
95
+ ```Ruby
96
+ module Rabbits
97
+ class Schema < ::Queues::Rabbit::Schema
98
+ queue Rabbits::Queues::MyQueue
99
+ exchange Rabbits::Queues::MyExchange
100
+ end
101
+ end
102
+ ```
103
+
104
+ You can register as many queues and exchanges as you need.
105
+
106
+ ```Ruby
107
+ module Rabbits
108
+ class Schema < ::Queues::Rabbit::Schema
109
+ queue Rabbits::Queues::MyQueueOne
110
+ exchange Rabbits::Queues::MyExchangeOne
111
+
112
+ queue Rabbits::Queues::MyQueueTwo
113
+ exchange Rabbits::Queues::MyExchangeTwo
114
+ end
115
+ end
116
+ ```
117
+
118
+ ## Queues
119
+
120
+ Each queue can be declared by a class that inherits from `Queues::Rabbit::Queue`
121
+
122
+ ### Queue Definition
123
+
124
+ ```Ruby
125
+ module Rabbits
126
+ module Queues
127
+ class MyQueue < ::Queues::Rabbit::Queue
128
+ queue 'my.queue',
129
+ auto_ack: true,
130
+ auto_delete: false,
131
+ durable: true,
132
+ prefetch: 1,
133
+ arguments: {}
134
+
135
+ # ...
136
+ end
137
+ end
138
+ end
139
+ ```
140
+
141
+ The `queue` method allows you to define the RabbitMQ queue parameters.
142
+
143
+ - The queue name
144
+ - **auto_ack:** When false messages have to be manually acknowledged (or rejected)
145
+ - **auto_delete:** If true, the queue will be deleted when the last consumer stops consuming.
146
+ - **durable:** If true, the queue will survive broker restarts, messages in the queue will only survive if they are published as persistent.
147
+ - **prefetch:** Specify how many messages to prefetch for consumers (with no_ack is false)
148
+ - **arguments:** Custom arguments, such as queue-ttl etc.
149
+
150
+ Params **durable**, **auto_delete** and **arguments** are optional, default values are:
151
+ - **durable:** true
152
+ - **auto_delete:** false
153
+ - **arguments:** {}
154
+
155
+ (Remember to register the queue class to the Schema, more details [here](#schema))
156
+
157
+ ### Subscribing a queue
158
+
159
+ To compute a message when it gets received, define a method called `consume` inside your queue Class, like so:
160
+
161
+ ```Ruby
162
+ module Rabbits
163
+ module Queues
164
+ class MyQueue < ::Queues::Rabbit::Queue
165
+ queue 'my.queue',
166
+ auto_ack: true,
167
+ auto_delete: false,
168
+ durable: true,
169
+ prefetch: 1,
170
+ arguments: {}
171
+
172
+ def consume(message)
173
+ # do something with the message
174
+ end
175
+ end
176
+ end
177
+ end
178
+ ```
179
+
180
+ The messange param is a `Queues::Rabbit::Message` instance where you can access the following properties:
181
+
182
+ - **body:** The message body.
183
+ - **consumer_tag:** The RabbitMQ consumer associated tag.
184
+ - **delivery_tag:** The RabbitMQ delivery tag.
185
+ - **exchange:** The exchange name (Empty for default exchange).
186
+
187
+ The `Queues::Rabbit::Message` also implements a few interesting methods:
188
+
189
+ - **ack:** Allows you to manually acknoledge the message (When **auto_ack** is set to **false**)
190
+ - **reject:** Allows you to manually reject a message (it accepts an argument **requeue** that if true the message will be put back into the queue)
191
+
192
+ ```Ruby
193
+ module Rabbits
194
+ module Queues
195
+ class MyQueue < ::Queues::Rabbit::Queue
196
+ queue 'my.queue',
197
+ auto_ack: false,
198
+
199
+ def consume(message)
200
+ puts message.body
201
+ message.ack
202
+ rescue
203
+ message.reject(requeue: false)
204
+ end
205
+ end
206
+ end
207
+ end
208
+ ```
209
+
210
+ ### WARNING
211
+
212
+ The **consume** method will get executed inside a separated thread, make sure it's threadsafe!
213
+
214
+ After defining the **consume** method, to subscribe the queue call the, call the **subscribe** method, like so:
215
+
216
+ ```Ruby
217
+ Rabbits::Queues::MyQueue.subscribe
218
+ ```
219
+
220
+ The method won't return until the connection gets closed.
221
+ Aliveness logs will get printed to **STDOUT**.
222
+
223
+ ### Publishing to queues
224
+
225
+ To publish a message into a declared queue, call the **publish** method:
226
+
227
+ ```Ruby
228
+ Rabbits::Queues::MyQueue.publish({ foo: 'bar' }.to_json, content_type: 'application/json')
229
+ ```
230
+
231
+ The **publish** method accepts several options, here's the method documentation:
232
+
233
+ ```Ruby
234
+ # @param [String] body The message body, can be a string or either a byte array
235
+ # @param [Hash] properties Request properties
236
+ # @option properties [String] :app_id Used to identify the app that generated the message
237
+ # @option properties [String] :content_encoding Content encoding of the body
238
+ # @option properties [String] :content_type Content type of the body
239
+ # @option properties [Integer] :correlation_id The correlation id, mostly used used for RPC communication
240
+ # @option properties [Integer] :delivery_mode 2 for persistent messages, all other values are for transient messages
241
+ # @option properties [Integer, String] :expiration Number of seconds the message will stay in the queue
242
+ # @option properties [Hash<String, Object>] :headers Custom headers
243
+ # @option properties [Boolean] :mandatory The message will be returned if the message can't be routed to a queue
244
+ # @option properties [String] :message_id Can be used to uniquely identify the message, e.g. for deduplication
245
+ # @option properties [Boolean] :persistent Same as delivery_mode: 2
246
+ # @option properties [Integer] :priority The message priority (between 0 and 255)
247
+ # @option properties [String] :reply_to Queue to reply RPC responses to
248
+ # @option properties [Date] :timestamp Often used for the time the message was originally generated
249
+ # @option properties [String] :type Can indicate what kind of message this is
250
+ # @option properties [String] :user_id Used to identify the user that published the message
251
+ #
252
+ # @return [Boolean] true if published, false otherwise
253
+ #
254
+ def publish(body, **properties)
255
+ ```
256
+
257
+ ### Purge a queue
258
+
259
+ To purge all messages from a defined queue, call the **purge** method, like so:
260
+
261
+ ```Ruby
262
+ Rabbits::Queues::MyQueue.purge
263
+ ```
264
+
265
+ ### Delete a queue
266
+
267
+ To delete a queue from RabbitMQ, call the **delete** method, like so:
268
+
269
+ ```Ruby
270
+ Rabbits::Queues::MyQueue.delete
271
+ ```
272
+
273
+ ## Exchanges
274
+
275
+ Just like queues, exchanges must be declared by a class that inherits, this time, from `Queues::Rabbit::Exchange`
276
+
277
+ ### Exchange Definition
278
+
279
+ ```Ruby
280
+ module Rabbits
281
+ module Exchanges
282
+ class MyExchange < ::Queues::Rabbit::Exchange
283
+ exchange 'my.exchange', 'direct',
284
+ auto_delete: false,
285
+ durable: true,
286
+ internal: false,
287
+ arguments: {}
288
+ end
289
+ end
290
+ end
291
+ ```
292
+
293
+ The `exchange` method allows you to define the exchange parameters.
294
+
295
+ - The exchange name
296
+ - The exchange type ('direct', 'fanout', 'headers', 'topic' ...)
297
+ - **auto_delete:** If true, the exchange will be deleted when the last queue/exchange gets unbounded.
298
+ - **durable:** If true, the exchange will persist between broker restarts, also a required for persistent messages.
299
+ - **internal:** If true, the messages can't be pushed directly to the exchange.
300
+ - **arguments:** Custom exchange arguments.
301
+
302
+ (Remember to register the exchange class to the Schema, more details [here](#schema))
303
+
304
+ ### Queue binding
305
+
306
+ To bind a queue to an exchange, call the **bind** method inside the queue class, like so:
307
+
308
+ ```Ruby
309
+ module Rabbits
310
+ module Queues
311
+ class MyQueue < ::Queues::Rabbit::Queue
312
+ queue 'my.queue',
313
+ auto_ack: true,
314
+ auto_delete: false,
315
+ durable: true,
316
+ prefetch: 1,
317
+ arguments: {}
318
+
319
+ bind Rabbits::Exchanges::MyExchange, 'my.binding.key', arguments: {}
320
+
321
+ # ...
322
+ end
323
+ end
324
+ end
325
+ ```
326
+
327
+ You can also statically declare the exchange name, like so:
328
+
329
+ ```Ruby
330
+ bind 'my.exchange', 'my.binding.key', arguments: {}
331
+ ```
332
+
333
+ The `bind` method allows you to define the queue-exchange binding parameters.
334
+
335
+ - The exchange name
336
+ - The binding key
337
+ - **arguments:** Message headers to match on (only relevant for header exchanges)
338
+
339
+ ### Queue unbinding
340
+
341
+ To unbind a queue from an exchange call the **unbind** method, like so:
342
+
343
+ ```Ruby
344
+ Rabbits::Queues::MyQueue.unbind(Rabbits::Exchanges::MyExchange, 'my.binding.key', arguments: {})
345
+ ```
346
+
347
+ or
348
+
349
+ ```Ruby
350
+ Rabbits::Queues::MyQueue.unbind('my.exchange', 'my.binding.key', arguments: {})
351
+ ```
352
+
353
+ ### Exchange binding
354
+
355
+ To bind an exchange to another exchange, call the **bind** method inside the exchange class, like so:
356
+
357
+ ```Ruby
358
+ module Rabbits
359
+ module Exchanges
360
+ class MyExchange < ::Queues::Rabbit::Exchange
361
+ exchange 'my.exchange', 'direct',
362
+ auto_delete: false,
363
+ durable: true,
364
+ internal: false,
365
+ arguments: {}
366
+
367
+ bind Rabbits::Exchanges::MyExchangeTwo, 'my.binding.key', arguments: {}
368
+ end
369
+ end
370
+ end
371
+ ```
372
+
373
+ ### Exchange unbinding
374
+
375
+ To unbind an exchange from another exchange call the **unbind** method, like so:
376
+
377
+ ```Ruby
378
+ Rabbits::Exchanges::MyExchange.unbind(Rabbits::Exchanges::MyExchangeTwo, 'my.binding.key', arguments: {})
379
+ ```
380
+
381
+ or
382
+
383
+ ```Ruby
384
+ Rabbits::Exchanges::MyExchange.unbind('my.exchange.two', 'my.binding.key', arguments: {})
385
+ ```
386
+
387
+ ### Publishing to an exchange
388
+
389
+ To publish a message to an exchange call the **publish** method, like so:
390
+
391
+ ```Ruby
392
+ Rabbits::Exchanges::MyExchange.publish('my message', 'my.routing.key', properties: {})
393
+ ```
394
+
395
+ The **publish** method accepts several options, here's the method documentation:
396
+
397
+ ```Ruby
398
+ # @param [String] body The message body, can be a string or either a byte array
399
+ # @param [String] routing_key The routing key to route the message to bounded queues
400
+ # @param [Hash] properties Request properties
401
+ # @option properties [String] :app_id Used to identify the app that generated the message
402
+ # @option properties [String] :content_encoding Content encoding of the body
403
+ # @option properties [String] :content_type Content type of the body
404
+ # @option properties [Integer] :correlation_id The correlation id, mostly used used for RPC communication
405
+ # @option properties [Integer] :delivery_mode 2 for persistent messages, all other values are for transient messages
406
+ # @option properties [Integer, String] :expiration Number of seconds the message will stay in the queue
407
+ # @option properties [Hash<String, Object>] :headers Custom headers
408
+ # @option properties [Boolean] :mandatory The message will be returned if the message can't be routed to a queue
409
+ # @option properties [String] :message_id Can be used to uniquely identify the message, e.g. for deduplication
410
+ # @option properties [Boolean] :persistent Same as delivery_mode: 2
411
+ # @option properties [Integer] :priority The message priority (between 0 and 255)
412
+ # @option properties [String] :reply_to Queue to reply RPC responses to
413
+ # @option properties [Date] :timestamp Often used for the time the message was originally generated
414
+ # @option properties [String] :type Can indicate what kind of message this is
415
+ # @option properties [String] :user_id Used to identify the user that published the message
416
+ #
417
+ # @return [Boolean] true if published, false otherwise
418
+ #
419
+ def publish(body, routing_key, **properties)
420
+ ```
421
+
422
+ ### Delete an exchange
423
+
424
+ To delete an exchange from RabbitMQ call the **delete** method, like so:
425
+
426
+ ```Ruby
427
+ Rabbits::Exchanges::MyExchange.delete
428
+ ```
429
+
430
+ ## Logging
431
+
432
+ Queues and Exchanges have a built-in logger.
433
+
434
+ Each queue and each exchange will have its log file inside the `log` directory. The filename will match the queue/exchange name.
435
+
436
+ While [consuming messages from a queue](#subscribing-a-queue), logs will also get pushed to `STDOUT`.
437
+
438
+ ## Usage tips
439
+
440
+ A good way to implement queues subscription is to use [Rails runners](https://guides.rubyonrails.org/command_line.html#bin-rails-runner) to spawn a specific process for each connection.
441
+
442
+ ```Bash
443
+ rails runner -e production "Rabbits::Queues::MyQueue.subscribe"
444
+ ```
445
+
446
+ ## Contributing
447
+
448
+ Bug reports and pull requests are welcome on GitHub at https://github.com/LapoElisacci/queues-rabbit.
449
+
450
+ ## Credits
451
+
452
+ The gem is based on the amazing RabbitMQ client by [cloudamqp](https://github.com/cloudamqp/amqp-client.rb).
453
+
454
+ ## License
455
+
456
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[spec rubocop]
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+
5
+ # Creates the Queues initializer file for Rails apps.
6
+ #
7
+ # @example Invokation from terminal
8
+ # rails generate queues_rabbit
9
+ #
10
+ class QueuesRabbitGenerator < Rails::Generators::Base
11
+ desc "Description:\n This prepares Rails for RabbitMQ Queues"
12
+
13
+ source_root File.expand_path('templates', __dir__)
14
+
15
+ desc 'Initialize Rails for RabbitMQ Queues'
16
+
17
+ def generate_layout
18
+ if !File.exist?('app/queues/application_queue.rb')
19
+ generate 'queues'
20
+ end
21
+
22
+ template 'schema.rb', 'app/queues/rabbits/schema.rb'
23
+ template 'queue.rb', 'app/queues/rabbits/queues/my_queue.rb'
24
+ template 'exchange.rb', 'app/queues/rabbits/exchanges/my_exchange.rb'
25
+ end
26
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rabbits
4
+ module Exchanges
5
+ class MyExchange < ::Queues::Rabbit::Exchange
6
+ exchange 'my.exchange', 'direct', # Required
7
+ durable: true, # Optional
8
+ auto_delete: false, # Optional
9
+ internal: false, # Optional
10
+ arguments: {} # Optional
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rabbits
4
+ module Queues
5
+ class MyQueue < ::Queues::Rabbit::Queue
6
+ queue 'my.queue', # Required
7
+ auto_ack: false, # Optional
8
+ auto_delete: false, # Optional
9
+ durable: true, # Optional
10
+ prefetch: 1, # Optional
11
+ arguments: {} # Optional
12
+
13
+ def consume(message)
14
+ # do something with the message
15
+ message.ack
16
+ rescue
17
+ message.reject(requeue: false)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rabbits
4
+ class Schema < ::Queues::Rabbit::Schema
5
+ queue Rabbits::Queues::MyQueue
6
+ exchange Rabbits::Exchanges::MyExchange
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Queues
4
+ module Rabbit
5
+ class Client < AMQP::Client; end
6
+ end
7
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Queues
4
+ module Rabbit
5
+ class Exchange
6
+ class << self
7
+ attr_accessor :arguments, :auto_delete, :durable, :internal, :name, :schema, :type
8
+
9
+ def bind(exchange, binding_key, arguments: {})
10
+ exchange = exchange < Queues::Rabbit::Exchange ? exchange.name : exchange
11
+ exchange_instance.bind(exchange, binding_key, arguments: arguments)
12
+ true
13
+ rescue Exception => e
14
+ logger.error_with_report "Unable to bind '#{name}' to '#{exchange}' with key '#{binding_key}' and arguments: '#{arguments}': #{e.message}."
15
+ false
16
+ end
17
+
18
+ def delete
19
+ exchange_instance.delete
20
+ true
21
+ rescue Exception => e
22
+ logger.error_with_report "Unable to delete #{name}: #{e.message}."
23
+ false
24
+ end
25
+
26
+ def exchange(name, type, arguments: {}, auto_delete: false, durable: true, internal: false)
27
+ self.arguments = arguments
28
+ self.auto_delete = auto_delete
29
+ self.name = name
30
+ self.durable = durable
31
+ self.internal = internal
32
+ self.name = name
33
+ self.type = type
34
+ self
35
+ end
36
+
37
+ def exchange_instance
38
+ @@exchange_instance ||= schema.client_instance.exchange(name, type, arguments: arguments, auto_delete: auto_delete, durable: durable, internal: internal)
39
+ end
40
+
41
+ def logger
42
+ @@logger ||= Queues::Rabbit::Logger.new(name, Queues::Rabbit.log_level)
43
+ end
44
+
45
+ #
46
+ # <Description>
47
+ #
48
+ # @param [String] body The message body, can be a string or either a byte array
49
+ # @param [String] routing_key The routing key to route the message to bounded queues
50
+ # @param [Hash] properties Request properties
51
+ # @option properties [String] :app_id Used to identify the app that generated the message
52
+ # @option properties [String] :content_encoding Content encoding of the body
53
+ # @option properties [String] :content_type Content type of the body
54
+ # @option properties [Integer] :correlation_id The correlation id, mostly used used for RPC communication
55
+ # @option properties [Integer] :delivery_mode 2 for persistent messages, all other values are for transient messages
56
+ # @option properties [Integer, String] :expiration Number of seconds the message will stay in the queue
57
+ # @option properties [Hash<String, Object>] :headers Custom headers
58
+ # @option properties [Boolean] :mandatory The message will be returned if the message can't be routed to a queue
59
+ # @option properties [String] :message_id Can be used to uniquely identify the message, e.g. for deduplication
60
+ # @option properties [Boolean] :persistent Same as delivery_mode: 2
61
+ # @option properties [Integer] :priority The message priority (between 0 and 255)
62
+ # @option properties [String] :reply_to Queue to reply RPC responses to
63
+ # @option properties [Date] :timestamp Often used for the time the message was originally generated
64
+ # @option properties [String] :type Can indicate what kind of message this is
65
+ # @option properties [String] :user_id Used to identify the user that published the message
66
+ #
67
+ # @return [Boolean] true if published, false otherwise
68
+ #
69
+ def publish(body, routing_key, **properties)
70
+ exchange_instance.publish(body, name, routing_key, **properties)
71
+ true
72
+ rescue Exception => e
73
+ logger.error_with_report "Unable to publish to #{name}: #{e.message}."
74
+ false
75
+ end
76
+
77
+ def unbind(exchange, binding_key, arguments: {})
78
+ exchange = exchange < Queues::Rabbit::Exchange ? exchange.name : exchange
79
+ exchange_instance.unbind(exchange, binding_key, arguments: arguments)
80
+ true
81
+ rescue Exception => e
82
+ logger.error_with_report "Unable to unbind '#{name}' to '#{exchange}' with key '#{binding_key}' and arguments: '#{arguments}': #{e.message}."
83
+ false
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_litteral: true
2
+
3
+ module Queues
4
+ module Rabbit
5
+ class Logger
6
+ delegate :unknown, :fatal, :error, :warn, :info, :debug, to: :@logger
7
+
8
+ def initialize(name, level)
9
+ @logger = ::Logger.new("log/#{name}.log")
10
+ @logger.level = level
11
+ @std = ::Logger.new(STDOUT)
12
+ @std.level = ::Logger::INFO
13
+ end
14
+
15
+ def error_with_report(message)
16
+ @logger.error { message }
17
+ @logger.error { 'Please report to https://github.com/LapoElisacci/queues-rabbit if needed.' }
18
+ end
19
+
20
+ def stdout(message, level = :info)
21
+ @std.send(level, message)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Queues
4
+ module Rabbit
5
+ class Message < AMQP::Client::Message
6
+ def initialize(message)
7
+ message.instance_variables.each do |variable|
8
+ instance_variable_set(variable, message.instance_variable_get(variable))
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end