queues-rabbit 0.1.0.beta

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.
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