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 +4 -4
- data/lib/smith/agent.rb +1 -2
- data/lib/smith/agent_process.rb +4 -4
- data/lib/smith/bootstrap.rb +19 -20
- data/lib/smith/commands/agency/group.rb +29 -0
- data/lib/smith/commands/smithctl/push.rb +9 -9
- data/lib/smith/commands/smithctl/rm.rb +52 -23
- data/lib/smith/messaging/factory.rb +4 -6
- data/lib/smith/utils.rb +42 -0
- data/lib/smith/version.rb +1 -1
- data/lib/smith.rb +1 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ac264c23960916b555109d48e592a8560447182f
|
4
|
+
data.tar.gz: 424cd6d244fbdce54cffce746aeb4f81635515e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
}
|
data/lib/smith/agent_process.rb
CHANGED
@@ -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
|
-
|
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
|
data/lib/smith/bootstrap.rb
CHANGED
@@ -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
|
-
|
45
|
-
logger.debug { "Loading #{@agent_name} from: #{
|
46
|
-
add_agent_load_path
|
47
|
-
load
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
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 =
|
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
|
-
|
163
|
-
|
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[:
|
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,
|
94
|
-
opt :message,
|
95
|
-
opt :file,
|
96
|
-
opt :number,
|
97
|
-
opt :reply,
|
98
|
-
opt :timeout,
|
99
|
-
opt :dynamic,
|
100
|
-
opt :
|
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
|
-
|
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)
|
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
|
37
|
-
opt
|
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
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
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
|
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 :
|
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
|
data/lib/smith/utils.rb
ADDED
@@ -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
data/lib/smith.rb
CHANGED
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.
|
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-
|
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
|