smith 0.6.5.2 → 0.6.7

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: 28e4e29c427b83d0923d75bdf2789e01dfec90ff
4
- data.tar.gz: ec4ecc625c7c52fc8079d9eb9e97bb5c56af40fb
3
+ metadata.gz: ac264c23960916b555109d48e592a8560447182f
4
+ data.tar.gz: 424cd6d244fbdce54cffce746aeb4f81635515e8
5
5
  SHA512:
6
- metadata.gz: a8d70474e776f60812b052223c253790e4e29ef69b48dfda51dc52513bffa3798b2135db4759131ea9174fa10ec70895f9ffbc4b0aa5852ff2c26c0d869183d9
7
- data.tar.gz: 4658f5f3d511ad13374cf4fc99cddd46a10aaa483f846acfacf5c61aeae5c170ef95002015d85a36d954b0cada657b84c4ab9145bc9d39566c52b81a1eeff592
6
+ metadata.gz: 9e73b594b540c6d136a5e9ed783531aa378603b28a0f1caa408e40a0f412d7583437b42b21fbcb14ec7566a6f339183a20f5dc51b7e823ea8970dd5ff8b98ff9
7
+ data.tar.gz: 894a371746a71b6af111614db36c5a6f9f58e6f070f2bbb2b1e16f6eba97904d16f1fd334e56ea335bd4058de372adff0b7123c4365eb8b1dfd206a750d3cfc0
data/lib/smith/agent.rb CHANGED
@@ -89,7 +89,7 @@ module Smith
89
89
  queue = agent.instance_variable_get(:@signal_handler_queue)
90
90
  signal = queue.pop
91
91
 
92
- agent.send(:logger).debug { "Running signal handlers for agent: #{agent.name}: #{signal}" }
92
+ # agent.send(:logger).debug { "Running signal handlers for agent: #{agent.name}: #{signal}" }
93
93
  handlers[signal].each { |handler| handler.call(signal) }
94
94
  end
95
95
  })
@@ -108,7 +108,6 @@ module Smith
108
108
  @signal_handlers[signal].insert((position == :beginning) ? 0 : -1, blk)
109
109
 
110
110
  Signal.trap(signal) {
111
- logger.debug { "Got signal: #{signal}" }
112
111
  @signal_handler_pipe_writer.write_nonblock('.')
113
112
  @signal_handler_queue << signal
114
113
  }
@@ -9,6 +9,8 @@ module Smith
9
9
  class AgentProcess
10
10
 
11
11
  include Smith::Logger
12
+ include Utils
13
+
12
14
  extend Forwardable
13
15
 
14
16
  class AgentState < ::Protobuf::Message
@@ -75,7 +77,7 @@ module Smith
75
77
  end
76
78
 
77
79
  event :kill do
78
- transition [:null, :unknown, :starting, :acknowledge_start, :stopping, :acknowledge_stop, :running, :dead] => :null
80
+ transition [:null, :unknown, :checked, :starting, :acknowledge_start, :stopping, :acknowledge_stop, :running, :dead] => :null
79
81
  end
80
82
  end
81
83
 
@@ -131,9 +133,7 @@ module Smith
131
133
  end
132
134
 
133
135
  def exists?
134
- Smith.agent_paths.detect do |path|
135
- Pathname.new(path).join("#{name.snake_case}.rb").exist?
136
- end
136
+ agent_path(name)
137
137
  end
138
138
 
139
139
  def to_s
@@ -8,7 +8,6 @@ $:.unshift(Pathname.new(__FILE__).dirname.parent.expand_path)
8
8
 
9
9
  require 'smith'
10
10
  require 'smith/agent'
11
- # require 'smith/synchronous_agent'
12
11
 
13
12
  module Smith
14
13
  class AgentBootstrap
@@ -16,6 +15,7 @@ module Smith
16
15
  attr_reader :agent
17
16
 
18
17
  include Logger
18
+ include Utils
19
19
 
20
20
  def initialize(name, uuid)
21
21
  Dir.chdir('/')
@@ -27,7 +27,6 @@ module Smith
27
27
  Thread.abort_on_exception = true
28
28
  @agent_name = name
29
29
  @agent_uuid = uuid
30
- @agent_filename = agent_path(name)
31
30
  end
32
31
 
33
32
  def signal_handlers
@@ -41,20 +40,19 @@ module Smith
41
40
  end
42
41
 
43
42
  def load_agent
44
- @agent_filename = agent_path(@agent_name)
45
- logger.debug { "Loading #{@agent_name} from: #{@agent_filename.dirname}" }
46
- add_agent_load_path
47
- load @agent_filename
48
- @agent = Kernel.const_get(@agent_name).new(@agent_uuid)
49
- end
50
-
51
- def agent_path(name)
52
- file_name = "#{name.snake_case}.rb"
53
- Smith.agent_paths.each do |path|
54
- p = Pathname.new(path).join(file_name)
55
- return p if p.exist?
43
+ path = agent_path(@agent_name)
44
+ logger.debug { "Loading #{@agent_name} from: #{path.dirname}" }
45
+ add_agent_load_path(path)
46
+ load path
47
+
48
+ begin
49
+ @agent = class_from_name(@agent_name).new(@agent_uuid)
50
+ rescue NameError => e
51
+ # TODO: include the class name from the path.
52
+ logger.fatal { "Cannot instantiate agent. The class name: #{@agent_name} probably didn't match the path" }
53
+ terminate!
54
+ false
56
55
  end
57
- return nil
58
56
  end
59
57
 
60
58
  def start!
@@ -128,8 +126,8 @@ module Smith
128
126
  #
129
127
  # This needs to be better thought out.
130
128
  # TODO think this through some more.
131
- def add_agent_load_path
132
- path = @agent_filename.dirname.dirname.join('lib')
129
+ def add_agent_load_path(path)
130
+ path = path.dirname.dirname.join('lib')
133
131
  # The load path may be a pathname or a string. Change to strings.
134
132
  unless $:.detect { |p| p.to_s == path.to_s }
135
133
  logger.debug { "Adding #{path} to load path" }
@@ -158,9 +156,10 @@ bootstrapper = Smith::AgentBootstrap.new(name, uuid)
158
156
  # is an exception the reactor is not going going to be running.
159
157
  begin
160
158
  Smith.start do
161
- bootstrapper.load_agent
162
- bootstrapper.signal_handlers
163
- bootstrapper.start!
159
+ if bootstrapper.load_agent
160
+ bootstrapper.signal_handlers
161
+ bootstrapper.start!
162
+ end
164
163
  end
165
164
  bootstrapper.shutdown
166
165
  rescue Exception => e
@@ -0,0 +1,29 @@
1
+ require_relative '../common'
2
+
3
+ module Smith
4
+ module Commands
5
+ class Group < CommandBase
6
+
7
+ include Common
8
+
9
+ def execute
10
+ group do |value|
11
+ responder.succeed(value)
12
+ end
13
+ end
14
+
15
+ # Returns the agents in a group.
16
+ def group(&blk)
17
+ begin
18
+ blk.call(agent_group(target.first).join(' '))
19
+ rescue RuntimeError => e
20
+ blk.call(e.message)
21
+ end
22
+ end
23
+
24
+ def options_spec
25
+ banner "Lists the agents in a group."
26
+ end
27
+ end
28
+ end
29
+ end
@@ -30,7 +30,7 @@ module Smith
30
30
  on_work = ->(message, iter) do
31
31
 
32
32
  error_handler = -> (e) do
33
- if options[:no_fail]
33
+ if options[:ignore_errors]
34
34
  logger.error { "#{e} #{message.strip}" }
35
35
  iter.call
36
36
  else
@@ -90,14 +90,14 @@ module Smith
90
90
  def options_spec
91
91
  banner "Send a message to a queue. The ACL can also be specified."
92
92
 
93
- opt :type, "message type", :type => :string, :default => 'default', :short => :t
94
- opt :message, "the message, as json", :type => :string, :short => :m
95
- opt :file, "read messages from the named file", :type => :string, :short => :f
96
- opt :number, "the number of times to send the message", :type => :integer, :default => 1, :short => :n
97
- opt :reply, "set a reply listener.", :short => :r
98
- opt :timeout, "timeout when waiting for a reply", :type => :integer, :depends => :reply, :default => Smith.config.smith.timeout
99
- opt :dynamic, "send message to a dynamic queue", :type => :boolean, :default => false, :short => :d
100
- opt :no_fail, "continue to process input data if there is an error", :type => :boolean, :default => false
93
+ opt :type, "message type", :type => :string, :default => 'default', :short => :t
94
+ opt :message, "the message, as json", :type => :string, :short => :m
95
+ opt :file, "read messages from the named file", :type => :string, :short => :f
96
+ opt :number, "the number of times to send the message", :type => :integer, :default => 1, :short => :n
97
+ opt :reply, "set a reply listener.", :short => :r
98
+ opt :timeout, "timeout when waiting for a reply", :type => :integer, :depends => :reply, :default => Smith.config.smith.timeout
99
+ opt :dynamic, "send message to a dynamic queue", :type => :boolean, :default => false, :short => :d
100
+ opt :ignore_errors, "continue to process input data if there is an error", :type => :boolean, :default => false
101
101
 
102
102
  conflicts :reply, :number, :file
103
103
  conflicts :message, :file
@@ -7,24 +7,16 @@ module Smith
7
7
  when 0
8
8
  responder.succeed("No queue specified. Please specify a queue.")
9
9
  else
10
- @on_error = proc do |ch,channel_close|
11
- case channel_close.reply_code
12
- when 404
13
- responder.succeed("No such queue: [#{channel_close.reply_code}]: #{channel_close.reply_text}")
14
- when 406
15
- responder.succeed("Queue not empty: [#{channel_close.reply_code}]: #{channel_close.reply_text}.")
16
- else
17
- responder.succeed("Unknown error: [#{channel_close.reply_code}]: #{channel_close.reply_text}")
18
- end
19
- end
20
-
21
- target.each do |queue_name|
10
+ worker = ->(queue_name, iter) do
22
11
  delete_queue(queue_name) do |delete_ok|
23
- delete_exchange(queue_name) do |delete_ok|
24
- responder.succeed((options[:verbose]) ? delete_ok.message_count.to_s : nil)
25
- end
12
+ delete_exchange(queue_name, &iter)
26
13
  end
27
14
  end
15
+
16
+ # FIXME: Return errors to the caller rather than doing nothing or logging errors
17
+ done = -> { responder.succeed }
18
+
19
+ EM::Iterator.new(target).each(worker, done)
28
20
  end
29
21
  end
30
22
 
@@ -33,14 +25,26 @@ module Smith
33
25
  def options_spec
34
26
  banner "Display or remove a message from the named queue."
35
27
 
36
- opt :force, "force the removal even if there are messages on the queue", :short => :f
37
- opt :verbose, "print the number of messages deleted", :short => :v
28
+ opt :force, "force the removal even if there are messages on the queue", :short => :f
29
+ opt :ignore_errors, "ignore any errors.", :default => false
30
+ opt :log_errors, "print any errors messages.", :default => false
38
31
  end
39
32
 
40
- def delete_exchange(exchange_name, &blk)
41
- AMQP::Channel.new(Smith.connection) do |channel,ok|
42
- channel.on_error(&@on_error)
43
- channel.direct("smith.#{exchange_name}", :passive => true) do |exchange|
33
+ # Delete an exchange.
34
+ #
35
+ # @param name [String] name of the exchange.
36
+ # @yield calls the block when the exchange has been deleted
37
+ # @yieldparam [AMQ::Protocol::Channel::Close] the amqp close message
38
+ # FIXME: remove duplication
39
+ def delete_exchange(name, &blk)
40
+ AMQP::Channel.new(Smith.connection) do |channel, ok|
41
+
42
+ channel.on_error do |channel, channel_close|
43
+ handler = (options[:ignore_errors]) ? blk : nil
44
+ log_error(channel, channel_close, &handler)
45
+ end
46
+
47
+ channel.direct("smith.#{name}", :passive => true) do |exchange|
44
48
  exchange_options = (options[:force]) ? {} : {:if_unused => true}
45
49
  exchange.delete(exchange_options) do |delete_ok|
46
50
  blk.call(delete_ok)
@@ -49,9 +53,19 @@ module Smith
49
53
  end
50
54
  end
51
55
 
56
+ # Delete an queue.
57
+ #
58
+ # @param name [String] name of the queue.
59
+ # @yield calls the block when the queue has been deleted
60
+ # @yieldparam [AMQ::Protocol::Channel::Close] the amqp close message
61
+ # FIXME: remove duplication
52
62
  def delete_queue(queue_name, &blk)
53
- AMQP::Channel.new(Smith.connection) do |channel,ok|
54
- channel.on_error(&@on_error)
63
+ AMQP::Channel.new(Smith.connection) do |channel, ok|
64
+ channel.on_error do |channel, channel_close|
65
+ handler = (options[:ignore_errors]) ? blk : nil
66
+ log_error(channel, channel_close, &handler)
67
+ end
68
+
55
69
  channel.queue("smith.#{queue_name}", :passive => true) do |queue|
56
70
  queue_options = (options[:force]) ? {} : {:if_unused => true, :if_empty => true}
57
71
  queue.delete(queue_options) do |delete_ok|
@@ -61,6 +75,21 @@ module Smith
61
75
  end
62
76
  end
63
77
 
78
+ # Get's called when there is a channel error.
79
+ #
80
+ # @param channel [AMQP::Channel] the channel that errored
81
+ # @param channel_close [AMQ::Protocol::Channel::Close] the amqp close message
82
+ # which contains details of why the channel was claosed.
83
+ def log_error(channel, channel_close, &blk)
84
+ base_error_msg = "#{channel_close.reply_code}, #{channel_close.reply_text}."
85
+ if blk
86
+ logger.error { "#{base_error_msg}. Ignoring as requested" } if options[:log_errors]
87
+ blk.call
88
+ else
89
+ responder.succeed(base_error_msg)
90
+ end
91
+ end
92
+
64
93
  def extract_queue(message)
65
94
  match = /.*?'(.*?)'.*$/.match(message) #[1]
66
95
  if match && match[1]
@@ -1,16 +1,18 @@
1
1
  # -*- encoding: utf-8 -*-
2
- module Smith
3
2
 
3
+ module Smith
4
4
  module ACL
5
5
  class Factory
6
6
  include Logger
7
7
 
8
+ extend Utils
9
+
8
10
  class << self
9
11
  def create(type, content=nil, &blk)
10
12
  if type.respond_to?(:serialize_to_string)
11
13
  return type
12
14
  else
13
- clazz = (type.is_a?(::Protobuf::Message)) ? type : get_clazz(type)
15
+ clazz = (type.is_a?(::Protobuf::Message)) ? type : class_from_name(type)
14
16
 
15
17
  if blk
16
18
  clazz.new.tap { |m| blk.call(m) }
@@ -19,10 +21,6 @@ module Smith
19
21
  end
20
22
  end
21
23
  end
22
-
23
- def get_clazz(type)
24
- type.to_s.split(/::/).inject(Kernel) { |acc, t| acc.const_get(t) }
25
- end
26
24
  end
27
25
  end
28
26
  end
@@ -0,0 +1,42 @@
1
+ module Smith
2
+ module Utils
3
+
4
+ # Searches the agent load path for agents. If there are multiple agents
5
+ # with the same name in different directories the first wins.
6
+ #
7
+ # @param name [String] the name of the agent.
8
+ # @return [Pathname] the path of the agent.
9
+ def agent_path(name)
10
+ Smith.agent_paths.each do |path|
11
+ p = path_from_class(path, name)
12
+ return p if p.exist?
13
+ end
14
+ return nil
15
+ end
16
+
17
+ # Constructs a path from a root and a fully qualified class.
18
+ #
19
+ # @param root [Pathname] the root path.
20
+ # @param clazz [String] the fully qualified class.
21
+ # @@return [Pathname] the path
22
+ def path_from_class(root, clazz)
23
+ parts = clazz.split(/::/).map(&:snake_case)
24
+ parts[-1] = "#{parts[-1]}.rb"
25
+ Pathname.new(root).join(*parts)
26
+ end
27
+
28
+ def class_name_from_path(root, path)
29
+ relative_path = path.relative_path_from(root)
30
+ parts = relative_path.split
31
+ parts.map { |p| p.to_s.camel_case }.join('::')
32
+ end
33
+
34
+ # Performs a Kernel.const_get on each element of the class.
35
+ #
36
+ # @param name [String]
37
+ # @return [Class] the agent class
38
+ def class_from_name(name)
39
+ name.to_s.split(/::/).inject(Kernel) { |acc, t| acc.const_get(t) }
40
+ end
41
+ end
42
+ end
data/lib/smith/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Smith
2
- VERSION = "0.6.5.2"
2
+ VERSION = "0.6.7"
3
3
  end
data/lib/smith.rb CHANGED
@@ -208,6 +208,7 @@ module Smith
208
208
  end
209
209
  end
210
210
 
211
+ require 'smith/utils'
211
212
  require 'smith/amqp_errors'
212
213
  require 'smith/object_count'
213
214
  require 'smith/cache'
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.6.5.2
4
+ version: 0.6.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Heycock
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-08 00:00:00.000000000 Z
11
+ date: 2014-11-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oj
@@ -205,6 +205,7 @@ files:
205
205
  - lib/smith/command.rb
206
206
  - lib/smith/command_base.rb
207
207
  - lib/smith/commands/agency/agents.rb
208
+ - lib/smith/commands/agency/group.rb
208
209
  - lib/smith/commands/agency/kill.rb
209
210
  - lib/smith/commands/agency/list.rb
210
211
  - lib/smith/commands/agency/logger.rb
@@ -253,6 +254,7 @@ files:
253
254
  - lib/smith/messaging/util.rb
254
255
  - lib/smith/object_count.rb
255
256
  - lib/smith/queue_definitions.rb
257
+ - lib/smith/utils.rb
256
258
  - lib/smith/version.rb
257
259
  homepage: http://github.com/filterfish/smith2
258
260
  licenses:
@@ -279,3 +281,4 @@ signing_key:
279
281
  specification_version: 4
280
282
  summary: Multi-agent framework
281
283
  test_files: []
284
+ has_rdoc: false