smith 0.8.3 → 0.8.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 28699a1628e95ca70d8b4885013ca54a4ffd10a9
4
- data.tar.gz: 40d84936049ef5870edb312f7b929cba7190e560
3
+ metadata.gz: 5b0a3ce48b208c5e828b780e7cc46b9acaf52db8
4
+ data.tar.gz: 3ef6cffd4dbe62b2b385744ed02f85a667f22ada
5
5
  SHA512:
6
- metadata.gz: d2fde06efa6ae03bee3ae7256e94e6ff050df99099c3a568a4627de290dbcb2acf87f5c877449e3f8e9a0a80817fb28081c011fbf0a95c74eca567b6236f70a3
7
- data.tar.gz: 36ae72308f09a898e5db3caf9fb235e9e5a66a6a59ac71e6ba112aaad0fa937507cbb2c2511895883a0b47a2e0ba95dc64f81dd2247c2aa2a34fc04cc88b6053
6
+ metadata.gz: e154e8e5f9a581e8f68bb663cd9509daa56c7e1d0d7844c536c2566e3bdb19d0123e83dae47741107813e473a41f4f31173023ed06655d3724ffb730ab640b7d
7
+ data.tar.gz: 1960ac4441479753ac6e7bce7da67533d04497c292a7dac43e2041deb8f2e9383fcfd74be9a5a7d83b6884cf826cfdd2c77ccd0ce21798e0267960c3d8c4388f
@@ -32,7 +32,7 @@ module Smith
32
32
  c.completion do |completion|
33
33
  acknowledge_start do
34
34
  @on_running.call(@on_running_completion)
35
- logger.info { "Agent started: #{name}:[#{pid}]." }
35
+ logger.info { "Agent started: #{name}, UUID: #{uuid}, PID: #{pid}" }
36
36
  end
37
37
  end
38
38
  end
@@ -49,9 +49,7 @@ module Smith
49
49
  c.completion do |completion|
50
50
  acknowledge_stop do
51
51
  @state = :stopping
52
- Smith.stop do
53
- logger.info { "Agent stopped: #{name}:[#{pid}]." }
54
- end
52
+ Smith.stop
55
53
  end
56
54
  end
57
55
  end
@@ -199,8 +199,9 @@ module Smith
199
199
  Process.detach(agent_process.pid)
200
200
  end
201
201
 
202
+ # FIXME: This doesn't appear to be being called.
202
203
  def self.acknowledge_start(agent_process, &blk)
203
- logger.info { "Agent started: #{agent_process.uuid}" }
204
+ logger.info { "Agent started: #{agent_process.name}, UUID: #{agent_process.uuid}, PID: #{agent_process.pid}" }
204
205
  end
205
206
 
206
207
  def self.stop(agent_process)
@@ -209,7 +210,7 @@ module Smith
209
210
  if count > 0
210
211
  sender.publish(ACL::AgentCommand.new(:command => 'stop'))
211
212
  else
212
- logger.warn { "Agent is not listening. Setting state to dead." }
213
+ logger.warn { "Agent is not listening. Setting state to dead: #{agent_process.name}, UUID: #{agent_process.uuid}, PID: #{agent_process.pid}" }
213
214
  agent_process.no_process_running
214
215
  end
215
216
  end
@@ -223,7 +224,7 @@ module Smith
223
224
 
224
225
  def self.acknowledge_stop(agent_process)
225
226
  agent_process.delete
226
- logger.info { "Agent stopped: #{agent_process.uuid}" }
227
+ logger.info { "Agent stopped: #{agent_process.name}, UUID: #{agent_process.uuid}, PID: #{agent_process.pid}" }
227
228
  end
228
229
 
229
230
  # This needs to use the PID class to verify if an agent is still running.
@@ -234,7 +235,8 @@ module Smith
234
235
  logger.info { "Agent's pid is 0. The agent probably didn't start correctly. Cleaning up." }
235
236
  agent_process.delete
236
237
  else
237
- logger.info { "Sending kill signal: #{agent_process.pid}: #{agent_process.uuid}" }
238
+ logger.info { "Sending signal: TERM, #{agent_process.name}, UUID: #{agent_process.uuid}, PID: #{agent_process.pid}" }
239
+
238
240
  begin
239
241
  Process.kill('TERM', agent_process.pid)
240
242
  rescue
@@ -95,7 +95,7 @@ module Smith
95
95
  def dead(agent_data)
96
96
  agent_exists?(agent_data.uuid) do |agent_process|
97
97
  if agent_process.no_process_running
98
- logger.fatal { "Agent is dead: #{agent_data.uuid}" }
98
+ logger.fatal { "Agent is dead: #{agent_process.name}, UUID: #{agent_process.uuid}, PID: #{agent_process.pid}" }
99
99
  end
100
100
  end
101
101
  end
@@ -25,6 +25,9 @@ module Smith
25
25
  # thrown in setup_control_queue, for example, it just kills
26
26
  # the agent without it actually raising the exception.
27
27
  Thread.abort_on_exception = true
28
+
29
+ EventMachine.error_handler { |e| terminate!(e) }
30
+
28
31
  @agent_name = name
29
32
  @agent_uuid = uuid
30
33
  end
@@ -33,7 +36,8 @@ module Smith
33
36
  logger.debug { "Installing default signal handlers" }
34
37
  %w{TERM INT QUIT}.each do |sig|
35
38
  @agent.install_signal_handler(sig) do |sig|
36
- logger.error { "Agent received: signal #{sig}: #{agent.name} (#{agent.uuid})" }
39
+ logger.error { "Received signal #{sig}: #{agent.name}, UUID: #{agent.uuid}, PID: #{agent.pid}." }
40
+
37
41
  terminate!
38
42
  end
39
43
  end
@@ -71,19 +75,16 @@ module Smith
71
75
 
72
76
  if Smith.running?
73
77
  send_dead_message
74
- unlink_pid_file
75
- Smith.stop
78
+ shutdown
76
79
  else
77
- logger.debug { "Reconnecting to AMQP Broker." }
78
80
  Smith.start do
79
81
  send_dead_message
80
- unlink_pid_file
81
- Smith.stop
82
+ shutdown
82
83
  end
83
84
  end
84
85
  end
85
86
 
86
- # Clean shutdown of the agent.
87
+ # Cleanly shutdown of the agent.
87
88
  def shutdown
88
89
  unlink_pid_file
89
90
  Smith.stop if Smith.running?
@@ -128,7 +129,7 @@ module Smith
128
129
  @agent.__send__(:__exception_handler, exception) if @agent
129
130
  logger.error { format_exception(exception) }
130
131
  end
131
- logger.error { "Terminating: #{@agent_uuid}." }
132
+ logger.error { "Terminating: #{@agent_name}, UUID: #{@agent_uuid}, PID: #{@pid.pid}." }
132
133
  end
133
134
 
134
135
  # Add the ../lib to the load path. This assumes the directory
@@ -168,18 +169,9 @@ Smith.compile_acls
168
169
 
169
170
  bootstrapper = Smith::AgentBootstrap.new(name, uuid)
170
171
 
171
- # I've tried putting the exception handling in the main reactor log
172
- # but it doesn't do anything. I know there's a reason for this but I
173
- # don't what it is at the moment. Just beware that whenever there
174
- # is an exception the reactor is not going going to be running.
175
- begin
176
- Smith.start do
177
- if bootstrapper.load_agent
178
- bootstrapper.signal_handlers
179
- bootstrapper.start!
180
- end
172
+ Smith.start do
173
+ if bootstrapper.load_agent
174
+ bootstrapper.signal_handlers
175
+ bootstrapper.start!
181
176
  end
182
- bootstrapper.shutdown
183
- rescue Exception => e
184
- bootstrapper.terminate!(e)
185
177
  end
@@ -69,7 +69,7 @@ module Smith
69
69
  end
70
70
 
71
71
  def __reload
72
- @logger = Logging.logger[self.class.to_s || 'main']
72
+ @logger = Logging.logger[(self.is_a?(Module)) ? name : self.class.name]
73
73
  @logger.caller_tracing = @@__trace
74
74
  @reload = false
75
75
  end
@@ -18,6 +18,7 @@ module Smith
18
18
  @acl_type_cache = AclTypeCache.instance
19
19
 
20
20
  @foo_options = {
21
+ :error_queue => opts.delete(:error_queue) { false },
21
22
  :auto_ack => option_or_default(@queue_def.options, :auto_ack, true),
22
23
  :threading => option_or_default(@queue_def.options, :threading, false)}
23
24
 
@@ -95,7 +96,7 @@ module Smith
95
96
  if !queue.subscribed?
96
97
  opts = @options.subscribe
97
98
  logger.debug { "Subscribing to: [queue]:#{@queue_def.denormalise} [options]:#{opts}" }
98
- queue.subscribe(opts) do |metadata,payload|
99
+ queue.subscribe(opts) do |metadata, payload|
99
100
  if payload
100
101
  on_message(metadata, payload, requeue_options, &blk)
101
102
  else
@@ -234,14 +235,20 @@ module Smith
234
235
  end
235
236
  end
236
237
 
238
+ # This class gets passed into the receive block and is a representation of
239
+ # both the message and the message metadata. It also handles requeues and
240
+ # retries. In short it's very much a convenience class which is why I have
241
+ # no idea what to call it!
242
+ #
237
243
  class Foo
238
244
  include Smith::Logger
239
245
 
240
246
  attr_accessor :metadata
241
247
 
242
248
  def initialize(metadata, data, opts={}, requeue_opts, &blk)
249
+ @opts = opts
243
250
  @metadata = metadata
244
- @reply_queue = opts[:reply_queue]
251
+ @reply_queue = @opts[:reply_queue]
245
252
  @requeue_opts = requeue_opts
246
253
 
247
254
  @acl_type_cache = AclTypeCache.instance
@@ -253,14 +260,14 @@ module Smith
253
260
 
254
261
  @message = clazz.new.parse_from_string(data)
255
262
 
256
- if opts[:threading]
263
+ if @opts[:threading]
257
264
  EM.defer do
258
265
  blk.call(@message, self)
259
- ack if opts[:auto_ack]
266
+ ack if @opts[:auto_ack]
260
267
  end
261
268
  else
262
269
  blk.call(@message, self)
263
- ack if opts[:auto_ack]
270
+ ack if @opts[:auto_ack]
264
271
  end
265
272
  end
266
273
 
@@ -289,6 +296,40 @@ module Smith
289
296
  end
290
297
  alias :call :ack
291
298
 
299
+ # Publish the ACL to the error queue set up for this queue. This method is only
300
+ # available if the :error_queue option is set to true. Note this is the
301
+ # receive queue name which in most cases is the same at the sender name
302
+ # but if you are using fanout queues it will be different.
303
+ #
304
+ # @param [ACL] acl Optional ACL. With any options this method will fail the entire
305
+ # ACL. This may not be what you want though. So this opton allows
306
+ # you to fail another ACL. WARNING: there is no type checking at
307
+ # the moment. If you publish an ACL that this agent can't process
308
+ # and republish that ACL at a future date the agent will blow up.
309
+ #
310
+ # @param [Hash] opts Options hash. This currently only supports on option:
311
+ # :ack. If you publish a different ACL from the one received you will have to
312
+ # ack that message yourself and make sure `:ack => nil`
313
+ #
314
+ # @yieldparam [Fixnum] The number of ACLs on the error queue.
315
+ #
316
+ def fail(acl=nil, opts={:ack => true}, &blk)
317
+ if @opts[:error_queue]
318
+ message = (acl) ? acl : @message
319
+ Sender.new("#{queue_name}.error") do |queue|
320
+ logger.debug { "Republishing ACL to error queue: \"#{queue.queue_name}\"" }
321
+ queue.publish(message) do
322
+ queue.number_of_messages do |count|
323
+ @metadata.ack if opts[:ack]
324
+ blk && blk && blk.call(count + 1)
325
+ end
326
+ end
327
+ end
328
+ else
329
+ raise ArgumentError, "You cannot fail this queue as you haven't specified the :error_queue option"
330
+ end
331
+ end
332
+
292
333
  # Make #call invoke ack. This makes the following idiom possible:
293
334
  #
294
335
  # receiver('queue').subscribe do |payload, receiver|
@@ -309,6 +350,23 @@ module Smith
309
350
  def correlation_id
310
351
  @metadata.correlation_id
311
352
  end
353
+
354
+ # Return the queue_name. Note this is the receive queue name which in
355
+ # most cases is the same at the sender name but if you are using fanout
356
+ # queues it will be different.
357
+ #
358
+ # @return [String] the name of the queue
359
+ #
360
+ def queue_name
361
+ begin
362
+ @a561facf ||= @metadata.channel.queues.detect { |queue| queue.bindings.first[:exchange] == @metadata.exchange }.name.gsub(/^#{Smith.config.smith.namespace}\./, '')
363
+ rescue NoMethodError
364
+ # If `bingings` is empty then an exception will be raised. I cannot
365
+ # see how it can possibly happend but if it does raise a slightly
366
+ # more informative exceptino
367
+ raise "Missing queue. This cannot happen and probably represents a bug. Exchange: #{@metadata.exchange}"
368
+ end
369
+ end
312
370
  end
313
371
  end
314
372
  end
@@ -1,3 +1,3 @@
1
1
  module Smith
2
- VERSION = "0.8.3"
2
+ VERSION = "0.8.4"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smith
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.3
4
+ version: 0.8.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Heycock
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-13 00:00:00.000000000 Z
11
+ date: 2016-02-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: amqp