amqp-boilerplate 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
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