smith 0.6.5.2 → 0.6.7
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 +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
|