dripdrop 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/README.md +23 -28
  2. data/VERSION +1 -1
  3. data/dripdrop.gemspec +25 -3
  4. data/example/combined.rb +33 -0
  5. data/example/pubsub.rb +7 -15
  6. data/example/stats_app/core.rb +113 -0
  7. data/example/stats_app/public/.sass-cache/b48b4299d80c05f528daf63fe51d85e5e3c10d98/stats.scssc +0 -0
  8. data/example/stats_app/public/backbone.js +16 -0
  9. data/example/stats_app/public/build_templates.rb +5 -0
  10. data/example/stats_app/public/json2.js +482 -0
  11. data/example/stats_app/public/protovis-r3.2.js +277 -0
  12. data/example/stats_app/public/stats.css +5 -0
  13. data/example/stats_app/public/stats.haml +61 -0
  14. data/example/stats_app/public/stats.html +26 -0
  15. data/example/stats_app/public/stats.js +113 -0
  16. data/example/stats_app/public/stats.scss +10 -0
  17. data/example/stats_app/public/underscore.js +17 -0
  18. data/example/xreq_xrep.rb +9 -11
  19. data/js/dripdrop.js +6 -2
  20. data/lib/dripdrop/handlers/base.rb +18 -0
  21. data/lib/dripdrop/handlers/http.rb +18 -18
  22. data/lib/dripdrop/handlers/websockets.rb +33 -26
  23. data/lib/dripdrop/handlers/zeromq.rb +30 -24
  24. data/lib/dripdrop/message.rb +5 -0
  25. data/lib/dripdrop/node/nodelet.rb +29 -0
  26. data/lib/dripdrop/node.rb +103 -25
  27. data/spec/gimite-websocket.rb +442 -0
  28. data/spec/message_spec.rb +5 -0
  29. data/spec/node/http_spec.rb +2 -8
  30. data/spec/node/nodelet_spec.rb +57 -0
  31. data/spec/node/routing_spec.rb +68 -0
  32. data/spec/node/websocket_spec.rb +88 -0
  33. data/spec/node/zmq_pushpull_spec.rb +2 -6
  34. data/spec/node/zmq_xrepxreq_spec.rb +24 -24
  35. data/spec/node_spec.rb +0 -1
  36. data/spec/spec_helper.rb +17 -3
  37. metadata +27 -5
  38. data/js/jack.js +0 -876
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ describe "nodelets" do
4
+ before(:all) do
5
+ nodelets = {}
6
+
7
+ @node = run_reactor do
8
+ routes_for :distributor do
9
+ route :output, :zmq_push, rand_addr, :bind
10
+ end
11
+ routes_for :worker_cluster do
12
+ route :worker1, :zmq_pull, distributor_output.address, :connect
13
+ route :worker2, :zmq_pull, distributor_output.address, :connect
14
+ end
15
+
16
+ nodelet :distributor do |d|
17
+ nodelets[:distributor] = d
18
+ end
19
+
20
+ nodelet :worker_cluster do |wc|
21
+ nodelets[:worker_cluster] = wc
22
+ end
23
+ end
24
+
25
+ @nodelets = nodelets
26
+ end
27
+
28
+ it "should create the nodelets" do
29
+ @nodelets.length.should == 2
30
+ end
31
+
32
+ it "should pass a DripDrop::Node::Nodelet to the block" do
33
+ @nodelets.values.each do |nlet|
34
+ nlet.should be_instance_of(DripDrop::Node::Nodelet)
35
+ end
36
+ end
37
+
38
+ it "should give access to the full routing table to nodelets" do
39
+ @node.routing.each do |route_name,handler|
40
+ @nodelets.values.each do |nlet|
41
+ nlet.send(route_name).should == handler
42
+ end
43
+ end
44
+ end
45
+
46
+ it "should define prefix-less versions of nodelet specific routes" do
47
+ {
48
+ @nodelets[:worker_cluster] => {:worker1 => :worker_cluster_worker1,
49
+ :worker2 => :worker_cluster_worker2},
50
+ @nodelets[:distributor] => {:output => :distributor_output}
51
+ }.each do |nlet, mapping|
52
+ mapping.each do |short,long|
53
+ nlet.send(short).should == nlet.send(long)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+
3
+ describe "routing" do
4
+ shared_examples_for "all routing" do
5
+ it "should define all routes in the table" do
6
+ @expected_routing.keys.each do |route_name|
7
+ @node.routing.keys.should include(route_name)
8
+ end
9
+ end
10
+
11
+ it "should define a handler in the routing table for each route" do
12
+ @expected_routing.keys.each do |route_name|
13
+ @node.routing[route_name].should be_kind_of(DripDrop::BaseHandler)
14
+ end
15
+ end
16
+
17
+ it "should define a singleton method for each entry in the routing table" do
18
+ @expected_routing.keys.each do |route_name|
19
+ @node.send(route_name).should == @node.routing[route_name]
20
+ end
21
+ end
22
+
23
+ it "should create handlers with the correct properties" do
24
+ @expected_routing.each do |route_name,expected_props|
25
+ handler = @node.send(route_name)
26
+ handler.class.should == expected_props[:class]
27
+ handler.socket_ctype.should == expected_props[:socket_ctype]
28
+ end
29
+ end
30
+ end
31
+
32
+ context "with no groups" do
33
+ before(:all) do
34
+ @expected_routing = {
35
+ :distributor => {:class => DripDrop::ZMQPushHandler, :socket_ctype => :bind},
36
+ :worker1 => {:class => DripDrop::ZMQPullHandler, :socket_ctype => :connect},
37
+ :worker2 => {:class => DripDrop::ZMQPullHandler, :socket_ctype => :connect}
38
+ }
39
+ @node = run_reactor do
40
+ route :distributor, :zmq_push, rand_addr, :bind
41
+ route :worker1, :zmq_pull, distributor.address, :connect
42
+ route :worker2, :zmq_pull, distributor.address, :connect
43
+ end
44
+ end
45
+
46
+ it_should_behave_like "all routing"
47
+ end
48
+ context "with groups" do
49
+ before(:all) do
50
+ @expected_routing = {
51
+ :distributor_output => {:class => DripDrop::ZMQPushHandler, :socket_ctype => :bind},
52
+ :worker_cluster_worker1 => {:class => DripDrop::ZMQPullHandler, :socket_ctype => :connect},
53
+ :worker_cluster_worker2 => {:class => DripDrop::ZMQPullHandler, :socket_ctype => :connect}
54
+ }
55
+ @node = run_reactor do
56
+ routes_for :distributor do
57
+ route :output, :zmq_push, rand_addr, :bind
58
+ end
59
+ routes_for :worker_cluster do
60
+ route :worker1, :zmq_pull, distributor_output.address, :connect
61
+ route :worker2, :zmq_pull, distributor_output.address, :connect
62
+ end
63
+ end
64
+ end
65
+
66
+ it_should_behave_like "all routing"
67
+ end
68
+ end
@@ -0,0 +1,88 @@
1
+ require 'spec_helper'
2
+
3
+ describe "websockets" do
4
+ def websockets_send_messages(to_send,&block)
5
+ received = []
6
+ responses = []
7
+ server = nil
8
+
9
+ open_message = DripDrop::Message.new('open', :body => 'test')
10
+ open_received = false
11
+
12
+ close_occured = false
13
+
14
+ error_occured = false
15
+
16
+ @node = run_reactor(1) do
17
+ addr = rand_addr('ws')
18
+
19
+ server = websocket(addr)
20
+ server.on_open do |conn|
21
+ conn.send_message(open_message)
22
+ end.on_recv do |message,conn|
23
+ received << message
24
+ conn.send_message(message)
25
+ end.on_close do |conn|
26
+ close_occured = true
27
+ end.on_error do |conn|
28
+ error_occured = true
29
+ end
30
+
31
+ EM.defer do
32
+ client = WebSocket.new(addr)
33
+ open_received = DripDrop::Message.decode_json(client.receive)
34
+ to_send.each do |message|
35
+ client.send(message.json_encoded)
36
+ end
37
+
38
+ recvd_count = 0
39
+ while recvd_count < to_send.length && (message = client.receive)
40
+ responses << DripDrop::Message.decode_json(message)
41
+ recvd_count += 1
42
+ end
43
+ client.close
44
+ end
45
+
46
+ zmq_subscribe(rand_addr, :bind) {} #Keep zmqmachine happy
47
+ end
48
+
49
+ {:received => received, :responses => responses,
50
+ :open_message => open_message, :open_received => open_received,
51
+ :close_occured => close_occured, :error_occured => error_occured,
52
+ :handlers => {:server => server }}
53
+ end
54
+ describe "basic sending and receiving" do
55
+ before(:all) do
56
+ @sent = []
57
+ 10.times {|i| @sent << DripDrop::Message.new("test-#{i}")}
58
+ @ws_info = websockets_send_messages(@sent)
59
+ end
60
+
61
+ it "should receive all sent messages" do
62
+ recvd_names = @ws_info[:received].map(&:name).inject(Set.new) {|memo,rn| memo << rn}
63
+ @sent.map(&:name).each {|sn| recvd_names.should include(sn)}
64
+ end
65
+
66
+ it "should return to the client as many responses as sent messages" do
67
+ @ws_info[:responses].length.should == @sent.length
68
+ end
69
+
70
+ it "should return to the client an identical message to that which was sent" do
71
+ @ws_info[:received].zip(@ws_info[:responses]).each do |recvd,resp|
72
+ recvd.name.should == resp.name
73
+ end
74
+ end
75
+
76
+ it "should generate an on open message" do
77
+ @ws_info[:open_received].to_hash.should == @ws_info[:open_message].to_hash
78
+ end
79
+
80
+ it "should generate a close event" do
81
+ @ws_info[:close_occured].should be_true
82
+ end
83
+
84
+ it "should not generate an error event" do
85
+ @ws_info[:error_occured].should be_false
86
+ end
87
+ end
88
+ end
@@ -6,7 +6,7 @@ describe "zmq push/pull" do
6
6
  push = nil
7
7
  pull = nil
8
8
 
9
- @ddn = DripDrop::Node.new do
9
+ @node = run_reactor do
10
10
  addr = rand_addr
11
11
 
12
12
  push = zmq_push(addr, :bind)
@@ -26,11 +26,7 @@ describe "zmq push/pull" do
26
26
 
27
27
  to_send.each {|message| push.send_message(message)}
28
28
  end
29
-
30
- @ddn.start
31
- sleep 0.1
32
- @ddn.stop rescue nil
33
-
29
+
34
30
  {:responses => responses, :handlers => { :push => push, :pull => [pull] }}
35
31
  end
36
32
  describe "basic sending and receiving" do
@@ -2,70 +2,73 @@ require 'spec_helper'
2
2
 
3
3
  describe "zmq xreq/xrep" do
4
4
  def xr_tranceive_messages(to_send,&block)
5
- responses = []
5
+ recvd = []
6
6
  req = nil
7
7
  rep = nil
8
8
 
9
- @ddn = DripDrop::Node.new do
9
+ @node = run_reactor do
10
10
  addr = rand_addr
11
11
 
12
12
  rep = zmq_xrep(addr, :bind)
13
13
  req = zmq_xreq(addr, :connect)
14
14
 
15
- rep.on_recv do |message,identities,seq|
16
- yield(identities,seq,message) if block
17
- responses << {:identities => identities, :seq => seq, :message => message}
15
+ rep.on_recv do |message,response|
16
+ recvd << {:message => message, :response => response}
18
17
  end
19
18
 
20
19
  to_send.each {|message| req.send_message(message)}
21
20
  end
22
21
 
23
- @ddn.start
24
- sleep 0.1
25
- @ddn.stop rescue nil
26
-
27
- {:responses => responses, :handlers => {:req => req, :rep => rep}}
22
+ {:recvd => recvd, :handlers => {:req => req, :rep => rep}}
28
23
  end
29
24
  describe "basic sending and receiving" do
30
25
  before(:all) do
31
26
  @sent = []
32
27
  10.times {|i| @sent << DripDrop::Message.new("test-#{i}")}
33
28
  xr_info = xr_tranceive_messages(@sent)
34
- @responses = xr_info[:responses]
29
+ @recvd = xr_info[:recvd]
35
30
  @req_handler = xr_info[:handlers][:req]
36
31
  @rep_handler = xr_info[:handlers][:rep]
37
32
  end
38
33
 
39
34
  it "should receive all sent messages in order" do
40
- @sent.zip(@responses).each do |sent,response|
41
- sent.name.should == response[:message].name
35
+ @sent.zip(@recvd).each do |sent,recvd|
36
+ sent.name.should == recvd[:message].name
37
+ end
38
+ end
39
+
40
+ it "should pass a ZMQXrepHandler::Response object to the response callback" do
41
+ @recvd.each do |recvd_item|
42
+ recvd_item[:response].should be_instance_of(DripDrop::ZMQXRepHandler::Response)
42
43
  end
43
44
  end
44
45
 
45
46
  it "should have a monotonically incrementing seq for responses" do
46
47
  last_seq = 0
47
- @responses.each do |resp|
48
- resp[:seq].should == last_seq + 1
49
- last_seq = resp[:seq]
48
+ @recvd.each do |recvd_item|
49
+ recvd_item[:response].seq.should == last_seq + 1
50
+ last_seq = recvd_item[:response].seq
50
51
  end
51
52
  end
52
53
 
53
54
  it "should include the identity of the sending socket" do
54
- @responses.each {|resp| resp[:identities].should_not be_nil}
55
+ @recvd.each do |recvd_item|
56
+ recvd_item[:response].identities.should_not be_nil
57
+ end
55
58
  end
56
59
 
57
60
  it "should send responses back to the proper xreq sender" do
58
61
  received_count = 0
59
62
 
60
- ddn = DripDrop::Node.new do
63
+ run_reactor(0.2) do
61
64
  addr = rand_addr
62
65
 
63
66
  rep = zmq_xrep(addr, :bind)
64
67
  req1 = zmq_xreq(addr, :connect)
65
68
  req2 = zmq_xreq(addr, :connect)
66
69
 
67
- rep.on_recv do |message,identities,seq|
68
- rep.send_message(message,identities,seq)
70
+ rep.on_recv do |message,response|
71
+ response.send_message(message)
69
72
  end
70
73
 
71
74
  r1_msg = DripDrop::Message.new("REQ1 Message")
@@ -82,10 +85,7 @@ describe "zmq xreq/xrep" do
82
85
  end
83
86
  end
84
87
  end
85
- ddn.start
86
- sleep 0.2
87
- ddn.stop rescue nil #This should work...
88
-
88
+
89
89
  received_count.should == 20
90
90
  end
91
91
  end
data/spec/node_spec.rb CHANGED
@@ -11,7 +11,6 @@ describe DripDrop::Node do
11
11
  end
12
12
 
13
13
  it "should start EventMachine" do
14
- pending "This is not repeatedly reliable"
15
14
  EM.reactor_running?.should be_true
16
15
  end
17
16
 
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,20 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib dripdrop]))
1
+ require File.expand_path(File.join(File.dirname(__FILE__), %w[. .. lib dripdrop]))
2
2
  Thread.abort_on_exception = true
3
3
 
4
- def rand_addr
5
- "tcp://127.0.0.1:#{rand(10_000) + 20_000}"
4
+ # Used to test websocket clients.
5
+ require 'gimite-websocket'
6
+
7
+ def rand_addr(scheme='tcp')
8
+ "#{scheme}://127.0.0.1:#{rand(10_000) + 20_000}"
9
+ end
10
+
11
+ def run_reactor(time=0.1,opts={},&block)
12
+ ddn = DripDrop::Node.new(opts,&block)
13
+ ddn.start
14
+ sleep time
15
+ ddn.stop
16
+ sleep 0.1
17
+ ddn
6
18
  end
19
+
20
+
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 3
8
- - 1
9
- version: 0.3.1
7
+ - 4
8
+ - 0
9
+ version: 0.4.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Andrew Cholakian
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-10-21 00:00:00 -07:00
17
+ date: 2010-11-15 00:00:00 -08:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -127,25 +127,43 @@ files:
127
127
  - doc_img/topology.png
128
128
  - dripdrop.gemspec
129
129
  - example/agent_test.rb
130
+ - example/combined.rb
130
131
  - example/http.rb
131
132
  - example/pubsub.rb
132
133
  - example/pushpull.rb
134
+ - example/stats_app/core.rb
135
+ - example/stats_app/public/.sass-cache/b48b4299d80c05f528daf63fe51d85e5e3c10d98/stats.scssc
136
+ - example/stats_app/public/backbone.js
137
+ - example/stats_app/public/build_templates.rb
138
+ - example/stats_app/public/json2.js
139
+ - example/stats_app/public/protovis-r3.2.js
140
+ - example/stats_app/public/stats.css
141
+ - example/stats_app/public/stats.haml
142
+ - example/stats_app/public/stats.html
143
+ - example/stats_app/public/stats.js
144
+ - example/stats_app/public/stats.scss
145
+ - example/stats_app/public/underscore.js
133
146
  - example/subclass.rb
134
147
  - example/xreq_xrep.rb
135
148
  - js/dripdrop.html
136
149
  - js/dripdrop.js
137
- - js/jack.js
138
150
  - js/qunit.css
139
151
  - js/qunit.js
140
152
  - lib/dripdrop.rb
141
153
  - lib/dripdrop/agent.rb
154
+ - lib/dripdrop/handlers/base.rb
142
155
  - lib/dripdrop/handlers/http.rb
143
156
  - lib/dripdrop/handlers/websockets.rb
144
157
  - lib/dripdrop/handlers/zeromq.rb
145
158
  - lib/dripdrop/message.rb
146
159
  - lib/dripdrop/node.rb
160
+ - lib/dripdrop/node/nodelet.rb
161
+ - spec/gimite-websocket.rb
147
162
  - spec/message_spec.rb
148
163
  - spec/node/http_spec.rb
164
+ - spec/node/nodelet_spec.rb
165
+ - spec/node/routing_spec.rb
166
+ - spec/node/websocket_spec.rb
149
167
  - spec/node/zmq_pushpull_spec.rb
150
168
  - spec/node/zmq_xrepxreq_spec.rb
151
169
  - spec/node_spec.rb
@@ -184,8 +202,12 @@ specification_version: 3
184
202
  summary: Evented framework for ZeroMQ and EventMachine Apps.
185
203
  test_files:
186
204
  - spec/spec_helper.rb
205
+ - spec/gimite-websocket.rb
187
206
  - spec/node/http_spec.rb
207
+ - spec/node/routing_spec.rb
188
208
  - spec/node/zmq_xrepxreq_spec.rb
189
209
  - spec/node/zmq_pushpull_spec.rb
210
+ - spec/node/nodelet_spec.rb
211
+ - spec/node/websocket_spec.rb
190
212
  - spec/message_spec.rb
191
213
  - spec/node_spec.rb