dripdrop 0.9.6 → 0.9.8
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.
- data/Rakefile +1 -2
- data/VERSION +1 -1
- data/dripdrop.gemspec +58 -64
- data/example/http.rb +1 -1
- data/lib/dripdrop/handlers/base.rb +21 -0
- data/lib/dripdrop/handlers/http.rb +47 -65
- data/lib/dripdrop/handlers/websockets.rb +23 -19
- data/lib/dripdrop/handlers/zeromq.rb +21 -13
- data/lib/dripdrop/message.rb +48 -25
- data/lib/dripdrop/node/nodelet.rb +6 -1
- data/lib/dripdrop/node.rb +5 -4
- data/spec/message_spec.rb +2 -7
- data/spec/node/http_spec.rb +2 -0
- data/spec/node/websocket_spec.rb +14 -4
- data/spec/node_spec.rb +1 -0
- data/spec/spec_helper.rb +2 -0
- metadata +134 -184
- data/.gitignore +0 -26
data/Rakefile
CHANGED
@@ -13,9 +13,8 @@ begin
|
|
13
13
|
gem.add_dependency('ffi-rzmq', '>= 0.7.1')
|
14
14
|
gem.add_dependency('eventmachine', '>= 0.12.10')
|
15
15
|
gem.add_dependency('em-websocket')
|
16
|
-
gem.add_dependency('
|
16
|
+
gem.add_dependency('eventmachine_httpserver')
|
17
17
|
gem.add_dependency('em-zeromq', '>= 0.1.2')
|
18
|
-
gem.add_dependency('msgpack')
|
19
18
|
gem.add_dependency('yajl-ruby')
|
20
19
|
end
|
21
20
|
Jeweler::GemcutterTasks.new
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.9.
|
1
|
+
0.9.8
|
data/dripdrop.gemspec
CHANGED
@@ -1,112 +1,106 @@
|
|
1
1
|
# Generated by jeweler
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{dripdrop}
|
8
|
-
s.version = "0.9.
|
8
|
+
s.version = "0.9.8"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Andrew Cholakian"]
|
12
|
-
s.date = %q{2011-02-
|
12
|
+
s.date = %q{2011-02-15}
|
13
13
|
s.description = %q{Evented framework for ZeroMQ and EventMachine Apps. }
|
14
14
|
s.email = %q{andrew@andrewvc.com}
|
15
15
|
s.extra_rdoc_files = [
|
16
16
|
"LICENSE",
|
17
|
-
|
17
|
+
"README.md"
|
18
18
|
]
|
19
19
|
s.files = [
|
20
20
|
".document",
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
"spec/spec_helper.rb"
|
21
|
+
"LICENSE",
|
22
|
+
"README.md",
|
23
|
+
"Rakefile",
|
24
|
+
"VERSION",
|
25
|
+
"doc_img/topology.png",
|
26
|
+
"dripdrop.gemspec",
|
27
|
+
"example/agent_test.rb",
|
28
|
+
"example/combined.rb",
|
29
|
+
"example/complex/README",
|
30
|
+
"example/complex/client.rb",
|
31
|
+
"example/complex/server.rb",
|
32
|
+
"example/complex/service.rb",
|
33
|
+
"example/complex/websocket.rb",
|
34
|
+
"example/http.rb",
|
35
|
+
"example/pubsub.rb",
|
36
|
+
"example/pushpull.rb",
|
37
|
+
"example/subclass.rb",
|
38
|
+
"example/xreq_xrep.rb",
|
39
|
+
"js/dripdrop.html",
|
40
|
+
"js/dripdrop.js",
|
41
|
+
"js/qunit.css",
|
42
|
+
"js/qunit.js",
|
43
|
+
"lib/dripdrop.rb",
|
44
|
+
"lib/dripdrop/agent.rb",
|
45
|
+
"lib/dripdrop/handlers/base.rb",
|
46
|
+
"lib/dripdrop/handlers/http.rb",
|
47
|
+
"lib/dripdrop/handlers/websockets.rb",
|
48
|
+
"lib/dripdrop/handlers/zeromq.rb",
|
49
|
+
"lib/dripdrop/message.rb",
|
50
|
+
"lib/dripdrop/node.rb",
|
51
|
+
"lib/dripdrop/node/nodelet.rb",
|
52
|
+
"spec/gimite-websocket.rb",
|
53
|
+
"spec/message_spec.rb",
|
54
|
+
"spec/node/http_spec.rb",
|
55
|
+
"spec/node/nodelet_spec.rb",
|
56
|
+
"spec/node/routing_spec.rb",
|
57
|
+
"spec/node/websocket_spec.rb",
|
58
|
+
"spec/node/zmq_pushpull_spec.rb",
|
59
|
+
"spec/node/zmq_xrepxreq_spec.rb",
|
60
|
+
"spec/node_spec.rb",
|
61
|
+
"spec/spec_helper.rb"
|
63
62
|
]
|
64
63
|
s.homepage = %q{http://github.com/andrewvc/dripdrop}
|
65
|
-
s.rdoc_options = ["--charset=UTF-8"]
|
66
64
|
s.require_paths = ["lib"]
|
67
|
-
s.rubygems_version = %q{1.
|
65
|
+
s.rubygems_version = %q{1.5.1}
|
68
66
|
s.summary = %q{Evented framework for ZeroMQ and EventMachine Apps.}
|
69
67
|
s.test_files = [
|
68
|
+
"spec/gimite-websocket.rb",
|
69
|
+
"spec/message_spec.rb",
|
70
|
+
"spec/node/http_spec.rb",
|
71
|
+
"spec/node/nodelet_spec.rb",
|
72
|
+
"spec/node/routing_spec.rb",
|
73
|
+
"spec/node/websocket_spec.rb",
|
74
|
+
"spec/node/zmq_pushpull_spec.rb",
|
75
|
+
"spec/node/zmq_xrepxreq_spec.rb",
|
70
76
|
"spec/node_spec.rb",
|
71
|
-
|
72
|
-
"spec/gimite-websocket.rb",
|
73
|
-
"spec/message_spec.rb",
|
74
|
-
"spec/node/nodelet_spec.rb",
|
75
|
-
"spec/node/zmq_pushpull_spec.rb",
|
76
|
-
"spec/node/zmq_xrepxreq_spec.rb",
|
77
|
-
"spec/node/routing_spec.rb",
|
78
|
-
"spec/node/websocket_spec.rb",
|
79
|
-
"spec/node/http_spec.rb"
|
77
|
+
"spec/spec_helper.rb"
|
80
78
|
]
|
81
79
|
|
82
80
|
if s.respond_to? :specification_version then
|
83
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
84
81
|
s.specification_version = 3
|
85
82
|
|
86
83
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
87
84
|
s.add_runtime_dependency(%q<ffi-rzmq>, [">= 0.7.1"])
|
88
85
|
s.add_runtime_dependency(%q<eventmachine>, [">= 0.12.10"])
|
89
86
|
s.add_runtime_dependency(%q<em-websocket>, [">= 0"])
|
90
|
-
s.add_runtime_dependency(%q<
|
87
|
+
s.add_runtime_dependency(%q<eventmachine_httpserver>, [">= 0"])
|
91
88
|
s.add_runtime_dependency(%q<em-zeromq>, [">= 0.1.2"])
|
92
|
-
s.add_runtime_dependency(%q<msgpack>, [">= 0"])
|
93
89
|
s.add_runtime_dependency(%q<yajl-ruby>, [">= 0"])
|
94
90
|
else
|
95
91
|
s.add_dependency(%q<ffi-rzmq>, [">= 0.7.1"])
|
96
92
|
s.add_dependency(%q<eventmachine>, [">= 0.12.10"])
|
97
93
|
s.add_dependency(%q<em-websocket>, [">= 0"])
|
98
|
-
s.add_dependency(%q<
|
94
|
+
s.add_dependency(%q<eventmachine_httpserver>, [">= 0"])
|
99
95
|
s.add_dependency(%q<em-zeromq>, [">= 0.1.2"])
|
100
|
-
s.add_dependency(%q<msgpack>, [">= 0"])
|
101
96
|
s.add_dependency(%q<yajl-ruby>, [">= 0"])
|
102
97
|
end
|
103
98
|
else
|
104
99
|
s.add_dependency(%q<ffi-rzmq>, [">= 0.7.1"])
|
105
100
|
s.add_dependency(%q<eventmachine>, [">= 0.12.10"])
|
106
101
|
s.add_dependency(%q<em-websocket>, [">= 0"])
|
107
|
-
s.add_dependency(%q<
|
102
|
+
s.add_dependency(%q<eventmachine_httpserver>, [">= 0"])
|
108
103
|
s.add_dependency(%q<em-zeromq>, [">= 0.1.2"])
|
109
|
-
s.add_dependency(%q<msgpack>, [">= 0"])
|
110
104
|
s.add_dependency(%q<yajl-ruby>, [">= 0"])
|
111
105
|
end
|
112
106
|
end
|
data/example/http.rb
CHANGED
@@ -1,6 +1,27 @@
|
|
1
1
|
class DripDrop
|
2
2
|
class BaseHandler
|
3
3
|
|
4
|
+
def on_error(&block)
|
5
|
+
@err_cbak = block
|
6
|
+
end
|
7
|
+
|
8
|
+
def handle_error(exception,*extra)
|
9
|
+
if @err_cbak
|
10
|
+
begin
|
11
|
+
@err_cbak.call(exception,*extra)
|
12
|
+
rescue StandardError => e
|
13
|
+
print_exception(e)
|
14
|
+
end
|
15
|
+
else
|
16
|
+
print_exception(e)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def print_exception(exception)
|
21
|
+
$stderr.write exception.message
|
22
|
+
$stderr.write exception.backtrace.join("\t\n")
|
23
|
+
end
|
24
|
+
|
4
25
|
private
|
5
26
|
# Normalize Hash objs and DripDrop::Message objs into DripDrop::Message objs
|
6
27
|
def dd_messagify(message)
|
@@ -1,89 +1,64 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
1
|
+
require 'eventmachine'
|
2
|
+
require 'evma_httpserver'
|
3
3
|
|
4
4
|
class DripDrop
|
5
|
-
class
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
body.each do |chunk|
|
10
|
-
@body_callback.call(chunk)
|
11
|
-
end
|
5
|
+
class HTTPServerHandlerResponse < BaseHandler
|
6
|
+
attr_reader :em_response, :message_class
|
7
|
+
def initialize(em_response)
|
8
|
+
@em_response = em_response
|
12
9
|
end
|
13
10
|
|
14
|
-
def
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
msg = dd_messagify(raw_msg)
|
20
|
-
if msg.is_a?(DripDrop::Message)
|
21
|
-
json = msg.encode_json
|
22
|
-
self.call([json])
|
23
|
-
self.succeed
|
24
|
-
else
|
25
|
-
raise "Message Type '#{msg.class}' not supported"
|
26
|
-
end
|
11
|
+
def send_message(message)
|
12
|
+
message = dd_messagify(message)
|
13
|
+
@em_response.status = 200
|
14
|
+
@em_response.content = message.json_encoded
|
15
|
+
@em_response.send_response
|
27
16
|
end
|
28
17
|
end
|
29
|
-
|
30
|
-
class
|
18
|
+
|
19
|
+
class HTTPEMServer < EM::Connection
|
20
|
+
include EM::HttpServer
|
31
21
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
22
|
+
def initialize(dd_handler)
|
23
|
+
@dd_handler = dd_handler
|
24
|
+
end
|
25
|
+
|
26
|
+
def post_init
|
27
|
+
super
|
28
|
+
no_environment_strings
|
37
29
|
end
|
38
30
|
|
39
|
-
def
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
msg = DripDrop::Message.decode_json(env['rack.input'].read)
|
48
|
-
@recv_cbak.call(msg,body,env)
|
49
|
-
else
|
50
|
-
raise "Unsupported message type #{@msg_format}"
|
51
|
-
end
|
52
|
-
end
|
31
|
+
def process_http_request
|
32
|
+
begin
|
33
|
+
message = @dd_handler.message_class.decode_json(@http_post_content)
|
34
|
+
response = EM::DelegatedHttpResponse.new(self)
|
35
|
+
dd_response = HTTPServerHandlerResponse.new(response)
|
36
|
+
@dd_handler.recv_cbak.call(message, dd_response) if @dd_handler.recv_cbak
|
37
|
+
rescue StandardError => e
|
38
|
+
handler_error(e)
|
53
39
|
end
|
54
|
-
|
55
|
-
AsyncResponse
|
56
40
|
end
|
57
41
|
end
|
58
|
-
|
42
|
+
|
59
43
|
class HTTPServerHandler < BaseHandler
|
60
|
-
attr_reader :address, :opts
|
44
|
+
attr_reader :address, :opts, :message_class, :uri, :recv_cbak
|
61
45
|
|
62
46
|
def initialize(uri,opts={})
|
63
|
-
@uri
|
64
|
-
@
|
65
|
-
@
|
47
|
+
@uri = uri
|
48
|
+
@uri_path = @uri.path.empty? ? '/' : @uri.path
|
49
|
+
@address = uri.to_s
|
50
|
+
@opts = opts
|
66
51
|
@message_class = @opts[:message_class] || DripDrop.default_message_class
|
67
52
|
end
|
68
53
|
|
69
54
|
def on_recv(msg_format=:dripdrop_json,&block)
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
uri_path = @uri.path.empty? ? '/' : @uri.path
|
75
|
-
|
76
|
-
Thin::Server.start(@uri.host, @uri.port) do
|
77
|
-
map uri_path do
|
78
|
-
run HTTPApp.new(msg_format,&block)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
rescue Exception => e
|
82
|
-
$stderr.write "Error in Thin server: #{e.message}\n#{e.backtrace.join("\n")}"
|
83
|
-
end
|
55
|
+
@recv_cbak = block
|
56
|
+
@conn = EM.start_server(@uri.host, @uri.port, HTTPEMServer, self)
|
57
|
+
self
|
84
58
|
end
|
85
59
|
end
|
86
60
|
|
61
|
+
|
87
62
|
class HTTPClientHandler < BaseHandler
|
88
63
|
attr_reader :address, :opts
|
89
64
|
|
@@ -106,7 +81,14 @@ class DripDrop
|
|
106
81
|
:content => dd_message.encode_json
|
107
82
|
)
|
108
83
|
req.callback do |response|
|
109
|
-
|
84
|
+
begin
|
85
|
+
# Hack to fix evma http
|
86
|
+
response[:content] =~ /(\{.*\})/
|
87
|
+
fixed_body = $1
|
88
|
+
block.call(@message_class.decode(fixed_body)) if block
|
89
|
+
rescue StandardError => e
|
90
|
+
handle_error(e)
|
91
|
+
end
|
110
92
|
end
|
111
93
|
else
|
112
94
|
raise "Unsupported message type '#{dd_message.class}'"
|
@@ -1,37 +1,45 @@
|
|
1
1
|
require 'em-websocket'
|
2
|
-
|
2
|
+
|
3
3
|
|
4
4
|
class DripDrop
|
5
5
|
class WebSocketHandler < BaseHandler
|
6
|
+
class SocketError < StandardError; attr_accessor :reason, :connection end
|
7
|
+
|
6
8
|
attr_reader :ws, :address, :thread
|
7
9
|
|
8
10
|
def initialize(address,opts={})
|
9
|
-
@
|
10
|
-
|
11
|
-
|
11
|
+
@opts = opts
|
12
|
+
@raw = false #Deal in strings or ZMQ::Message objects
|
13
|
+
host, port = address.host, address.port.to_i
|
14
|
+
@message_class = @opts[:message_class] || DripDrop.default_message_class
|
15
|
+
@debug = @opts[:debug] || false
|
12
16
|
|
13
17
|
EventMachine::WebSocket.start(:host => host,:port => port,:debug => @debug) do |ws|
|
14
18
|
#A WebSocketHandler:Connection gets passed to all callbacks
|
15
19
|
dd_conn = Connection.new(ws)
|
16
20
|
|
17
|
-
ws.onopen
|
21
|
+
ws.onopen { @onopen_handler.call(dd_conn) if @onopen_handler }
|
18
22
|
ws.onclose { @onclose_handler.call(dd_conn) if @onclose_handler }
|
19
|
-
ws.onerror {|reason|
|
23
|
+
ws.onerror {|reason|
|
24
|
+
e = SocketError.new
|
25
|
+
e.reason = reason
|
26
|
+
e.connection = dd_conn
|
27
|
+
handle_error(e)
|
28
|
+
}
|
20
29
|
|
21
|
-
ws.onmessage
|
30
|
+
ws.onmessage { |message|
|
22
31
|
if @onmessage_handler
|
23
32
|
begin
|
24
|
-
message =
|
33
|
+
message = @message_class.decode(message) unless @raw
|
34
|
+
@onmessage_handler.call(message,dd_conn)
|
25
35
|
rescue StandardError => e
|
26
|
-
|
36
|
+
handle_error(e,dd_conn)
|
27
37
|
end
|
28
|
-
|
29
|
-
@onmessage_handler.call(message,dd_conn)
|
30
38
|
end
|
31
|
-
|
39
|
+
}
|
32
40
|
end
|
33
41
|
end
|
34
|
-
|
42
|
+
|
35
43
|
def on_recv(&block)
|
36
44
|
@raw = false
|
37
45
|
@onmessage_handler = block
|
@@ -53,11 +61,6 @@ class DripDrop
|
|
53
61
|
@onclose_handler = block
|
54
62
|
self
|
55
63
|
end
|
56
|
-
|
57
|
-
def on_error(&block)
|
58
|
-
@onerror_handler = block
|
59
|
-
self
|
60
|
-
end
|
61
64
|
end
|
62
65
|
|
63
66
|
class WebSocketHandler::Connection < BaseHandler
|
@@ -69,7 +72,8 @@ class DripDrop
|
|
69
72
|
end
|
70
73
|
|
71
74
|
def send_message(message)
|
72
|
-
|
75
|
+
encoded_message = dd_messagify(message).encoded
|
76
|
+
@ws.send(encoded_message)
|
73
77
|
end
|
74
78
|
end
|
75
79
|
end
|
@@ -38,7 +38,7 @@ class DripDrop
|
|
38
38
|
def initialize(*args)
|
39
39
|
super(*args)
|
40
40
|
@send_queue = []
|
41
|
-
@send_queue_enabled =
|
41
|
+
@send_queue_enabled = false
|
42
42
|
end
|
43
43
|
|
44
44
|
def on_writable(socket)
|
@@ -48,7 +48,7 @@ class DripDrop
|
|
48
48
|
num_parts = message.length
|
49
49
|
message.each_with_index do |part,i|
|
50
50
|
# Set the multi-part flag unless this is the last message
|
51
|
-
flags = (i + 1 < num_parts ? ZMQ::SNDMORE : 0)
|
51
|
+
flags = (i + 1 < num_parts ? ZMQ::SNDMORE : 0) | ZMQ::NOBLOCK
|
52
52
|
|
53
53
|
if part.class == ZMQ::Message
|
54
54
|
socket.send(part, flags)
|
@@ -104,15 +104,19 @@ class DripDrop
|
|
104
104
|
end
|
105
105
|
|
106
106
|
def on_readable(socket, messages)
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
107
|
+
begin
|
108
|
+
case @msg_format
|
109
|
+
when :raw
|
110
|
+
@recv_cbak.call(messages)
|
111
|
+
when :dripdrop
|
112
|
+
raise "Expected message in one part" if messages.length > 1
|
113
|
+
body = messages.shift.copy_out_string
|
114
|
+
@recv_cbak.call(decode_message(body))
|
115
|
+
else
|
116
|
+
raise "Unknown message format '#{@msg_format}'"
|
117
|
+
end
|
118
|
+
rescue StandardError => e
|
119
|
+
handle_error(e)
|
116
120
|
end
|
117
121
|
end
|
118
122
|
|
@@ -255,8 +259,12 @@ class DripDrop
|
|
255
259
|
end
|
256
260
|
|
257
261
|
def on_readable(socket, messages)
|
258
|
-
|
259
|
-
|
262
|
+
begin
|
263
|
+
# Strip out empty delimiter
|
264
|
+
super(socket, messages[1..-1])
|
265
|
+
rescue StandardError => e
|
266
|
+
handle_error(e)
|
267
|
+
end
|
260
268
|
end
|
261
269
|
end
|
262
270
|
end
|
data/lib/dripdrop/message.rb
CHANGED
@@ -1,9 +1,15 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
|
3
|
-
|
2
|
+
|
3
|
+
if PLATFORM == 'java'
|
4
|
+
require 'json'
|
5
|
+
else
|
6
|
+
require 'yajl'
|
7
|
+
require 'yajl/json_gem'
|
8
|
+
end
|
4
9
|
|
5
10
|
class DripDrop
|
6
11
|
class WrongMessageClassError < StandardError; end
|
12
|
+
|
7
13
|
# DripDrop::Message messages are exchanged between all tiers in the architecture
|
8
14
|
# A Message is composed of a name, head, and body, and should be restricted to types that
|
9
15
|
# can be readily encoded to JSON.
|
@@ -40,12 +46,12 @@ class DripDrop
|
|
40
46
|
|
41
47
|
# The encoded message, ready to be sent across the wire via ZMQ
|
42
48
|
def encoded
|
43
|
-
self.to_hash.
|
49
|
+
self.to_hash.to_json
|
44
50
|
end
|
45
51
|
|
46
|
-
# Encodes the hash represntation of the message to JSON
|
52
|
+
# (Deprecated) Encodes the hash represntation of the message to JSON
|
47
53
|
def json_encoded
|
48
|
-
|
54
|
+
encoded
|
49
55
|
end
|
50
56
|
# (Deprecated, use json_encoded)
|
51
57
|
def encode_json; json_encoded; end
|
@@ -73,40 +79,56 @@ class DripDrop
|
|
73
79
|
|
74
80
|
def self.recreate_message(hash)
|
75
81
|
raise ArgumentError, "Message missing head: #{hash.inspect}" unless hash['head']
|
76
|
-
|
77
|
-
|
82
|
+
|
83
|
+
klass = (hash['head'] && hash['head']['message_class']) ? constantize(hash['head']['message_class']) : nil
|
84
|
+
if klass && (!(klass == self) && !self.subclasses.include?(klass))
|
85
|
+
raise DripDrop::WrongMessageClassError, "Wrong message class '#{klass}', expected '#{self}'"
|
86
|
+
end
|
87
|
+
|
88
|
+
klass ? klass.from_hash(hash) : self.from_hash(hash)
|
78
89
|
end
|
79
90
|
|
80
91
|
# Parses an already encoded string
|
81
92
|
def self.decode(msg)
|
82
93
|
return nil if msg.nil? || msg.empty?
|
83
|
-
|
84
|
-
|
85
|
-
if msg.class.to_s == 'ZMQ::Message'
|
86
|
-
msg = msg.copy_out_string
|
87
|
-
return nil if msg.empty?
|
88
|
-
end
|
89
|
-
decoded = MessagePack.unpack(msg)
|
94
|
+
|
95
|
+
decoded = JSON.parse(msg)
|
90
96
|
self.recreate_message(decoded)
|
91
97
|
end
|
92
98
|
|
93
99
|
# (Deprecated). Use decode instead
|
94
100
|
def self.parse(msg); self.decode(msg) end
|
95
101
|
|
96
|
-
# Decodes a string containing a JSON representation of a message
|
102
|
+
# (Deprecated) Decodes a string containing a JSON representation of a message
|
97
103
|
def self.decode_json(str)
|
104
|
+
self.decode(str)
|
105
|
+
end
|
106
|
+
|
107
|
+
def self.constantize(str)
|
98
108
|
begin
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
109
|
+
str.split('::').inject(Object) {|memo,name|
|
110
|
+
memo = memo.const_get(name); memo
|
111
|
+
}
|
112
|
+
rescue NameError => e
|
113
|
+
nil
|
103
114
|
end
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
115
|
+
end
|
116
|
+
|
117
|
+
#Used for reconstructing messages
|
118
|
+
def self.subclasses(direct = false)
|
119
|
+
classes = []
|
120
|
+
if direct
|
121
|
+
ObjectSpace.each_object(Class) do |c|
|
122
|
+
next unless c.superclass == self
|
123
|
+
classes << c
|
124
|
+
end
|
125
|
+
else
|
126
|
+
ObjectSpace.each_object(Class) do |c|
|
127
|
+
next unless c.ancestors.include?(self) and (c != self)
|
128
|
+
classes << c
|
129
|
+
end
|
130
|
+
end
|
131
|
+
classes
|
110
132
|
end
|
111
133
|
end
|
112
134
|
|
@@ -157,6 +179,7 @@ class DripDrop
|
|
157
179
|
end
|
158
180
|
end
|
159
181
|
|
182
|
+
|
160
183
|
#Including this module into your subclass will automatically register the class
|
161
184
|
#with AutoMessageClass
|
162
185
|
module SubclassedMessage
|
@@ -3,10 +3,15 @@ class DripDrop::Node
|
|
3
3
|
class Nodelet
|
4
4
|
attr_accessor :name, :routing
|
5
5
|
|
6
|
-
def initialize(ctx, name,
|
6
|
+
def initialize(ctx, name, *configure_args)
|
7
7
|
@ctx = ctx
|
8
8
|
@name = name
|
9
9
|
@internal_routing = {}
|
10
|
+
configure(*configure_args)
|
11
|
+
end
|
12
|
+
|
13
|
+
def configure(*args)
|
14
|
+
# Do nothing!
|
10
15
|
end
|
11
16
|
|
12
17
|
def route(name,handler_type,*handler_args)
|
data/lib/dripdrop/node.rb
CHANGED
@@ -138,8 +138,8 @@ class DripDrop
|
|
138
138
|
#
|
139
139
|
# If you specify a block, Nodelet#action will be ignored and the block
|
140
140
|
# will be run
|
141
|
-
def nodelet(name,klass=Nodelet,&block)
|
142
|
-
nlet = @nodelets[name] ||= klass.new(self,name
|
141
|
+
def nodelet(name,klass=Nodelet,*configure_args,&block)
|
142
|
+
nlet = @nodelets[name] ||= klass.new(self,name,*configure_args)
|
143
143
|
if block
|
144
144
|
block.call(nlet)
|
145
145
|
else
|
@@ -147,7 +147,7 @@ class DripDrop
|
|
147
147
|
end
|
148
148
|
nlet
|
149
149
|
end
|
150
|
-
|
150
|
+
|
151
151
|
# Creates a ZMQ::SUB type socket. Can only receive messages via +on_recv+.
|
152
152
|
# zmq_subscribe sockets have a +topic_filter+ option, which restricts which
|
153
153
|
# messages they can receive. It takes a regexp as an option.
|
@@ -269,7 +269,8 @@ class DripDrop
|
|
269
269
|
end
|
270
270
|
|
271
271
|
# Catch all error handler
|
272
|
-
|
272
|
+
# Global to all DripDrop Nodes
|
273
|
+
def self.error_handler(e)
|
273
274
|
$stderr.write "#{e.class}: #{e.message}\n\t#{e.backtrace.join("\n\t")}"
|
274
275
|
end
|
275
276
|
|
data/spec/message_spec.rb
CHANGED
@@ -40,19 +40,14 @@ describe DripDrop::Message do
|
|
40
40
|
before(:all) do
|
41
41
|
@message, @attrs = create_basic
|
42
42
|
end
|
43
|
-
it "should encode to valid
|
43
|
+
it "should encode to valid JSON hash without error" do
|
44
44
|
enc = @message.encoded
|
45
45
|
enc.should be_a(String)
|
46
|
-
|
46
|
+
JSON.parse(enc).should be_a(Hash)
|
47
47
|
end
|
48
48
|
it "should decode encoded messages without errors" do
|
49
49
|
DripDrop::Message.decode(@message.encoded).should be_a(DripDrop::Message)
|
50
50
|
end
|
51
|
-
it "should encode to valid JSON without error" do
|
52
|
-
enc = @message.json_encoded
|
53
|
-
enc.should be_a(String)
|
54
|
-
JSON.parse(enc).should be_a(Hash)
|
55
|
-
end
|
56
51
|
it "should decode JSON encoded messages without errors" do
|
57
52
|
DripDrop::Message.decode_json(@message.json_encoded).should be_a(DripDrop::Message)
|
58
53
|
end
|
data/spec/node/http_spec.rb
CHANGED
data/spec/node/websocket_spec.rb
CHANGED
@@ -4,6 +4,7 @@ describe "websockets" do
|
|
4
4
|
def websockets_send_messages(to_send,&block)
|
5
5
|
received = []
|
6
6
|
responses = []
|
7
|
+
seen_signatures = Set.new
|
7
8
|
server = nil
|
8
9
|
|
9
10
|
open_message = DripDrop::Message.new('open', :body => 'test')
|
@@ -13,12 +14,13 @@ describe "websockets" do
|
|
13
14
|
|
14
15
|
error_occured = false
|
15
16
|
|
16
|
-
@node = run_reactor(
|
17
|
+
@node = run_reactor(2) do
|
17
18
|
addr = rand_addr('ws')
|
18
19
|
|
19
20
|
server = websocket(addr)
|
20
21
|
server.on_open do |conn|
|
21
22
|
conn.send_message(open_message)
|
23
|
+
seen_signatures << conn.signature
|
22
24
|
end.on_recv do |message,conn|
|
23
25
|
received << message
|
24
26
|
conn.send_message(message)
|
@@ -30,7 +32,7 @@ describe "websockets" do
|
|
30
32
|
|
31
33
|
EM.defer do
|
32
34
|
client = WebSocket.new(addr)
|
33
|
-
open_received = DripDrop::Message.
|
35
|
+
open_received = DripDrop::Message.decode(client.receive)
|
34
36
|
to_send.each do |message|
|
35
37
|
client.send(message.json_encoded)
|
36
38
|
end
|
@@ -41,6 +43,10 @@ describe "websockets" do
|
|
41
43
|
recvd_count += 1
|
42
44
|
end
|
43
45
|
client.close
|
46
|
+
|
47
|
+
# This one only connects to test unique signatures
|
48
|
+
client2 = WebSocket.new(addr)
|
49
|
+
client2.close
|
44
50
|
end
|
45
51
|
|
46
52
|
zmq_subscribe(rand_addr, :bind) {} #Keep zmqmachine happy
|
@@ -48,8 +54,8 @@ describe "websockets" do
|
|
48
54
|
|
49
55
|
{:received => received, :responses => responses,
|
50
56
|
:open_message => open_message, :open_received => open_received,
|
51
|
-
:close_occured => close_occured, :error_occured => error_occured,
|
52
|
-
:handlers => {:server => server }}
|
57
|
+
:close_occured => close_occured, :error_occured => error_occured,
|
58
|
+
:seen_signatures => seen_signatures,:handlers => {:server => server }}
|
53
59
|
end
|
54
60
|
describe "basic sending and receiving" do
|
55
61
|
before(:all) do
|
@@ -84,5 +90,9 @@ describe "websockets" do
|
|
84
90
|
it "should not generate an error event" do
|
85
91
|
@ws_info[:error_occured].should be_false
|
86
92
|
end
|
93
|
+
|
94
|
+
it "should see unique connection signatures for each client" do
|
95
|
+
@ws_info[:seen_signatures].length.should == 2
|
96
|
+
end
|
87
97
|
end
|
88
98
|
end
|
data/spec/node_spec.rb
CHANGED
@@ -72,6 +72,7 @@ describe DripDrop::Node do
|
|
72
72
|
class TestException < StandardError; end
|
73
73
|
|
74
74
|
it "should rescue exceptions in the EM reactor" do
|
75
|
+
pending "Not sure if this feature is a good idea"
|
75
76
|
expectations = an_instance_of(TestException)
|
76
77
|
reactor = run_reactor do
|
77
78
|
self.should_receive(:error_handler).with(expectations)
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,127 +1,84 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dripdrop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 9
|
9
|
-
- 6
|
10
|
-
version: 0.9.6
|
4
|
+
prerelease:
|
5
|
+
version: 0.9.8
|
11
6
|
platform: ruby
|
12
7
|
authors:
|
13
|
-
- Andrew Cholakian
|
8
|
+
- Andrew Cholakian
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
12
|
|
18
|
-
date: 2011-02-
|
13
|
+
date: 2011-02-15 00:00:00 -08:00
|
19
14
|
default_executable:
|
20
15
|
dependencies:
|
21
|
-
- !ruby/object:Gem::Dependency
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
- - ">="
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
hash: 31
|
90
|
-
segments:
|
91
|
-
- 0
|
92
|
-
- 1
|
93
|
-
- 2
|
94
|
-
version: 0.1.2
|
95
|
-
type: :runtime
|
96
|
-
version_requirements: *id005
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: msgpack
|
99
|
-
prerelease: false
|
100
|
-
requirement: &id006 !ruby/object:Gem::Requirement
|
101
|
-
none: false
|
102
|
-
requirements:
|
103
|
-
- - ">="
|
104
|
-
- !ruby/object:Gem::Version
|
105
|
-
hash: 3
|
106
|
-
segments:
|
107
|
-
- 0
|
108
|
-
version: "0"
|
109
|
-
type: :runtime
|
110
|
-
version_requirements: *id006
|
111
|
-
- !ruby/object:Gem::Dependency
|
112
|
-
name: yajl-ruby
|
113
|
-
prerelease: false
|
114
|
-
requirement: &id007 !ruby/object:Gem::Requirement
|
115
|
-
none: false
|
116
|
-
requirements:
|
117
|
-
- - ">="
|
118
|
-
- !ruby/object:Gem::Version
|
119
|
-
hash: 3
|
120
|
-
segments:
|
121
|
-
- 0
|
122
|
-
version: "0"
|
123
|
-
type: :runtime
|
124
|
-
version_requirements: *id007
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: ffi-rzmq
|
18
|
+
prerelease: false
|
19
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
|
+
none: false
|
21
|
+
requirements:
|
22
|
+
- - ">="
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 0.7.1
|
25
|
+
type: :runtime
|
26
|
+
version_requirements: *id001
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: eventmachine
|
29
|
+
prerelease: false
|
30
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
31
|
+
none: false
|
32
|
+
requirements:
|
33
|
+
- - ">="
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: 0.12.10
|
36
|
+
type: :runtime
|
37
|
+
version_requirements: *id002
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: em-websocket
|
40
|
+
prerelease: false
|
41
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: "0"
|
47
|
+
type: :runtime
|
48
|
+
version_requirements: *id003
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: eventmachine_httpserver
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: "0"
|
58
|
+
type: :runtime
|
59
|
+
version_requirements: *id004
|
60
|
+
- !ruby/object:Gem::Dependency
|
61
|
+
name: em-zeromq
|
62
|
+
prerelease: false
|
63
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.1.2
|
69
|
+
type: :runtime
|
70
|
+
version_requirements: *id005
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: yajl-ruby
|
73
|
+
prerelease: false
|
74
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: "0"
|
80
|
+
type: :runtime
|
81
|
+
version_requirements: *id006
|
125
82
|
description: "Evented framework for ZeroMQ and EventMachine Apps. "
|
126
83
|
email: andrew@andrewvc.com
|
127
84
|
executables: []
|
@@ -129,94 +86,87 @@ executables: []
|
|
129
86
|
extensions: []
|
130
87
|
|
131
88
|
extra_rdoc_files:
|
132
|
-
- LICENSE
|
133
|
-
- README.md
|
89
|
+
- LICENSE
|
90
|
+
- README.md
|
134
91
|
files:
|
135
|
-
- .document
|
136
|
-
-
|
137
|
-
-
|
138
|
-
-
|
139
|
-
-
|
140
|
-
-
|
141
|
-
-
|
142
|
-
-
|
143
|
-
- example/
|
144
|
-
- example/
|
145
|
-
- example/complex/
|
146
|
-
- example/complex/
|
147
|
-
- example/complex/
|
148
|
-
- example/complex/
|
149
|
-
- example/
|
150
|
-
- example/
|
151
|
-
- example/
|
152
|
-
- example/
|
153
|
-
- example/
|
154
|
-
-
|
155
|
-
- js/dripdrop.
|
156
|
-
- js/
|
157
|
-
- js/qunit.
|
158
|
-
-
|
159
|
-
- lib/dripdrop.rb
|
160
|
-
- lib/dripdrop/
|
161
|
-
- lib/dripdrop/handlers/
|
162
|
-
- lib/dripdrop/handlers/
|
163
|
-
- lib/dripdrop/handlers/
|
164
|
-
- lib/dripdrop/
|
165
|
-
- lib/dripdrop/
|
166
|
-
- lib/dripdrop/node.rb
|
167
|
-
-
|
168
|
-
- spec/
|
169
|
-
- spec/
|
170
|
-
- spec/node/
|
171
|
-
- spec/node/
|
172
|
-
- spec/node/
|
173
|
-
- spec/node/
|
174
|
-
- spec/node/
|
175
|
-
- spec/
|
176
|
-
- spec/
|
177
|
-
- spec/spec_helper.rb
|
92
|
+
- .document
|
93
|
+
- LICENSE
|
94
|
+
- README.md
|
95
|
+
- Rakefile
|
96
|
+
- VERSION
|
97
|
+
- doc_img/topology.png
|
98
|
+
- dripdrop.gemspec
|
99
|
+
- example/agent_test.rb
|
100
|
+
- example/combined.rb
|
101
|
+
- example/complex/README
|
102
|
+
- example/complex/client.rb
|
103
|
+
- example/complex/server.rb
|
104
|
+
- example/complex/service.rb
|
105
|
+
- example/complex/websocket.rb
|
106
|
+
- example/http.rb
|
107
|
+
- example/pubsub.rb
|
108
|
+
- example/pushpull.rb
|
109
|
+
- example/subclass.rb
|
110
|
+
- example/xreq_xrep.rb
|
111
|
+
- js/dripdrop.html
|
112
|
+
- js/dripdrop.js
|
113
|
+
- js/qunit.css
|
114
|
+
- js/qunit.js
|
115
|
+
- lib/dripdrop.rb
|
116
|
+
- lib/dripdrop/agent.rb
|
117
|
+
- lib/dripdrop/handlers/base.rb
|
118
|
+
- lib/dripdrop/handlers/http.rb
|
119
|
+
- lib/dripdrop/handlers/websockets.rb
|
120
|
+
- lib/dripdrop/handlers/zeromq.rb
|
121
|
+
- lib/dripdrop/message.rb
|
122
|
+
- lib/dripdrop/node.rb
|
123
|
+
- lib/dripdrop/node/nodelet.rb
|
124
|
+
- spec/gimite-websocket.rb
|
125
|
+
- spec/message_spec.rb
|
126
|
+
- spec/node/http_spec.rb
|
127
|
+
- spec/node/nodelet_spec.rb
|
128
|
+
- spec/node/routing_spec.rb
|
129
|
+
- spec/node/websocket_spec.rb
|
130
|
+
- spec/node/zmq_pushpull_spec.rb
|
131
|
+
- spec/node/zmq_xrepxreq_spec.rb
|
132
|
+
- spec/node_spec.rb
|
133
|
+
- spec/spec_helper.rb
|
178
134
|
has_rdoc: true
|
179
135
|
homepage: http://github.com/andrewvc/dripdrop
|
180
136
|
licenses: []
|
181
137
|
|
182
138
|
post_install_message:
|
183
|
-
rdoc_options:
|
184
|
-
|
139
|
+
rdoc_options: []
|
140
|
+
|
185
141
|
require_paths:
|
186
|
-
- lib
|
142
|
+
- lib
|
187
143
|
required_ruby_version: !ruby/object:Gem::Requirement
|
188
144
|
none: false
|
189
145
|
requirements:
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
segments:
|
194
|
-
- 0
|
195
|
-
version: "0"
|
146
|
+
- - ">="
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: "0"
|
196
149
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
197
150
|
none: false
|
198
151
|
requirements:
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
segments:
|
203
|
-
- 0
|
204
|
-
version: "0"
|
152
|
+
- - ">="
|
153
|
+
- !ruby/object:Gem::Version
|
154
|
+
version: "0"
|
205
155
|
requirements: []
|
206
156
|
|
207
157
|
rubyforge_project:
|
208
|
-
rubygems_version: 1.
|
158
|
+
rubygems_version: 1.5.1
|
209
159
|
signing_key:
|
210
160
|
specification_version: 3
|
211
161
|
summary: Evented framework for ZeroMQ and EventMachine Apps.
|
212
162
|
test_files:
|
213
|
-
- spec/
|
214
|
-
- spec/
|
215
|
-
- spec/
|
216
|
-
- spec/
|
217
|
-
- spec/node/
|
218
|
-
- spec/node/
|
219
|
-
- spec/node/
|
220
|
-
- spec/node/
|
221
|
-
- spec/
|
222
|
-
- spec/
|
163
|
+
- spec/gimite-websocket.rb
|
164
|
+
- spec/message_spec.rb
|
165
|
+
- spec/node/http_spec.rb
|
166
|
+
- spec/node/nodelet_spec.rb
|
167
|
+
- spec/node/routing_spec.rb
|
168
|
+
- spec/node/websocket_spec.rb
|
169
|
+
- spec/node/zmq_pushpull_spec.rb
|
170
|
+
- spec/node/zmq_xrepxreq_spec.rb
|
171
|
+
- spec/node_spec.rb
|
172
|
+
- spec/spec_helper.rb
|
data/.gitignore
DELETED