message_queue 0.0.4 → 0.1.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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +87 -2
  3. data/examples/{publisher.rb → producer.rb} +4 -3
  4. data/examples/producible_consumable.rb +28 -0
  5. data/lib/message_queue/adapter.rb +4 -0
  6. data/lib/message_queue/adapters/bunny/connection.rb +26 -28
  7. data/lib/message_queue/adapters/bunny/consumer.rb +21 -11
  8. data/lib/message_queue/adapters/bunny/{publisher.rb → producer.rb} +12 -12
  9. data/lib/message_queue/adapters/memory/connection.rb +12 -0
  10. data/lib/message_queue/adapters/memory/consumer.rb +34 -0
  11. data/lib/message_queue/adapters/memory/producer.rb +11 -0
  12. data/lib/message_queue/adapters/memory.rb +11 -0
  13. data/lib/message_queue/connection.rb +64 -0
  14. data/lib/message_queue/consumable.rb +83 -0
  15. data/lib/message_queue/consumable_runner.rb +28 -0
  16. data/lib/message_queue/consumer.rb +18 -0
  17. data/lib/message_queue/error_handlers/airbrake.rb +19 -0
  18. data/lib/message_queue/error_handlers/logger.rb +16 -0
  19. data/lib/message_queue/logging.rb +30 -0
  20. data/lib/message_queue/message.rb +14 -0
  21. data/lib/message_queue/options_helper.rb +26 -0
  22. data/lib/message_queue/producer.rb +29 -0
  23. data/lib/message_queue/producible.rb +49 -0
  24. data/lib/message_queue/rails.rb +19 -0
  25. data/lib/message_queue/serializer.rb +4 -0
  26. data/lib/message_queue/serializers/json.rb +4 -0
  27. data/lib/message_queue/serializers/message_pack.rb +4 -0
  28. data/lib/message_queue/serializers/plain.rb +4 -0
  29. data/lib/message_queue/version.rb +1 -1
  30. data/lib/message_queue.rb +118 -1
  31. data/test/adapters/bunny_test.rb +47 -32
  32. data/test/adapters/memory_test.rb +26 -0
  33. data/test/consumable_test.rb +45 -0
  34. data/test/message_queue_test.rb +22 -0
  35. data/test/options_helper_test.rb +23 -0
  36. data/test/producible_test.rb +41 -0
  37. data/test/support/message_queue.yml +1 -0
  38. metadata +29 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 69c5d3a42305c245b66001e3f1eb926db2e79d79
4
- data.tar.gz: 67afed64dc220d8d9853dc608c5affc0c6e5fb1e
3
+ metadata.gz: 6e91039cfe1a4655089a9d9fe51b6f5f40ac0040
4
+ data.tar.gz: 399c152cae5cb9af53a1831bf6f7e9b86c0ff3f9
5
5
  SHA512:
6
- metadata.gz: 17ad92ad1ca7187ec5ad36da7c1ce51e8b835b6e4d85693ab26f6cc0cea6af3b0de60f6dace19c2c30a5cac5dfaed8d8130278a6eb8831414d45ee569420001d
7
- data.tar.gz: 2b6ba6e40c26fd2be1939b0593f911ba942fd640cd3a763c11c5606756cc53ea2996de3d7c7e68baaa5757a661ba8156e59953f92332e06025765a2cc5fa6e85
6
+ metadata.gz: 41fd54adc323d25ee56b597da2c8b25b8cd72177af4fae1d9f79b31412e953caf1c5d738c0f767fe684cd758bc6902f93d8f8f30fd7da1849c05dadf19d71f13
7
+ data.tar.gz: 62e935dde186e86ee8c0df12ae81d8e82b7e40e0ae0a35323d9f040c99f827291d054bff14f74c3da425f4f0f402d3c80643a90ed55d83e260bde7642f30ca56
data/README.md CHANGED
@@ -18,9 +18,15 @@ Or install it yourself as:
18
18
 
19
19
  ## Usage
20
20
 
21
+ ### with_connection
22
+
23
+ `with_connection` initializes a connection using the specified adapter
24
+ and serializer, connects to the message queue, runs a block of code and
25
+ disconnects.
26
+
21
27
  ```ruby
22
28
  MessageQueue.with_connection(:adapter => :bunny, :serializer => :message_pack) do |conn|
23
- publisher = conn.new_publisher(
29
+ producer = conn.new_producer(
24
30
  :exchange => {
25
31
  :name => "time",
26
32
  :type => :topic
@@ -44,16 +50,95 @@ MessageQueue.with_connection(:adapter => :bunny, :serializer => :message_pack) d
44
50
  puts "Received message: #{payload}"
45
51
  end
46
52
 
47
- publisher.publish Time.now.to_s
53
+ producer.publish Time.now.to_s
48
54
 
49
55
  sleep 1
50
56
  end
51
57
  ```
52
58
 
59
+ You could maintain a global connection by using the `connect` method on
60
+ `MessageQueue`.
61
+
62
+ ```ruby
63
+ MessageQueue.connect(:adater => :bunny, :serializer => :json)
64
+ puts MessageQueue.connected? # => true
65
+
66
+ producer = MessageQueue.new_producer(
67
+ :exchange => {
68
+ :name => "time",
69
+ :type => :topic
70
+ },
71
+ :message => {
72
+ :routing_key => "time.now"
73
+ }
74
+ )
75
+
76
+ consumer = MessageQueue.new_consumer(
77
+ :queue => {
78
+ :name => "print_time_now"
79
+ },
80
+ :exchange => {
81
+ :name => "time",
82
+ :routing_key => "time.#"
83
+ }
84
+ )
85
+
86
+ consumer.subscribe do |delivery_info, metadata, payload|
87
+ puts "Received message: #{payload}"
88
+ end
89
+
90
+ producer.publish Time.now.to_s
91
+
92
+ sleep 1
93
+
94
+ MessageQueue.disconnect
95
+ puts MessageQueue.connected? # => false
96
+ ```
97
+
98
+ You could also mix in the `MessageQueue::Producible` module and the
99
+ `MessageQueue::Consumable` module to your producer class and consumer
100
+ class respectively. The consumer class needs to implement a `process`
101
+ method which will be passed a `MessageQueue::Message` instance when it
102
+ receives a message.
103
+
104
+ ```ruby
105
+ class Producer
106
+ include MessageQueue::Producible
107
+
108
+ exchange :name => "time", :type => :topic
109
+ message :routing_key => "time.now", :mandatory => true
110
+ end
111
+
112
+ class Consumer
113
+ include MessageQueue::Consumable
114
+
115
+ queue :name => "print_time_now"
116
+ exchange :name => "time", :routing_key => "time.#"
117
+
118
+ def process(message)
119
+ puts "Received message #{message.payload}"
120
+ end
121
+ end
122
+
123
+ MessageQueue.connect(:adater => :bunny, :serializer => :json)
124
+ Producer.new.publish(Time.now.to_s)
125
+
126
+ sleep 1
127
+
128
+ MessageQueue.disconnect
129
+ ```
130
+
53
131
  ## Examples
54
132
 
55
133
  See [examples](https://github.com/jingweno/message_queue/tree/master/examples).
56
134
 
135
+ ## Rails
136
+
137
+ For Rails, `message_queue` automatically loads settings from
138
+ `RAILS_ROOT/config/message_queue.yml`. If the file doesn't exist, it
139
+ initializes the queue in
140
+ [memory](https://github.com/jingweno/message_queue/tree/master/lib/message_queue/adapters/memory) mode.
141
+
57
142
  ## Contributing
58
143
 
59
144
  1. Fork it
@@ -1,15 +1,16 @@
1
1
  require_relative "../lib/message_queue"
2
2
 
3
3
  MessageQueue.with_connection(:adapter => :bunny, :serializer => :message_pack) do |conn|
4
- publisher = conn.new_publisher(
4
+ producer = conn.new_producer(
5
5
  :exchange => {
6
6
  :name => "time",
7
7
  :type => :topic
8
8
  },
9
9
  :message => {
10
- :routing_key => "time.now"
10
+ :routing_key => "time.now",
11
+ :mandatory => true
11
12
  }
12
13
  )
13
14
 
14
- publisher.publish Time.now.to_s
15
+ producer.publish Time.now.to_s
15
16
  end
@@ -0,0 +1,28 @@
1
+ require_relative "../lib/message_queue"
2
+
3
+ class Producer
4
+ include MessageQueue::Producible
5
+
6
+ exchange :name => "time", :type => :topic
7
+ message :routing_key => "time.now", :mandatory => true
8
+ end
9
+
10
+ class Consumer
11
+ include MessageQueue::Consumable
12
+
13
+ queue :name => "print_time_now"
14
+ exchange :name => "time", :routing_key => "time.#"
15
+
16
+ def process(message)
17
+ puts "Received message #{message.payload}"
18
+ end
19
+ end
20
+
21
+ MessageQueue.connect(:adapter => :bunny, :serializer => :json)
22
+ MessageQueue.run_consumables
23
+
24
+ Producer.new.publish(Time.now.to_s)
25
+
26
+ sleep 1
27
+
28
+ MessageQueue.disconnect
@@ -10,6 +10,10 @@ module MessageQueue
10
10
  instance.new_connection(serializer, options)
11
11
  end
12
12
  end
13
+
14
+ def new_connection(serializer, options = {})
15
+ Connection.new(serializer, options)
16
+ end
13
17
  end
14
18
  end
15
19
  end
@@ -1,25 +1,13 @@
1
- class MessageQueue::Adapters::Bunny::Connection
2
- attr_reader :serializer, :settings, :connection
3
-
4
- # Public: Initialize a new Bunny connection.
5
- #
6
- # serializer - The Serializer for dumping and loading payload.
7
- #
8
- # settings - The Hash settings used to connect with Bunny.
9
- # Details in http://rubybunny.info/articles/connecting.html.
10
- #
11
- # Returns a Connection wrapper for Bunny.
12
- def initialize(serializer, settings)
13
- @serializer = serializer
14
- @settings = settings
15
- end
1
+ class MessageQueue::Adapters::Bunny::Connection < MessageQueue::Connection
2
+ attr_reader :connection
16
3
 
17
4
  # Public: Connect to RabbitMQ
18
5
  #
19
6
  # Returns the Bunny instance
20
7
  def connect
21
8
  @connection ||= begin
22
- bunny = ::Bunny.new(settings)
9
+ super
10
+ bunny = ::Bunny.new(bunny_settings)
23
11
  bunny.start
24
12
  bunny
25
13
  end
@@ -30,27 +18,23 @@ class MessageQueue::Adapters::Bunny::Connection
30
18
  # Returns nothing
31
19
  def disconnect
32
20
  if @connection
21
+ super
33
22
  @connection.close if @connection.open?
34
23
  @connection = nil
35
24
  end
36
25
  end
37
26
 
38
- # Public: Connect to RabbitMQ, execute the block and disconnect
27
+ # Public: Check if it's connected to the message queue
39
28
  #
40
- # Returns nothing
41
- def with_connection(&block)
42
- begin
43
- connect
44
- block.call(self)
45
- ensure
46
- disconnect
47
- end
29
+ # Returns true if it's connected
30
+ def connected?
31
+ @connection.open? if @connection
48
32
  end
49
33
 
50
- def new_publisher(options)
34
+ def new_producer(options)
51
35
  raise "No connection to RabbitMQ" unless connection
52
36
 
53
- Publisher.new(self, options)
37
+ Producer.new(self, options)
54
38
  end
55
39
 
56
40
  def new_consumer(options)
@@ -58,7 +42,21 @@ class MessageQueue::Adapters::Bunny::Connection
58
42
 
59
43
  Consumer.new(self, options)
60
44
  end
45
+
46
+ private
47
+
48
+ def bunny_settings
49
+ default_bunny_settings.merge(settings)
50
+ end
51
+
52
+ def default_bunny_settings
53
+ {
54
+ :heartbeat => 1,
55
+ :automatically_recover => true,
56
+ :network_recovery_interval => 1
57
+ }
58
+ end
61
59
  end
62
60
 
63
- require "message_queue/adapters/bunny/publisher"
61
+ require "message_queue/adapters/bunny/producer"
64
62
  require "message_queue/adapters/bunny/consumer"
@@ -1,5 +1,4 @@
1
- class MessageQueue::Adapters::Bunny::Connection::Consumer
2
- attr_reader :connection
1
+ class MessageQueue::Adapters::Bunny::Connection::Consumer < MessageQueue::Consumer
3
2
  attr_reader :queue_options, :queue_name
4
3
  attr_reader :exchange_options, :exchange_name, :exchange_routing_key
5
4
  attr_reader :subscribe_options
@@ -25,27 +24,34 @@ class MessageQueue::Adapters::Bunny::Connection::Consumer
25
24
  #
26
25
  # Returns a Consumer.
27
26
  def initialize(connection, options = {})
28
- @connection = connection
27
+ super
29
28
 
30
- options = options.dup
31
-
32
- @queue_options = options.fetch(:queue)
29
+ @queue_options = self.options.fetch(:queue)
33
30
  @queue_name = queue_options.delete(:name) || (raise "Missing queue name")
34
31
 
35
- @exchange_options = options.fetch(:exchange)
32
+ @exchange_options = self.options.fetch(:exchange)
36
33
  @exchange_name = exchange_options.delete(:name) || (raise "Missing exchange name")
37
34
  @exchange_routing_key = exchange_options.delete(:routing_key) || queue_name
38
35
 
39
- @subscribe_options = options.fetch(:subscribe, {})
36
+ @subscribe_options = self.options.fetch(:subscribe, {}).merge(:ack => true)
40
37
  end
41
38
 
42
39
  def subscribe(options = {}, &block)
43
40
  @subscription = queue.subscribe(subscribe_options.merge(options)) do |delivery_info, metadata, payload|
44
- block.call(delivery_info, metadata, connection.serializer.load(payload))
41
+ begin
42
+ message = MessageQueue::Message.new(:message_id => metadata[:message_id],
43
+ :type => metadata[:type],
44
+ :timestamp => metadata[:timestamp],
45
+ :routing_key => delivery_info[:routing_key],
46
+ :payload => load_object(payload))
47
+ block.call(message)
48
+ ensure
49
+ ack(delivery_info.delivery_tag)
50
+ end
45
51
  end
46
52
  end
47
53
 
48
- def unsubscribe
54
+ def unsubscribe(options = {})
49
55
  @subscription.cancel if @subscription
50
56
  end
51
57
 
@@ -53,9 +59,13 @@ class MessageQueue::Adapters::Bunny::Connection::Consumer
53
59
  @queue ||= channel.queue(queue_name, queue_options).bind(exchange_name, :routing_key => exchange_routing_key)
54
60
  end
55
61
 
62
+ def ack(delivery_tag)
63
+ channel.ack(delivery_tag, false)
64
+ end
65
+
56
66
  private
57
67
 
58
68
  def channel
59
- connection.connection.create_channel
69
+ @channel ||= connection.connection.create_channel
60
70
  end
61
71
  end
@@ -1,13 +1,13 @@
1
- class MessageQueue::Adapters::Bunny::Connection::Publisher
2
- attr_reader :connection, :exchange
1
+ class MessageQueue::Adapters::Bunny::Connection::Producer < MessageQueue::Producer
2
+ attr_reader :exchange
3
3
  attr_reader :exchange_options, :exchange_name, :exchange_type
4
4
  attr_reader :message_options
5
5
 
6
- # Public: Initialize a new Bunny publisher.
6
+ # Public: Initialize a new Bunny producer.
7
7
  #
8
8
  # connection - The Bunny Connection.
9
9
  # options - The Hash options used to initialize the exchange
10
- # of a publisher:
10
+ # of a producer:
11
11
  # :exchange -
12
12
  # :name - The String exchange name.
13
13
  # :type - The Symbol exchange type.
@@ -21,20 +21,20 @@ class MessageQueue::Adapters::Bunny::Connection::Publisher
21
21
  #
22
22
  # Returns a Publisher.
23
23
  def initialize(connection, options = {})
24
- @connection = connection
24
+ super
25
25
 
26
- options = options.dup
27
-
28
- @exchange_options = options.fetch(:exchange)
26
+ @exchange_options = self.options.fetch(:exchange)
29
27
  @exchange_name = exchange_options.delete(:name) || (raise "Missing exchange name")
30
28
  @exchange_type = exchange_options.delete(:type) || (raise "Missing exchange type")
31
29
 
32
- @message_options = options.fetch(:message)
30
+ @message_options = self.options.fetch(:message)
33
31
 
34
- @exchange = connection.connection.create_channel.send(exchange_type, exchange_name, exchange_options)
32
+ @exchange = connection.connection.default_channel.send(exchange_type, exchange_name, exchange_options)
35
33
  end
36
34
 
37
- def publish(payload, options = {})
38
- exchange.publish(connection.serializer.dump(payload), message_options.merge(options))
35
+ def publish(object, options = {})
36
+ options = message_options.merge(default_options).merge(options)
37
+ object = dump_object(object)
38
+ exchange.publish(object, options)
39
39
  end
40
40
  end
@@ -0,0 +1,12 @@
1
+ class MessageQueue::Adapters::Memory::Connection < MessageQueue::Connection
2
+ def new_producer(options = {})
3
+ Producer.new(self, options)
4
+ end
5
+
6
+ def new_consumer(options = {})
7
+ Consumer.new(self, options)
8
+ end
9
+ end
10
+
11
+ require "message_queue/adapters/memory/producer"
12
+ require "message_queue/adapters/memory/consumer"
@@ -0,0 +1,34 @@
1
+ class MessageQueue::Adapters::Memory::Connection::Consumer < MessageQueue::Consumer
2
+ attr_reader :queue, :block
3
+
4
+ def initialize(*args)
5
+ super
6
+ @queue = []
7
+ end
8
+
9
+ def subscribe(options = {}, &block)
10
+ producer = options.fetch(:producer)
11
+ producer.add_observer(self)
12
+ @block = block
13
+ end
14
+
15
+ def unsubscribe(options = {})
16
+ producer = options.fetch(:producer)
17
+ producer.delete_observer(self)
18
+ @block = nil
19
+ end
20
+
21
+ def update(object, options)
22
+ object = load_object(object)
23
+ message = MessageQueue::Message.new(:message_id => options[:message_id],
24
+ :type => options[:type],
25
+ :timestamp => options[:timestamp],
26
+ :routing_key => options[:routing_key],
27
+ :payload => load_object(object))
28
+ if block
29
+ block.call(message)
30
+ else
31
+ queue << message
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,11 @@
1
+ require "observer"
2
+
3
+ class MessageQueue::Adapters::Memory::Connection::Producer < MessageQueue::Producer
4
+ include Observable
5
+
6
+ def publish(object, options = {})
7
+ changed
8
+ notify_observers(dump_object(object), default_options.merge(options))
9
+ true
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module MessageQueue
2
+ module Adapters
3
+ class Memory < Adapter
4
+ def new_connection(serializer, options = {})
5
+ Connection.new(serializer, options)
6
+ end
7
+ end
8
+ end
9
+ end
10
+
11
+ require "message_queue/adapters/memory/connection"
@@ -0,0 +1,64 @@
1
+ require "message_queue/logging"
2
+
3
+ class MessageQueue::Connection
4
+ include MessageQueue::Logging
5
+
6
+ attr_reader :serializer, :settings
7
+
8
+ # Public: Initialize a new Bunny connection.
9
+ #
10
+ # serializer - The Serializer for dumping and loading payload.
11
+ #
12
+ # settings - The Hash settings used to connect.
13
+ #
14
+ #
15
+ # Returns a Connection wrapper for Bunny.
16
+ def initialize(serializer, settings)
17
+ @serializer = serializer
18
+ @settings = settings
19
+ end
20
+
21
+ # Public: Connect to the message queue
22
+ #
23
+ # Returns nothing
24
+ def connect
25
+ logger.info("Connecting to message queue with adapter #{self.class} and settings #{settings}")
26
+ end
27
+
28
+ # Public: Disconnect from the message queue
29
+ #
30
+ # Returns nothing
31
+ def disconnect
32
+ logger.info("Disconnecting from message queue")
33
+ end
34
+
35
+ # Public: Check if it's connected to the message queue
36
+ #
37
+ # Returns true if it's connected
38
+ def connected?
39
+ false
40
+ end
41
+
42
+ # Public: Connect to the message, execute the block and disconnect
43
+ #
44
+ # Returns nothing
45
+ def with_connection(&block)
46
+ begin
47
+ connect
48
+ block.call(self)
49
+ ensure
50
+ disconnect
51
+ end
52
+ end
53
+
54
+ def new_producer(options = {})
55
+ Producer.new(self, options)
56
+ end
57
+
58
+ def new_consumer(options = {})
59
+ Consumer.new(self, options)
60
+ end
61
+ end
62
+
63
+ require "message_queue/producer"
64
+ require "message_queue/consumer"
@@ -0,0 +1,83 @@
1
+ require "message_queue/logging"
2
+
3
+ module MessageQueue
4
+ # A module to mix in a consumer class, for example:
5
+ #
6
+ # class Consumer
7
+ # include MessageQueue::Consumable
8
+ #
9
+ # queue :name => "print_time_now"
10
+ # exchange :name => "time", :routing_key => "time.#"
11
+ #
12
+ # def process(message)
13
+ # ...
14
+ # end
15
+ # end
16
+ #
17
+ # The consumer class needs to implement the process method which will be passed
18
+ # a MessageQueue::Message instance when it receives a message.
19
+ module Consumable
20
+ include Logging
21
+
22
+ def self.included(base)
23
+ base.extend(ClassMethods)
24
+ MessageQueue.register_consumable(base)
25
+ end
26
+
27
+ module ClassMethods
28
+ def queue(options = {})
29
+ queue_options.merge!(options)
30
+ end
31
+
32
+ def exchange(options = {})
33
+ exchange_options.merge!(options)
34
+ end
35
+
36
+ def subscribe(options = {})
37
+ subscribe_options.merge!(options)
38
+ end
39
+
40
+ def queue_options
41
+ @queue_options ||= {}
42
+ end
43
+
44
+ def exchange_options
45
+ @exchange_options ||= {}
46
+ end
47
+
48
+ def subscribe_options
49
+ @subscribe_options ||= {}
50
+ end
51
+ end
52
+
53
+ def initialize
54
+ @consumer = MessageQueue.new_consumer(:queue => self.class.queue_options,
55
+ :exchange => self.class.exchange_options,
56
+ :subscribe => self.class.subscribe_options)
57
+ end
58
+
59
+ def subscribe(options = {})
60
+ @consumer.subscribe(options) do |message|
61
+ begin
62
+ logger.info("Message(#{message.message_id || '-'}): " +
63
+ "routing key: #{message.routing_key}, " +
64
+ "type: #{message.type}, " +
65
+ "timestamp: #{message.timestamp}, " +
66
+ "consumer: #{@consumer.class}, " +
67
+ "payload: #{message.payload}")
68
+ process(message)
69
+ rescue StandardError => ex
70
+ handle_error(message, consumer, ex)
71
+ end
72
+ end
73
+ end
74
+
75
+ private
76
+
77
+ def handle_error(message, consumer, ex)
78
+ MessageQueue.error_handlers.each do |handler|
79
+ handler.handle(message, consumer, ex)
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,28 @@
1
+ module MessageQueue
2
+ class ConsumableRunner
3
+ include Logging
4
+
5
+ attr_reader :consumables
6
+
7
+ def initialize(consumables)
8
+ @consumables = consumables
9
+ end
10
+
11
+ def run(options = {})
12
+ begin
13
+ block = !!options[:block]
14
+ consumables.each_with_index do |consumable, index|
15
+ # Blocks the last consumer
16
+ opts = if index < consumables.size - 1
17
+ {}
18
+ else
19
+ { :block => block }
20
+ end
21
+ consumable.new.subscribe(opts)
22
+ end
23
+ rescue SignalException => ex
24
+ logger.info "Received Signal #{ex}"
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,18 @@
1
+ require "message_queue/options_helper"
2
+
3
+ module MessageQueue
4
+ class Consumer
5
+ include OptionsHelper
6
+
7
+ attr_reader :connection, :options
8
+
9
+ def initialize(connection, options = {})
10
+ @connection = connection
11
+ @options = deep_clone(options)
12
+ end
13
+
14
+ def load_object(object)
15
+ connection.serializer.load(object)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,19 @@
1
+ begin
2
+ require "airbrake"
3
+ rescue LoadError
4
+ end
5
+
6
+ if defined?(Airbrake)
7
+ module MessageQueue
8
+ module ErrorHandlers
9
+ class Airbrake
10
+ def handle(message, consumer, ex)
11
+ params = message.attributes.merge(:pid => Process.pid, :consumer => consumer.inspect)
12
+ ::Airbrake.notify_or_ignore(ex, :parameters => params)
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ MessageQueue.register_error_handler MessageQueue::ErrorHandlers::Airbrake.new
19
+ end