smith 0.8.3 → 0.8.4

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