droid 0.9.0 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +34 -0
- metadata +12 -15
- data/bin/conf +0 -31
- data/speaker/droid_speaker.rb +0 -79
- data/speaker/speak +0 -33
- data/speaker/test.rb +0 -58
data/README.md
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
Droid - our AMQP wrapper
|
2
|
+
========================
|
3
|
+
|
4
|
+
Every instance type in the heroku cloud runs an agent, which we call a droid. These report instance stats into opsdash, and give the instance a connection to our general AMQP backbone.
|
5
|
+
|
6
|
+
Setup
|
7
|
+
-----
|
8
|
+
|
9
|
+
To use droid from an app or component, add the following to that app's Gemfile:
|
10
|
+
|
11
|
+
gem 'droid', VERSION
|
12
|
+
|
13
|
+
Set VERSION to the [current version](http://rubygems.org/gems/droid).
|
14
|
+
|
15
|
+
Legacy setup
|
16
|
+
------------
|
17
|
+
|
18
|
+
Our pre-gem was to check out droid into /usr/local/droid on all instance types.
|
19
|
+
This is deprecated.
|
20
|
+
|
21
|
+
Releasing a new droid gem
|
22
|
+
-------------------------
|
23
|
+
|
24
|
+
$ gem install jeweler
|
25
|
+
$ echo "vX.X.X" > VERSION
|
26
|
+
$ rake build
|
27
|
+
$ git commit -am "vX.X.X"
|
28
|
+
$ git tag vX.X.X
|
29
|
+
$ git push origin master --tags
|
30
|
+
$ gem push pkg/droid-X.X.X.gem
|
31
|
+
|
32
|
+
Then increment the version number in the Gemfile for any component that you
|
33
|
+
wish to use the new version.
|
34
|
+
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: droid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 57
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 9
|
9
|
-
-
|
10
|
-
version: 0.9.
|
9
|
+
- 1
|
10
|
+
version: 0.9.1
|
11
11
|
platform: ruby
|
12
12
|
authors: []
|
13
13
|
|
@@ -15,8 +15,8 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-06
|
19
|
-
default_executable:
|
18
|
+
date: 2010-07-06 00:00:00 -07:00
|
19
|
+
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
22
|
name: json_pure
|
@@ -48,12 +48,12 @@ dependencies:
|
|
48
48
|
version_requirements: *id002
|
49
49
|
description:
|
50
50
|
email:
|
51
|
-
executables:
|
52
|
-
- conf
|
53
|
-
extensions: []
|
51
|
+
executables: []
|
54
52
|
|
55
|
-
|
53
|
+
extensions: []
|
56
54
|
|
55
|
+
extra_rdoc_files:
|
56
|
+
- README.md
|
57
57
|
files:
|
58
58
|
- lib/droid.rb
|
59
59
|
- lib/droid/sync.rb
|
@@ -62,18 +62,15 @@ files:
|
|
62
62
|
- lib/memcache_cluster.rb
|
63
63
|
- lib/stats.rb
|
64
64
|
- lib/utilization.rb
|
65
|
-
- speaker/droid_speaker.rb
|
66
|
-
- speaker/speak
|
67
|
-
- speaker/test.rb
|
68
65
|
- vendor/logger_client/Rakefile
|
69
66
|
- vendor/logger_client/init.rb
|
70
67
|
- vendor/logger_client/lib/logger_client.rb
|
71
68
|
- vendor/logger_client/test.rb
|
72
|
-
-
|
69
|
+
- README.md
|
73
70
|
- test/base.rb
|
74
71
|
- test/droid_test.rb
|
72
|
+
- test/heroku_droid_test.rb
|
75
73
|
- test/wait_for_port_test.rb
|
76
|
-
- bin/conf
|
77
74
|
has_rdoc: true
|
78
75
|
homepage:
|
79
76
|
licenses: []
|
@@ -109,7 +106,7 @@ signing_key:
|
|
109
106
|
specification_version: 3
|
110
107
|
summary: AMQP wrapper
|
111
108
|
test_files:
|
112
|
-
- test/heroku_droid_test.rb
|
113
109
|
- test/base.rb
|
114
110
|
- test/droid_test.rb
|
111
|
+
- test/heroku_droid_test.rb
|
115
112
|
- test/wait_for_port_test.rb
|
data/bin/conf
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require 'socket'
|
3
|
-
|
4
|
-
def wait_for_tcp_port(port, options={})
|
5
|
-
options[:timeout] ||= 30
|
6
|
-
options[:host] ||= "localhost"
|
7
|
-
|
8
|
-
options[:timeout].times do
|
9
|
-
begin
|
10
|
-
x = TCPSocket.new(options[:host], port)
|
11
|
-
x.close
|
12
|
-
return
|
13
|
-
rescue
|
14
|
-
sleep 1
|
15
|
-
next
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
raise "#{options[:host]}:#{port} did not come up after #{options[:timeout]} seconds"
|
20
|
-
end
|
21
|
-
|
22
|
-
puts "Waiting for RabbitMQ"
|
23
|
-
wait_for_tcp_port(5672)
|
24
|
-
|
25
|
-
puts `rabbitmqctl add_vhost /heroku`
|
26
|
-
|
27
|
-
%w[hermes core].each do |agent|
|
28
|
-
puts `rabbitmqctl add_user #{agent} thisisheroku!`
|
29
|
-
puts `rabbitmqctl set_permissions -p /heroku #{agent} \".*\" \".*\" \".*\"`
|
30
|
-
end
|
31
|
-
|
data/speaker/droid_speaker.rb
DELETED
@@ -1,79 +0,0 @@
|
|
1
|
-
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../vendor/json_pure-1.1.3/lib'
|
2
|
-
require 'json'
|
3
|
-
require 'drb'
|
4
|
-
require 'timeout'
|
5
|
-
|
6
|
-
class DroidSpeaker
|
7
|
-
|
8
|
-
def self.drb_connect(port)
|
9
|
-
DRb.start_service()
|
10
|
-
@drb = DRbObject.new(nil,"druby://localhost:#{port}")
|
11
|
-
end
|
12
|
-
|
13
|
-
def self.drb_cast(topic, payload, &p)
|
14
|
-
@drb.publish(topic, payload, &p)
|
15
|
-
end
|
16
|
-
|
17
|
-
def self.drb_call(topic, payload)
|
18
|
-
## this is the best stupid trick I could think of the force blocking
|
19
|
-
lock = Thread.new { sleep 9999 }
|
20
|
-
@r = nil
|
21
|
-
@drb.publish(topic, payload) do |result|
|
22
|
-
@r = result
|
23
|
-
lock.kill
|
24
|
-
end
|
25
|
-
lock.join
|
26
|
-
@r
|
27
|
-
end
|
28
|
-
|
29
|
-
def self.send(topic, payload, &p)
|
30
|
-
i = new
|
31
|
-
i.send(topic, payload, &p)
|
32
|
-
i.flush
|
33
|
-
end
|
34
|
-
|
35
|
-
def self.start
|
36
|
-
i = new
|
37
|
-
yield(i)
|
38
|
-
i.flush
|
39
|
-
end
|
40
|
-
|
41
|
-
def initialize
|
42
|
-
@message = nil
|
43
|
-
@callback = nil
|
44
|
-
end
|
45
|
-
|
46
|
-
def send(topic, payload, &blk)
|
47
|
-
if defined?(Log) and event_id = Log.default_options[:event_id]
|
48
|
-
payload.merge!(:event_hash => event_id)
|
49
|
-
end
|
50
|
-
|
51
|
-
attrs = { :topic => topic, :payload => payload }
|
52
|
-
if blk # this message should be replied
|
53
|
-
attrs.merge!(:has_reply => true)
|
54
|
-
@callback = blk
|
55
|
-
end
|
56
|
-
@message = attrs
|
57
|
-
end
|
58
|
-
|
59
|
-
class MessageError < RuntimeError; end
|
60
|
-
|
61
|
-
def flush
|
62
|
-
out = ''
|
63
|
-
IO.popen("#{File.dirname(__FILE__)}/../speaker/speak 2>/dev/null", 'w+') do |io|
|
64
|
-
io.puts @message.to_json
|
65
|
-
out = io.read
|
66
|
-
end
|
67
|
-
begin
|
68
|
-
response = JSON.parse(out)
|
69
|
-
response.delete('event_hash')
|
70
|
-
@callback.call(response) if @callback
|
71
|
-
rescue JSON::ParserError
|
72
|
-
if out.include?('Timeout::Error')
|
73
|
-
raise Timeout::Error, "Timed out while waiting for a response for #{@message[:topic]}"
|
74
|
-
else
|
75
|
-
raise MessageError, out
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
data/speaker/speak
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
begin
|
4
|
-
$:.unshift '/usr/local/droid/lib'
|
5
|
-
require 'heroku_droid'
|
6
|
-
|
7
|
-
msg = JSON.load(gets)
|
8
|
-
|
9
|
-
Timeout.timeout(10) do
|
10
|
-
HerokuDroid.new('Droid Speaker', :standard_topics => false) do |droid|
|
11
|
-
if msg['has_reply']
|
12
|
-
@event_hash = msg['payload']['event_hash'] ||= Droid::Basic.new(droid).event_hash
|
13
|
-
droid.listen4('event.error') do |d|
|
14
|
-
if d.headers[:event_hash] == @event_hash
|
15
|
-
puts "Message #{msg['topic']} failed: see event #{@event_hash}"
|
16
|
-
Droid.stop_safe
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
droid.publish(msg['topic'], msg['payload']) do |d|
|
21
|
-
puts d.params.to_json
|
22
|
-
Droid.stop_safe
|
23
|
-
end
|
24
|
-
else
|
25
|
-
droid.publish(msg['topic'], msg['payload'])
|
26
|
-
puts({}.to_json)
|
27
|
-
Droid.stop_safe
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
rescue Object => e
|
32
|
-
puts "#{e.class}: #{e.message}\n\t#{e.backtrace.join("\n\t")}"
|
33
|
-
end
|
data/speaker/test.rb
DELETED
@@ -1,58 +0,0 @@
|
|
1
|
-
Thread.new do
|
2
|
-
require File.dirname(__FILE__) + '/../lib/heroku_droid'
|
3
|
-
HerokuDroid.new('Droid speaker test') do |droid|
|
4
|
-
droid.listen4('speaker.test') do |msg|
|
5
|
-
if msg['marco'] == 1
|
6
|
-
puts "Got 'marco', returning 'polo'..."
|
7
|
-
msg.reply('polo' => 1)
|
8
|
-
else
|
9
|
-
puts "Bad payload"
|
10
|
-
msg.reply('error' => 1)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
droid.listen4('speaker.raise') do |msg|
|
14
|
-
raise "droid raised exception"
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
sleep 2
|
20
|
-
|
21
|
-
require File.dirname(__FILE__) + '/droid_speaker'
|
22
|
-
|
23
|
-
puts "\nTest 1: Sending simple message"
|
24
|
-
DroidSpeaker.send('fire.and.forget', 'val' => 1)
|
25
|
-
puts "\tSuccess!"
|
26
|
-
|
27
|
-
puts "\nTest 2: Sending and receiving response"
|
28
|
-
DroidSpeaker.send('speaker.test', 'marco' => 1) do |r|
|
29
|
-
if r['polo'] == 1
|
30
|
-
puts "\tSuccess!"
|
31
|
-
else
|
32
|
-
puts "\tFailed, result: #{r.inspect}"
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
puts "\nTest 3: Exceptions"
|
37
|
-
begin
|
38
|
-
DroidSpeaker.send('speaker.raise', {}) do |r|
|
39
|
-
puts "\tFailed, expected exception"
|
40
|
-
end
|
41
|
-
rescue DroidSpeaker::MessageError => e
|
42
|
-
if e.message =~ /event \w+/
|
43
|
-
puts "\tSuccess!"
|
44
|
-
else
|
45
|
-
puts "\tFailed, droid speaker raised #{e.message}"
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
puts "\nTest 4: Timeout"
|
50
|
-
begin
|
51
|
-
DroidSpeaker.send('dont.reply', {}) do |r|
|
52
|
-
puts "\tFailed, didnt expect a response"
|
53
|
-
end
|
54
|
-
rescue Timeout::Error
|
55
|
-
puts "\tSuccess!"
|
56
|
-
rescue Exception => e
|
57
|
-
puts "\tFailed, expected Timeout::Error, got #{e.class.name}"
|
58
|
-
end
|