dripdrop 0.3.1 → 0.4.0

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.
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