dripdrop 0.9.10 → 0.10.0.beta1
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/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
|