amqp-boilerplate 0.0.5 → 0.0.6

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/CHANGELOG CHANGED
@@ -1,3 +1,13 @@
1
+ = version 0.0.6
2
+
3
+ * [FEATURE] Do not abort consumer thread when a StandardError-like exception
4
+ is raised, but log this instead
5
+
6
+ = version 0.0.5
7
+
8
+ * [FEATURE] Allow additional options to be passed when binding to an
9
+ exchange
10
+
1
11
  = version 0.0.4
2
12
 
3
13
  * [ENHANCEMENT] Documentation
@@ -49,7 +49,7 @@ module AMQP
49
49
  end
50
50
 
51
51
  # Macro that subscribes to asynchronous message delivery.
52
- #
52
+ #
53
53
  # @param [Hash] options Options that will be passed as options to {http://rdoc.info/github/ruby-amqp/amqp/master/AMQP/Queue#subscribe-instance_method AMQP::Queue#subscribe}
54
54
  def amqp_subscription(options={})
55
55
  @subscription_options = options
@@ -64,18 +64,38 @@ module AMQP
64
64
  queue = channel.queue(@queue_name, @queue_options)
65
65
  # Binding a queue to a exchange by passing a string (instead of a AMQP::Exchange instance)
66
66
  queue.bind(@exchange_name, @exchange_options) if @exchange_name
67
- queue.subscribe(@subscription_options, &consumer.method(:handle_message))
67
+ queue.subscribe(@subscription_options, &consumer.method(:handle_message_wrapper))
68
68
 
69
69
  AMQP::Boilerplate.logger.info("[#{self.name}.start] Started consumer '#{self.name}'")
70
70
  end
71
71
  end
72
72
 
73
+ def handle_channel_error(channel, channel_close)
74
+ AMQP::Boilerplate.logger.error("[#{self.class}#handle_channel_error] Code = #{channel_close.reply_code}, message = #{channel_close.reply_text}")
75
+ end
76
+
73
77
  def handle_message(metadata, payload)
74
78
  raise NotImplementedError, "The time has come to implement your own consumer class. Good luck!"
75
79
  end
76
80
 
77
- def handle_channel_error(channel, channel_close)
78
- AMQP::Boilerplate.logger.error("[#{self.class}#handle_channel_error] Code = #{channel_close.reply_code}, message = #{channel_close.reply_text}")
81
+ # Wrapper around message handling routine to prevent the consumer from
82
+ # being killed when an exception occurs
83
+ #
84
+ # Catches anything that quacks like a +StandardError+. +SystemExit+s,
85
+ # +SyntaxError+s and the like will still cause the consumer to be
86
+ # aborted. See Ruby's exception inheritance hierarchy for a complete
87
+ # list of what is and what is not handled by this wrapper.
88
+ def handle_message_wrapper(metadata, payload)
89
+ handle_message(metadata, payload)
90
+ rescue StandardError => e
91
+ message = <<-MSG
92
+ [#{self.class}] An exception occurred while processing a message
93
+ Payload: #{payload}
94
+ Exception: #{e.message}
95
+ Backtrace: #{e.backtrace.join("\n")}
96
+ MSG
97
+
98
+ AMQP::Boilerplate.logger.error(message)
79
99
  end
80
100
  end
81
101
  end
@@ -1,5 +1,5 @@
1
1
  module AMQP
2
2
  module Boilerplate
3
- VERSION = "0.0.5"
3
+ VERSION = "0.0.6"
4
4
  end
5
5
  end
@@ -17,10 +17,9 @@ module AMQP
17
17
  if defined?(PhusionPassenger)
18
18
  PhusionPassenger.on_event(:starting_worker_process) do |forked|
19
19
  if forked
20
- amqp_thread = Thread.new {
20
+ Thread.new do
21
21
  AMQP::Boilerplate.start
22
- }
23
- amqp_thread.abort_on_exception = true
22
+ end
24
23
  end
25
24
  end
26
25
  else
@@ -105,7 +105,7 @@ describe AMQP::Boilerplate::Consumer do
105
105
  @queue.should_receive(:bind).with(@exchange_name, anything)
106
106
  BarConsumer.start
107
107
  end
108
-
108
+
109
109
  it "should pass an empty hash when no amqp_exchange options are defined" do
110
110
  BarConsumer.amqp_exchange(@exchange_name)
111
111
  @queue.should_receive(:bind).with(anything, {})
@@ -130,4 +130,47 @@ describe AMQP::Boilerplate::Consumer do
130
130
  end
131
131
  end
132
132
  end
133
+
134
+ describe "#handle_message_wrapper" do
135
+ before(:each) do
136
+ @consumer = BarConsumer.new
137
+
138
+ @metadata = mock("metadata")
139
+ @payload = "payload"
140
+ end
141
+
142
+ it "should let handle_message do the heavy lifting" do
143
+ @consumer.should_receive(:handle_message).with(@metadata, @payload)
144
+ @consumer.handle_message_wrapper(@metadata, @payload)
145
+ end
146
+
147
+ describe "when a StandardError-like error is raised" do
148
+ before(:each) do
149
+ @consumer.stub(:handle_message).and_raise(StandardError)
150
+ end
151
+
152
+ it "should be caught" do
153
+ expect {
154
+ @consumer.handle_message_wrapper(@metadata, @payload)
155
+ }.to_not raise_error
156
+ end
157
+
158
+ it "should log" do
159
+ AMQP::Boilerplate.logger.should_receive(:error)
160
+ @consumer.handle_message_wrapper(@metadata, @payload)
161
+ end
162
+ end
163
+
164
+ describe "when a NotImplementedError is raised" do
165
+ before(:each) do
166
+ @consumer.stub(:handle_message).and_raise(NotImplementedError)
167
+ end
168
+
169
+ it "should not be caught" do
170
+ expect {
171
+ @consumer.handle_message_wrapper(@metadata, @payload)
172
+ }.to raise_error(NotImplementedError)
173
+ end
174
+ end
175
+ end
133
176
  end
@@ -49,7 +49,7 @@ describe AMQP::Boilerplate do
49
49
  PhusionPassenger = Class.new
50
50
  PhusionPassenger.stub(:on_event).and_yield(true)
51
51
 
52
- @thread = mock(Thread, :abort_on_exception= => nil)
52
+ @thread = mock(Thread)
53
53
  Thread.stub(:new).and_yield.and_return(@thread)
54
54
  end
55
55
 
@@ -67,11 +67,6 @@ describe AMQP::Boilerplate do
67
67
  Thread.should_receive(:new)
68
68
  AMQP::Boilerplate.boot
69
69
  end
70
-
71
- it "should abort thread on exception" do
72
- @thread.should_receive(:abort_on_exception=).with(true)
73
- AMQP::Boilerplate.boot
74
- end
75
70
  end
76
71
  end
77
72
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: amqp-boilerplate
3
3
  version: !ruby/object:Gem::Version
4
- hash: 21
4
+ hash: 19
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 5
10
- version: 0.0.5
9
+ - 6
10
+ version: 0.0.6
11
11
  platform: ruby
12
12
  authors:
13
13
  - Patrick Baselier
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2011-09-20 00:00:00 +02:00
19
+ date: 2011-09-21 00:00:00 +02:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency