dripdrop 0.9.10 → 0.10.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +143 -33
- data/Rakefile +7 -3
- data/VERSION +1 -1
- data/dripdrop.gemspec +14 -14
- data/example/complex/server.rb +18 -31
- data/lib/dripdrop/handlers/base.rb +9 -6
- data/lib/dripdrop/handlers/mongrel2.rb +163 -0
- data/lib/dripdrop/handlers/{websockets.rb → websocket_server.rb} +6 -2
- data/lib/dripdrop/handlers/zeromq.rb +101 -71
- data/lib/dripdrop/message.rb +2 -2
- data/lib/dripdrop/node.rb +63 -24
- data/spec/node/websocket_spec.rb +1 -1
- data/spec/node/zmq_m2_spec.rb +77 -0
- data/spec/node/zmq_pushpull_spec.rb +3 -1
- data/spec/node_spec.rb +1 -2
- metadata +103 -111
@@ -12,16 +12,28 @@ class DripDrop
|
|
12
12
|
end
|
13
13
|
|
14
14
|
class ZMQBaseHandler < BaseHandler
|
15
|
-
|
15
|
+
attr_reader :connection
|
16
16
|
|
17
17
|
def initialize(opts={})
|
18
18
|
@opts = opts
|
19
19
|
@connection = nil
|
20
20
|
@msg_format = opts[:msg_format] || :dripdrop
|
21
|
+
@message_class = @opts[:message_class] || DripDrop.default_message_class
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_connection(connection)
|
25
|
+
@connection = connection
|
26
|
+
end
|
27
|
+
|
28
|
+
def read_connection
|
29
|
+
@connection
|
30
|
+
end
|
31
|
+
|
32
|
+
def write_connection
|
33
|
+
@connection
|
21
34
|
end
|
22
35
|
|
23
36
|
def on_recv(msg_format=:dripdrop,&block)
|
24
|
-
@msg_format = msg_format
|
25
37
|
@recv_cbak = block
|
26
38
|
self
|
27
39
|
end
|
@@ -41,27 +53,13 @@ class DripDrop
|
|
41
53
|
@send_queue_enabled = false
|
42
54
|
end
|
43
55
|
|
44
|
-
def on_writable(
|
56
|
+
def on_writable(conn)
|
45
57
|
unless @send_queue.empty?
|
46
58
|
message = @send_queue.shift
|
47
59
|
|
48
|
-
|
49
|
-
message.each_with_index do |part,i|
|
50
|
-
# Set the multi-part flag unless this is the last message
|
51
|
-
flags = (i + 1 < num_parts ? ZMQ::SNDMORE : 0) | ZMQ::NOBLOCK
|
52
|
-
|
53
|
-
if part.class == ZMQ::Message
|
54
|
-
socket.send(part, flags)
|
55
|
-
else
|
56
|
-
if part.class == String
|
57
|
-
socket.send_string(part, flags)
|
58
|
-
else
|
59
|
-
$stderr.write "Can only send Strings, not #{part.class}: #{part}" if @debug
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
60
|
+
conn.send_msg(*message)
|
63
61
|
else
|
64
|
-
|
62
|
+
conn.deregister_writable if @send_queue_enabled
|
65
63
|
end
|
66
64
|
end
|
67
65
|
|
@@ -78,27 +76,18 @@ class DripDrop
|
|
78
76
|
else
|
79
77
|
@send_queue.push([message])
|
80
78
|
end
|
81
|
-
|
82
79
|
|
83
|
-
if @send_queue_enabled
|
84
|
-
@connection.register_writable
|
80
|
+
self.write_connection.register_writable if @send_queue_enabled
|
85
81
|
|
86
|
-
|
87
|
-
on_writable(
|
88
|
-
|
89
|
-
on_writable(@connection.socket)
|
90
|
-
end
|
82
|
+
EM::next_tick {
|
83
|
+
on_writable(self.write_connection)
|
84
|
+
}
|
91
85
|
end
|
92
86
|
end
|
93
87
|
|
94
88
|
module ZMQReadableHandler
|
95
89
|
attr_accessor :message_class
|
96
|
-
|
97
|
-
def initialize(*args)
|
98
|
-
super(*args)
|
99
|
-
@message_class = @opts[:message_class] || DripDrop.default_message_class
|
100
|
-
end
|
101
|
-
|
90
|
+
|
102
91
|
def decode_message(msg)
|
103
92
|
@message_class.decode(msg)
|
104
93
|
end
|
@@ -109,7 +98,10 @@ class DripDrop
|
|
109
98
|
when :raw
|
110
99
|
@recv_cbak.call(messages)
|
111
100
|
when :dripdrop
|
112
|
-
|
101
|
+
if messages.length > 1
|
102
|
+
raise "Expected message in one part for #{self.inspect}, got #{messages.map(&:copy_out_string)}"
|
103
|
+
end
|
104
|
+
|
113
105
|
body = messages.shift.copy_out_string
|
114
106
|
@recv_cbak.call(decode_message(body))
|
115
107
|
else
|
@@ -119,10 +111,6 @@ class DripDrop
|
|
119
111
|
handle_error(e)
|
120
112
|
end
|
121
113
|
end
|
122
|
-
|
123
|
-
def post_setup
|
124
|
-
@connection.register_readable
|
125
|
-
end
|
126
114
|
end
|
127
115
|
|
128
116
|
class ZMQSubHandler < ZMQBaseHandler
|
@@ -136,17 +124,21 @@ class DripDrop
|
|
136
124
|
end
|
137
125
|
|
138
126
|
def on_readable(socket, messages)
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
127
|
+
begin
|
128
|
+
if @msg_format == :dripdrop
|
129
|
+
unless messages.length == 2
|
130
|
+
return false
|
131
|
+
end
|
132
|
+
topic = messages.shift.copy_out_string
|
133
|
+
if @topic_filter.nil? || topic.match(@topic_filter)
|
134
|
+
body = messages.shift.copy_out_string
|
135
|
+
@recv_cbak.call(decode_message(body))
|
136
|
+
end
|
137
|
+
else
|
138
|
+
super(socket,messages)
|
147
139
|
end
|
148
|
-
|
149
|
-
|
140
|
+
rescue StandardError => e
|
141
|
+
handle_error(e)
|
150
142
|
end
|
151
143
|
end
|
152
144
|
|
@@ -161,7 +153,7 @@ class DripDrop
|
|
161
153
|
|
162
154
|
#Sends a message along
|
163
155
|
def send_message(message)
|
164
|
-
dd_message = dd_messagify(message)
|
156
|
+
dd_message = dd_messagify(message,@message_class)
|
165
157
|
if dd_message.is_a?(DripDrop::Message)
|
166
158
|
super([dd_message.name, dd_message.encoded])
|
167
159
|
else
|
@@ -172,8 +164,6 @@ class DripDrop
|
|
172
164
|
|
173
165
|
class ZMQPullHandler < ZMQBaseHandler
|
174
166
|
include ZMQReadableHandler
|
175
|
-
|
176
|
-
|
177
167
|
end
|
178
168
|
|
179
169
|
class ZMQPushHandler < ZMQBaseHandler
|
@@ -190,12 +180,43 @@ class DripDrop
|
|
190
180
|
|
191
181
|
def on_readable(socket,messages)
|
192
182
|
if @msg_format == :dripdrop
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
183
|
+
begin
|
184
|
+
if messages.length < 3
|
185
|
+
raise "Expected message in at least 3 parts, got #{messages.map(&:copy_out_string).inspect}"
|
186
|
+
end
|
187
|
+
|
188
|
+
message_strings = messages.map(&:copy_out_string)
|
189
|
+
|
190
|
+
# parse the message into identities, delimiter and body
|
191
|
+
identities = []
|
192
|
+
delimiter = nil
|
193
|
+
body = nil
|
194
|
+
# It's an identitiy if it isn't an empty string
|
195
|
+
# Once we hit the delimiter, we know the rest after is the body
|
196
|
+
message_strings.each_with_index do |ms,i|
|
197
|
+
unless ms.empty?
|
198
|
+
identities << ms
|
199
|
+
else
|
200
|
+
delimiter = ms
|
201
|
+
|
202
|
+
unless message_strings.length == i+2
|
203
|
+
raise "Expected body in 1 part got '#{message_strings.inspect}'"
|
204
|
+
end
|
205
|
+
|
206
|
+
body = message_strings[i+1]
|
207
|
+
break
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
raise "Received xreq message with no body!" unless body
|
212
|
+
message = decode_message(body)
|
213
|
+
raise "Received nil message! #{body}" unless message
|
214
|
+
seq = message.head[SEQ_CTR_KEY]
|
215
|
+
response = ZMQXRepHandler::Response.new(self,identities,seq,@message_class)
|
216
|
+
@recv_cbak.call(message,response) if @recv_cbak
|
217
|
+
rescue StandardError => e
|
218
|
+
handle_error(e)
|
219
|
+
end
|
199
220
|
else
|
200
221
|
super(socket,messages)
|
201
222
|
end
|
@@ -217,14 +238,15 @@ class DripDrop
|
|
217
238
|
class ZMQXRepHandler::Response < ZMQBaseHandler
|
218
239
|
attr_accessor :xrep, :seq, :identities
|
219
240
|
|
220
|
-
def initialize(xrep,identities,seq)
|
241
|
+
def initialize(xrep,identities,seq,message_class)
|
221
242
|
@xrep = xrep
|
222
243
|
@seq = seq
|
223
|
-
@identities
|
244
|
+
@identities = identities
|
245
|
+
@message_class = message_class
|
224
246
|
end
|
225
247
|
|
226
248
|
def send_message(message)
|
227
|
-
dd_message = dd_messagify(message)
|
249
|
+
dd_message = dd_messagify(message,@message_class)
|
228
250
|
@xrep.send_message(dd_message,identities,seq)
|
229
251
|
end
|
230
252
|
end
|
@@ -240,22 +262,30 @@ class DripDrop
|
|
240
262
|
@promises = {}
|
241
263
|
|
242
264
|
self.on_recv do |message|
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
265
|
+
begin
|
266
|
+
seq = message.head[SEQ_CTR_KEY]
|
267
|
+
raise "Missing Seq Counter" unless seq
|
268
|
+
promise = @promises.delete(seq)
|
269
|
+
promise.call(message) if promise
|
270
|
+
rescue StandardError => e
|
271
|
+
handle_error(e)
|
272
|
+
end
|
247
273
|
end
|
248
274
|
end
|
249
275
|
|
250
276
|
def send_message(message,&block)
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
277
|
+
begin
|
278
|
+
dd_message = dd_messagify(message,@message_class)
|
279
|
+
if dd_message.is_a?(DripDrop::Message)
|
280
|
+
@seq_counter += 1
|
281
|
+
dd_message.head[SEQ_CTR_KEY] = @seq_counter
|
282
|
+
@promises[@seq_counter] = block if block
|
283
|
+
message = dd_message
|
284
|
+
end
|
285
|
+
rescue StandardError => e
|
286
|
+
handle_error(e)
|
257
287
|
end
|
258
|
-
super(message)
|
288
|
+
super(['', message.encoded])
|
259
289
|
end
|
260
290
|
|
261
291
|
def on_readable(socket, messages)
|
data/lib/dripdrop/message.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
|
3
|
-
if
|
3
|
+
if RUBY_PLATFORM == 'java'
|
4
4
|
require 'json'
|
5
5
|
else
|
6
6
|
require 'yajl'
|
@@ -82,7 +82,7 @@ class DripDrop
|
|
82
82
|
|
83
83
|
klass = (hash['head'] && hash['head']['message_class']) ? constantize(hash['head']['message_class']) : nil
|
84
84
|
if klass && (!(klass == self) && !self.subclasses.include?(klass))
|
85
|
-
raise DripDrop::WrongMessageClassError, "Wrong message class '#{klass}', expected '#{self}'"
|
85
|
+
raise DripDrop::WrongMessageClassError, "Wrong message class '#{klass}', expected '#{self}' for message #{hash.inspect}"
|
86
86
|
end
|
87
87
|
|
88
88
|
klass ? klass.from_hash(hash) : self.from_hash(hash)
|
data/lib/dripdrop/node.rb
CHANGED
@@ -9,28 +9,29 @@ require 'dripdrop/message'
|
|
9
9
|
require 'dripdrop/node/nodelet'
|
10
10
|
require 'dripdrop/handlers/base'
|
11
11
|
require 'dripdrop/handlers/zeromq'
|
12
|
-
require 'dripdrop/handlers/
|
12
|
+
require 'dripdrop/handlers/websocket_server'
|
13
|
+
require 'dripdrop/handlers/mongrel2'
|
13
14
|
require 'dripdrop/handlers/http_client'
|
14
15
|
|
15
16
|
begin
|
16
17
|
require 'dripdrop/handlers/http_server'
|
17
18
|
rescue LoadError => e
|
18
|
-
$stderr.write "
|
19
|
-
$stderr.write e.message + "\n"
|
20
|
-
$stderr.write e.backtrace.join("\t\n")
|
19
|
+
$stderr.write "Warning, could not load http server, your probably don't have eventmachine_httpserver installed\n"
|
21
20
|
end
|
22
21
|
|
23
22
|
class DripDrop
|
24
23
|
class Node
|
25
24
|
ZCTX = ZMQ::Context.new 1
|
26
25
|
|
27
|
-
attr_reader :zm_reactor, :routing, :nodelets
|
26
|
+
attr_reader :zm_reactor, :routing, :nodelets, :run_list
|
28
27
|
attr_accessor :debug
|
29
28
|
|
30
29
|
def initialize(opts={},&block)
|
31
30
|
@block = block
|
32
31
|
@thread = nil # Thread containing the reactors
|
33
32
|
@routing = {} # Routing table
|
33
|
+
@run_list = opts['run_list'] || opts[:run_list] || nil #List of nodelets to run
|
34
|
+
@run_list = @run_list.map(&:to_sym) if @run_list
|
34
35
|
@debug = opts[:debug]
|
35
36
|
@recipients_for = {}
|
36
37
|
@handler_default_opts = {:debug => @debug}
|
@@ -42,7 +43,7 @@ class DripDrop
|
|
42
43
|
# This is non-blocking.
|
43
44
|
def start
|
44
45
|
@thread = Thread.new do
|
45
|
-
EM.error_handler {|e| self.error_handler e}
|
46
|
+
EM.error_handler {|e| self.class.error_handler e}
|
46
47
|
EM.run { action }
|
47
48
|
end
|
48
49
|
end
|
@@ -146,8 +147,26 @@ class DripDrop
|
|
146
147
|
#
|
147
148
|
# If you specify a block, Nodelet#action will be ignored and the block
|
148
149
|
# will be run
|
150
|
+
#
|
151
|
+
# Nodelets are made available as instance methods on the current DripDrop::Nodelet
|
152
|
+
# Object, so the following works as well:
|
153
|
+
#
|
154
|
+
# nodelet :mynodelet
|
155
|
+
#
|
156
|
+
# mynodelet.route :route_name, :zmq_xreq, 'tcp://127.0.0.1:2000', ;bind
|
149
157
|
def nodelet(name,klass=Nodelet,*configure_args,&block)
|
158
|
+
# If there's a run list, only run nodes in that list
|
159
|
+
return nil if @run_list && !@run_list.include?(name.to_sym)
|
160
|
+
|
150
161
|
nlet = @nodelets[name] ||= klass.new(self,name,*configure_args)
|
162
|
+
|
163
|
+
# Define a method returning the nodelet in the current node
|
164
|
+
unless respond_to?(name)
|
165
|
+
(class << self; self; end).class_eval do
|
166
|
+
define_method(name) { nlet }
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
151
170
|
if block
|
152
171
|
block.call(nlet)
|
153
172
|
else
|
@@ -156,6 +175,10 @@ class DripDrop
|
|
156
175
|
nlet
|
157
176
|
end
|
158
177
|
|
178
|
+
def zmq_m2(addresses, opts={}, &block)
|
179
|
+
zmq_handler(DripDrop::Mongrel2Handler, [ZMQ::PULL, ZMQ::PUB], addresses, [:connect, :connect], opts)
|
180
|
+
end
|
181
|
+
|
159
182
|
# Creates a ZMQ::SUB type socket. Can only receive messages via +on_recv+.
|
160
183
|
# zmq_subscribe sockets have a +topic_filter+ option, which restricts which
|
161
184
|
# messages they can receive. It takes a regexp as an option.
|
@@ -199,11 +222,11 @@ class DripDrop
|
|
199
222
|
zmq_handler(DripDrop::ZMQXReqHandler,ZMQ::XREQ,address,socket_ctype,opts)
|
200
223
|
end
|
201
224
|
|
202
|
-
# Binds an EM websocket connection to +address+. takes blocks for
|
225
|
+
# Binds an EM websocket server connection to +address+. takes blocks for
|
203
226
|
# +on_open+, +on_recv+, +on_close+ and +on_error+.
|
204
227
|
#
|
205
228
|
# For example +on_recv+ could be used to echo incoming messages thusly:
|
206
|
-
#
|
229
|
+
# websocket_server(addr).on_open {|conn|
|
207
230
|
# ws.send_message(:name => 'ws_open_ack')
|
208
231
|
# }.on_recv {|msg,conn|
|
209
232
|
# conn.send(msg)
|
@@ -213,12 +236,18 @@ class DripDrop
|
|
213
236
|
#
|
214
237
|
# The +ws+ object that's passed into the handlers is not
|
215
238
|
# the +DripDrop::WebSocketHandler+ object, but an em-websocket object.
|
216
|
-
def
|
239
|
+
def websocket_server(address,opts={})
|
217
240
|
uri = URI.parse(address)
|
218
241
|
h_opts = handler_opts_given(opts)
|
219
242
|
DripDrop::WebSocketHandler.new(uri,h_opts)
|
220
243
|
end
|
221
244
|
|
245
|
+
# DEPRECATED: Use websocket_server
|
246
|
+
def websocket(*args)
|
247
|
+
$stderr.write "DripDrop#websocket handler is deprecated, use DripDrop#websocket_server"
|
248
|
+
websocket_server(*args)
|
249
|
+
end
|
250
|
+
|
222
251
|
# Starts a new Thin HTTP server listening on address.
|
223
252
|
# Can have an +on_recv+ handler that gets passed +msg+ and +response+ args.
|
224
253
|
# http_server(addr) {|msg,response| response.send_message(msg)}
|
@@ -285,22 +314,32 @@ class DripDrop
|
|
285
314
|
private
|
286
315
|
|
287
316
|
def zmq_handler(klass, sock_type, address, socket_ctype, opts={})
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
317
|
+
h_opts = handler_opts_given(opts)
|
318
|
+
|
319
|
+
sock_type = [sock_type].flatten
|
320
|
+
address = [address].flatten
|
321
|
+
socket_ctype = [socket_ctype].flatten
|
322
|
+
|
323
|
+
handler = klass.new(h_opts)
|
324
|
+
|
325
|
+
sock_type.length.times do |index|
|
326
|
+
addr_uri = URI.parse(address[index])
|
327
|
+
|
328
|
+
host_str = addr_uri.host
|
329
|
+
#if addr_uri.scheme == 'tcp'
|
330
|
+
# host = Resolv.getaddresses(addr_uri.host).first
|
331
|
+
# host_addr = Resolv.getaddresses('localhost').map {|a| IPAddr.new(a)}.find {|a| a.ipv4?}
|
332
|
+
# host_str = host_addr.ipv6? ? "[#{host_addr.to_s}]" : host_addr.to_s
|
333
|
+
#else
|
334
|
+
# host_str = addr_uri.host
|
335
|
+
#end
|
336
|
+
|
337
|
+
z_addr = "#{addr_uri.scheme}://#{host_str}:#{addr_uri.port.to_i}"
|
338
|
+
|
339
|
+
connection = EM::ZeroMQ::Context.new(@zctx).create sock_type[index], socket_ctype[index], z_addr, handler
|
340
|
+
handler.add_connection connection
|
341
|
+
end
|
298
342
|
|
299
|
-
z_addr = "#{addr_uri.scheme}://#{host_str}:#{addr_uri.port.to_i}"
|
300
|
-
h_opts = handler_opts_given(opts)
|
301
|
-
connection = EM::ZeroMQ.create @zctx, sock_type, socket_ctype, address, klass.new(h_opts)
|
302
|
-
handler = connection.handler
|
303
|
-
handler.connection = connection
|
304
343
|
handler.post_setup
|
305
344
|
handler
|
306
345
|
end
|
data/spec/node/websocket_spec.rb
CHANGED
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
m2_req = '34f9cfef-dc52-4b7f-b197-098765432112 16 /handlertest 537:{"PATH":"/handlertest","accept-language":"en-us,en;q=0.5","user-agent":"Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.13) Gecko/20110207 Gentoo Firefox/3.6.13","host":"it.wishdev.org:6767","accept-charset":"ISO-8859-1,utf-8;q=0.7,*;q=0.7","accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","keep-alive":"115","x-forwarded-for":"127.0.0.1","cache-control":"max-age=0","connection":"keep-alive","accept-encoding":"gzip,deflate","METHOD":"GET","VERSION":"HTTP/1.1","URI":"/handlertest","PATTERN":"/handlertest"},0:,'
|
4
|
+
dd_resp = "34f9cfef-dc52-4b7f-b197-098765432112 2:16, HTTP/1.1 200 OK\r\nContent-Length: 19\r\n\r\nHello from DripDrop"
|
5
|
+
|
6
|
+
body = ""
|
7
|
+
conn_id = "16"
|
8
|
+
headers = {"PATH"=>"/handlertest",
|
9
|
+
"accept-language"=>"en-us,en;q=0.5",
|
10
|
+
"user-agent"=>
|
11
|
+
"Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.13) Gecko/20110207 Gentoo Firefox/3.6.13",
|
12
|
+
"host"=>"it.wishdev.org:6767",
|
13
|
+
"accept-charset"=>"ISO-8859-1,utf-8;q=0.7,*;q=0.7",
|
14
|
+
"accept"=>"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
15
|
+
"keep-alive"=>"115",
|
16
|
+
"x-forwarded-for"=>"127.0.0.1",
|
17
|
+
"cache-control"=>"max-age=0",
|
18
|
+
"connection"=>"keep-alive",
|
19
|
+
"accept-encoding"=>"gzip,deflate",
|
20
|
+
"METHOD"=>"GET",
|
21
|
+
"VERSION"=>"HTTP/1.1",
|
22
|
+
"URI"=>"/handlertest",
|
23
|
+
"PATTERN"=>"/handlertest"}
|
24
|
+
path = "/handlertest"
|
25
|
+
sender = "34f9cfef-dc52-4b7f-b197-098765432112"
|
26
|
+
|
27
|
+
describe "zmq m2" do
|
28
|
+
def pp_send_messages(to_send)
|
29
|
+
responses = []
|
30
|
+
requests = []
|
31
|
+
|
32
|
+
@node = run_reactor(2) do
|
33
|
+
addr = rand_addr
|
34
|
+
addr2 = rand_addr
|
35
|
+
|
36
|
+
m2_send = zmq_push(addr, :bind, {:msg_format => :raw})
|
37
|
+
m2_recv = zmq_subscribe(addr2, :bind, {:msg_format => :raw})
|
38
|
+
|
39
|
+
dd = zmq_m2([addr, addr2])
|
40
|
+
|
41
|
+
dd.on_recv do |req|
|
42
|
+
requests << req
|
43
|
+
dd.reply_http req, "Hello from DripDrop"
|
44
|
+
end
|
45
|
+
|
46
|
+
m2_recv.on_recv do |msg|
|
47
|
+
responses << msg
|
48
|
+
end
|
49
|
+
|
50
|
+
sleep 1
|
51
|
+
|
52
|
+
to_send.each {|message| m2_send.send_message(message)}
|
53
|
+
end
|
54
|
+
|
55
|
+
{:responses => responses, :requests => requests}
|
56
|
+
end
|
57
|
+
describe "basic sending and receiving" do
|
58
|
+
before(:all) do
|
59
|
+
@sent = [m2_req]
|
60
|
+
pp_info = pp_send_messages(@sent)
|
61
|
+
@responses = pp_info[:responses]
|
62
|
+
@requests = pp_info[:requests]
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should parse a request" do
|
66
|
+
@requests[0].body.should == body
|
67
|
+
@requests[0].conn_id.should == conn_id
|
68
|
+
@requests[0].headers.should == headers
|
69
|
+
@requests[0].path.should == path
|
70
|
+
@requests[0].sender.should == sender
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should respond to an http request" do
|
74
|
+
@responses[0][0].copy_out_string.should == dd_resp
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -7,7 +7,7 @@ describe "zmq push/pull" do
|
|
7
7
|
push = nil
|
8
8
|
pull = nil
|
9
9
|
|
10
|
-
@node = run_reactor do
|
10
|
+
@node = run_reactor(2) do
|
11
11
|
addr = rand_addr
|
12
12
|
|
13
13
|
push = zmq_push(addr, :bind)
|
@@ -25,6 +25,8 @@ describe "zmq push/pull" do
|
|
25
25
|
responses << message
|
26
26
|
end
|
27
27
|
|
28
|
+
sleep 1
|
29
|
+
|
28
30
|
to_send.each {|message| push.send_message(message)}
|
29
31
|
end
|
30
32
|
|
data/spec/node_spec.rb
CHANGED
@@ -72,10 +72,9 @@ 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"
|
76
75
|
expectations = an_instance_of(TestException)
|
77
76
|
reactor = run_reactor do
|
78
|
-
self.should_receive(:error_handler).with(expectations)
|
77
|
+
self.class.should_receive(:error_handler).with(expectations)
|
79
78
|
EM.next_tick do
|
80
79
|
raise TestException, "foo"
|
81
80
|
end
|