dripdrop 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -40,7 +40,7 @@ Here's an example of the kind of thing DripDrop makes easy, from [example/combin
40
40
  end
41
41
  end.start! #Start the reactor and block until complete
42
42
 
43
- Note that these aren't regular ZMQ sockets, and that the HTTP server isn't a regular server. They only speak and respond using DripDrop::Message formatted messages. For HTTP/WebSockets it's JSON that looks like {name: 'name', head: {}, body: anything}, for ZeroMQ it means BERT. There is a raw mode that you can use for other message formats, but using DripDrop::Messages makes things easier, and for some socket types (like XREQ/XREP) the predefined format is very useful in matching requests to replies.
43
+ Note that these aren't regular ZMQ sockets, and that the HTTP server isn't a regular server. They only speak and respond using DripDrop::Message formatted messages. For HTTP/WebSockets it's JSON that looks like {name: 'name', head: {}, body: anything}, for ZeroMQ it means MessagePack. There is a raw mode that you can use for other message formats, but using DripDrop::Messages makes things easier, and for some socket types (like XREQ/XREP) the predefined format is very useful in matching requests to replies.
44
44
 
45
45
  #RDoc
46
46
 
@@ -48,7 +48,7 @@ RDocs can be found [here](http://www.rdoc.info/github/andrewvc/dripdrop/master/f
48
48
 
49
49
  #How It Works
50
50
 
51
- DripDrop encapsulates both zmqmachine, and eventmachine. It provides some sane default messaging choices, using [BERT](http://github.com/blog/531-introducing-bert-and-bert-rpc) (A binary, JSON, like serialization format) and JSON for serialization. While zmqmachine and eventmachine APIs, some convoluted ones, the goal here is to smooth over the bumps, and make them play together nicely.
51
+ DripDrop encapsulates both zmqmachine, and eventmachine. It provides some sane default messaging choices, using [MessagePack](http://msgpack.org/)(A binary, JSON, like serialization format) and JSON for serialization. While zmqmachine and eventmachine APIs, some convoluted ones, the goal here is to smooth over the bumps, and make them play together nicely.
52
52
 
53
53
  #Contributors
54
54
 
data/Rakefile CHANGED
@@ -15,7 +15,7 @@ begin
15
15
  gem.add_dependency('em-websocket')
16
16
  gem.add_dependency('thin')
17
17
  gem.add_dependency('zmqmachine')
18
- gem.add_dependency('bert')
18
+ gem.add_dependency('msgpack')
19
19
  gem.add_dependency('json')
20
20
  end
21
21
  Jeweler::GemcutterTasks.new
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.0
1
+ 0.6.0
data/dripdrop.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{dripdrop}
8
- s.version = "0.5.0"
8
+ s.version = "0.6.0"
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{2010-11-16}
12
+ s.date = %q{2010-12-17}
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 = [
@@ -74,16 +74,16 @@ Gem::Specification.new do |s|
74
74
  s.rubygems_version = %q{1.3.7}
75
75
  s.summary = %q{Evented framework for ZeroMQ and EventMachine Apps.}
76
76
  s.test_files = [
77
- "spec/spec_helper.rb",
78
- "spec/gimite-websocket.rb",
77
+ "spec/gimite-websocket.rb",
78
+ "spec/message_spec.rb",
79
+ "spec/node_spec.rb",
80
+ "spec/spec_helper.rb",
79
81
  "spec/node/http_spec.rb",
80
- "spec/node/routing_spec.rb",
81
- "spec/node/zmq_xrepxreq_spec.rb",
82
- "spec/node/zmq_pushpull_spec.rb",
83
82
  "spec/node/nodelet_spec.rb",
83
+ "spec/node/routing_spec.rb",
84
84
  "spec/node/websocket_spec.rb",
85
- "spec/message_spec.rb",
86
- "spec/node_spec.rb"
85
+ "spec/node/zmq_pushpull_spec.rb",
86
+ "spec/node/zmq_xrepxreq_spec.rb"
87
87
  ]
88
88
 
89
89
  if s.respond_to? :specification_version then
@@ -96,7 +96,7 @@ Gem::Specification.new do |s|
96
96
  s.add_runtime_dependency(%q<em-websocket>, [">= 0"])
97
97
  s.add_runtime_dependency(%q<thin>, [">= 0"])
98
98
  s.add_runtime_dependency(%q<zmqmachine>, [">= 0"])
99
- s.add_runtime_dependency(%q<bert>, [">= 0"])
99
+ s.add_runtime_dependency(%q<msgpack>, [">= 0"])
100
100
  s.add_runtime_dependency(%q<json>, [">= 0"])
101
101
  else
102
102
  s.add_dependency(%q<ffi-rzmq>, [">= 0"])
@@ -104,7 +104,7 @@ Gem::Specification.new do |s|
104
104
  s.add_dependency(%q<em-websocket>, [">= 0"])
105
105
  s.add_dependency(%q<thin>, [">= 0"])
106
106
  s.add_dependency(%q<zmqmachine>, [">= 0"])
107
- s.add_dependency(%q<bert>, [">= 0"])
107
+ s.add_dependency(%q<msgpack>, [">= 0"])
108
108
  s.add_dependency(%q<json>, [">= 0"])
109
109
  end
110
110
  else
@@ -113,7 +113,7 @@ Gem::Specification.new do |s|
113
113
  s.add_dependency(%q<em-websocket>, [">= 0"])
114
114
  s.add_dependency(%q<thin>, [">= 0"])
115
115
  s.add_dependency(%q<zmqmachine>, [">= 0"])
116
- s.add_dependency(%q<bert>, [">= 0"])
116
+ s.add_dependency(%q<msgpack>, [">= 0"])
117
117
  s.add_dependency(%q<json>, [">= 0"])
118
118
  end
119
119
  end
data/example/subclass.rb CHANGED
@@ -10,14 +10,14 @@ Thread.abort_on_exception = true
10
10
  class TimestampedMessage < DripDrop::Message
11
11
  def self.create_message(*args)
12
12
  obj = super
13
- obj.head[:timestamps] = []
14
- obj.head[:timestamps] << Time.now
13
+ obj.head['timestamps'] = []
14
+ obj.head['timestamps'] << Time.now.to_s
15
15
  obj
16
16
  end
17
17
 
18
18
  def self.recreate_message(*args)
19
19
  obj = super
20
- obj.head[:timestamps] << Time.now.to_s
20
+ obj.head['timestamps'] << Time.now.to_s
21
21
  obj
22
22
  end
23
23
  end
@@ -37,13 +37,13 @@ node = DripDrop::Node.new do
37
37
  pull2 = zmq_pull("tcp://127.0.0.1:2202", :connect)
38
38
 
39
39
  pull1.on_recv do |msg|
40
- puts "Pull 1 #{msg.head}"
40
+ puts "Pull 1 #{msg.head.inspect}"
41
41
  sleep 1
42
42
  push2.send_message(msg)
43
43
  end
44
44
 
45
45
  pull2.on_recv do |msg|
46
- puts "Pull 2 #{msg.head}"
46
+ puts "Pull 2 #{msg.head.inspect}"
47
47
  end
48
48
 
49
49
  push1.send_message(TimestampedMessage.create_message(:name => 'test', :body => "Hello there"))
@@ -8,7 +8,6 @@ else
8
8
  ZMQGEM = :ffirzmq
9
9
  end
10
10
  require 'uri'
11
- require 'bert'
12
11
 
13
12
  class DripDrop
14
13
  #The Agent class is a simple ZMQ Pub client. It uses DripDrop::Message messages
@@ -1,4 +1,5 @@
1
1
  require 'thin'
2
+ require 'thin_parser'
2
3
  require 'json'
3
4
 
4
5
  class DripDrop
@@ -1,5 +1,5 @@
1
1
  require 'rubygems'
2
- require 'bert'
2
+ require 'msgpack'
3
3
  require 'json'
4
4
 
5
5
  class DripDrop
@@ -11,8 +11,7 @@ class DripDrop
11
11
  # body: anything you'd like, it can be null even
12
12
  #
13
13
  # Hashes, arrays, strings, integers, symbols, and floats are probably what you should stick to.
14
- # Internally, they're just stored as BERT, which is great because if you don't use JSON
15
- # things like symbols and binary data are transmitted more efficiently and transparently.
14
+ # Internally, they're just stored using MsgPack, which is pretty much a super-fast, binary JSON
16
15
  #
17
16
  # The basic message format is built to mimic HTTP (s/url_path/name/). Why? Because I'm a dumb web developer :)
18
17
  # The name is kind of like the URL, its what kind of message this is, but it's a loose definition,
@@ -24,22 +23,22 @@ class DripDrop
24
23
 
25
24
  # Creates a new message.
26
25
  # example:
27
- # DripDrop::Message.new('mymessage', :head => {:timestamp => Time.now},
26
+ # DripDrop::Message.new('mymessage', 'head' => {:timestamp => Time.now},
28
27
  # :body => {:mykey => :myval, :other_key => ['complex']})
29
28
  def initialize(name,extra={})
30
29
  raise ArgumentError, "Message names may not be empty or null!" if name.nil? || name.empty?
31
30
 
32
- @head = extra[:head] || {}
31
+ @head = extra[:head] || extra['head'] || {}
33
32
  raise ArgumentError, "Invalid head #{@head}. Head must be a hash!" unless @head.is_a?(Hash)
34
- @head[:msg_class] = self.class.to_s
33
+ @head['msg_class'] = self.class.to_s
35
34
 
36
35
  @name = name
37
- @body = extra[:body]
36
+ @body = extra[:body] || extra['body']
38
37
  end
39
38
 
40
39
  # The encoded message, ready to be sent across the wire via ZMQ
41
40
  def encoded
42
- BERT.encode(self.to_hash)
41
+ self.to_hash.to_msgpack
43
42
  end
44
43
 
45
44
  # Encodes the hash represntation of the message to JSON
@@ -50,15 +49,17 @@ class DripDrop
50
49
  def encode_json; json_encoded; end
51
50
 
52
51
  # Convert the Message to a hash like:
53
- # {:name => @name, :head => @head, :body => @body}
52
+ # {'name' => @name, 'head' => @head, 'body' => @body}
54
53
  def to_hash
55
- {:name => @name, :head => @head, :body => @body}
54
+ {'name' => @name, 'head' => @head, 'body' => @body}
56
55
  end
57
56
 
58
57
  # Build a new Message from a hash that looks like
59
- # {:name => name, :body => body, :head => head}
58
+ # {:name => name, :body => body, 'head' => head}
60
59
  def self.from_hash(hash)
61
- self.new(hash[:name],:head => hash[:head], :body => hash[:body])
60
+ self.new(hash[:name] || hash['name'],
61
+ :head => hash[:head] || hash['head'],
62
+ :body => hash[:body] || hash['body'])
62
63
  end
63
64
 
64
65
  def self.create_message(*args)
@@ -69,7 +70,8 @@ class DripDrop
69
70
  end
70
71
 
71
72
  def self.recreate_message(hash)
72
- raise ArgumentError, "Wrong message class #{hash[:head][:msg_class]} for #{self.to_s}" unless hash[:head][:msg_class] == self.to_s
73
+ raise ArgumentError, "Message missing head: #{hash.inspect}" unless hash['head']
74
+ raise ArgumentError, "Wrong message class #{hash['head']['msg_class']} for #{self.to_s}" unless hash['head']['msg_class'] == self.to_s
73
75
  self.from_hash(hash)
74
76
  end
75
77
 
@@ -82,7 +84,7 @@ class DripDrop
82
84
  msg = msg.copy_out_string
83
85
  return nil if msg.empty?
84
86
  end
85
- decoded = BERT.decode(msg)
87
+ decoded = MessagePack.unpack(msg)
86
88
  self.recreate_message(decoded)
87
89
  end
88
90
 
@@ -99,10 +101,10 @@ class DripDrop
99
101
  end
100
102
 
101
103
  # Keep this consistent
102
- json_hash['head'][:msg_class] = json_hash['head'][:msg_class]
104
+ json_hash['head']['msg_class'] = json_hash['head']['msg_class']
103
105
  json_hash['head'].delete('msg_class')
104
106
 
105
- self.new(json_hash['name'], :head => json_hash['head'], :body => json_hash['body'])
107
+ self.new(json_hash['name'], 'head' => json_hash['head'], :body => json_hash['body'])
106
108
  end
107
109
  end
108
110
 
@@ -121,12 +123,15 @@ class DripDrop
121
123
  def verify_args(*args)
122
124
  head =
123
125
  case args[0]
124
- when Hash then args[0][:head]
125
- else args[1]
126
+ when Hash
127
+ az = args[0]
128
+ az[:head] || az['head']
129
+ else
130
+ args[1]
126
131
  end
127
- raise ArgumentError, "Invalid head #{head}. Head must be a hash!" unless head.is_a?(Hash)
132
+ raise ArgumentError, "Invalid head #{head.inspect}. Head must be a hash! (args: #{args.inspect})" unless head.is_a?(Hash)
128
133
 
129
- msg_class = head[:msg_class]
134
+ msg_class = head['msg_class']
130
135
  unless DripDrop::AutoMessageClass.message_subclasses.has_key?(msg_class)
131
136
  raise ArgumentError, "Unknown AutoMessage message class #{msg_class}"
132
137
  end
data/spec/message_spec.rb CHANGED
@@ -9,8 +9,8 @@ describe DripDrop::Message do
9
9
  def create_basic
10
10
  attrs = {
11
11
  :name => 'test',
12
- :head => {:foo => :bar},
13
- :body => [:foo, :bar, :baz]
12
+ :head => {'foo' => 'bar'},
13
+ :body => ['foo', 'bar', 'baz']
14
14
  }
15
15
  message = DripDrop::Message.new(attrs[:name],:head => attrs[:head],
16
16
  :body => attrs[:body])
@@ -28,7 +28,7 @@ describe DripDrop::Message do
28
28
  }.should_not raise_exception
29
29
  end
30
30
  it "should set the head to a single key hash containing message class if nil provided" do
31
- DripDrop::Message.new('nilhead', :head => nil).head.should == {:msg_class => 'DripDrop::Message'}
31
+ DripDrop::Message.new('nilhead', :head => nil).head.should == {'msg_class' => 'DripDrop::Message'}
32
32
  end
33
33
  it "should raise an exception if a non-hash, non-nil head is provided" do
34
34
  lambda {
@@ -40,10 +40,10 @@ describe DripDrop::Message do
40
40
  before(:all) do
41
41
  @message, @attrs = create_basic
42
42
  end
43
- it "should encode to valid BERT hash without error" do
43
+ it "should encode to valid MessagePack hash without error" do
44
44
  enc = @message.encoded
45
45
  enc.should be_a(String)
46
- BERT.decode(enc).should be_a(Hash)
46
+ MessagePack.unpack(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)
@@ -67,8 +67,8 @@ describe DripDrop::Message do
67
67
  def create_auto_message
68
68
  attrs = {
69
69
  :name => 'test',
70
- :head => {:foo => :bar, :msg_class => 'SpecMessageClass'},
71
- :body => [:foo, :bar, :baz]
70
+ :head => {'foo' => 'bar', 'msg_class' => 'SpecMessageClass'},
71
+ :body => ['foo', 'bar', 'baz']
72
72
  }
73
73
 
74
74
  message = DripDrop::AutoMessageClass.create_message(attrs)
@@ -81,21 +81,16 @@ describe DripDrop::Message do
81
81
  it "should be added to the subclass message class hash if SubclassedMessage included" do
82
82
  DripDrop::AutoMessageClass.message_subclasses.should include('SpecMessageClass' => SpecMessageClass)
83
83
  end
84
- it "should set the msg_class using a symbol, not a string when using JSON" do
85
- msg = DripDrop::Message.decode_json(DripDrop::Message.new('test').json_encoded)
86
- msg.head['msg_class'].should be_nil
87
- msg.head[:msg_class].should == 'DripDrop::Message'
88
- end
89
84
  it "should throw an exception if we try to recreate a message of the wrong class" do
90
85
  msg = DripDrop::Message.new('test')
91
86
  lambda{SpecMessageClass.recreate_message(msg.to_hash)}.should raise_exception
92
87
  end
93
88
 
94
89
  describe "DripDrop::AutoMessageClass" do
95
- it "should create a properly classed message based on head[:msg_class]" do
90
+ it "should create a properly classed message based on head['msg_class']" do
96
91
  @message.should be_a(SpecMessageClass)
97
92
  end
98
- it "should recreate a message based on head[:msg_class]" do
93
+ it "should recreate a message based on head['msg_class']" do
99
94
  DripDrop::AutoMessageClass.recreate_message(@message.to_hash).should be_a(SpecMessageClass)
100
95
  end
101
96
  end
@@ -36,11 +36,11 @@ describe "http" do
36
36
  @sent = []
37
37
  10.times {|i| @sent << DripDrop::Message.new("test-#{i}")}
38
38
  @client_responses = []
39
- http_info = http_send_messages(@sent) do |sent_message,resp_message|
39
+ @http_info = http_send_messages(@sent) do |sent_message,resp_message|
40
40
  @client_responses << {:sent_message => sent_message,
41
41
  :resp_message => resp_message}
42
42
  end
43
- @responses = http_info[:responses]
43
+ @responses = @http_info[:responses]
44
44
  end
45
45
 
46
46
  it "should receive all sent messages" do
@@ -16,7 +16,7 @@ describe "zmq xreq/xrep" do
16
16
  rep.on_recv do |message,response|
17
17
  recvd << {:message => message, :response => response}
18
18
 
19
- response.send_message :name => 'response', :body => {:orig_name => message.name}
19
+ response.send_message :name => 'response', :body => {'orig_name' => message.name}
20
20
  end
21
21
 
22
22
  to_send.each do |message|
@@ -47,7 +47,7 @@ describe "zmq xreq/xrep" do
47
47
 
48
48
  it "should receive a reply message for each sent message" do
49
49
  @sent.zip(@replied).each do |sent, replied|
50
- replied.body[:orig_name].should == sent.name
50
+ replied.body['orig_name'].should == sent.name
51
51
  end
52
52
  end
53
53
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dripdrop
3
3
  version: !ruby/object:Gem::Version
4
- hash: 11
4
+ hash: 7
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 5
8
+ - 6
9
9
  - 0
10
- version: 0.5.0
10
+ version: 0.6.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Andrew Cholakian
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-11-16 00:00:00 -08:00
18
+ date: 2010-12-17 00:00:00 -08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -89,7 +89,7 @@ dependencies:
89
89
  type: :runtime
90
90
  version_requirements: *id005
91
91
  - !ruby/object:Gem::Dependency
92
- name: bert
92
+ name: msgpack
93
93
  prerelease: false
94
94
  requirement: &id006 !ruby/object:Gem::Requirement
95
95
  none: false
@@ -211,13 +211,13 @@ signing_key:
211
211
  specification_version: 3
212
212
  summary: Evented framework for ZeroMQ and EventMachine Apps.
213
213
  test_files:
214
- - spec/spec_helper.rb
215
214
  - spec/gimite-websocket.rb
215
+ - spec/message_spec.rb
216
+ - spec/node_spec.rb
217
+ - spec/spec_helper.rb
216
218
  - spec/node/http_spec.rb
217
- - spec/node/routing_spec.rb
218
- - spec/node/zmq_xrepxreq_spec.rb
219
- - spec/node/zmq_pushpull_spec.rb
220
219
  - spec/node/nodelet_spec.rb
220
+ - spec/node/routing_spec.rb
221
221
  - spec/node/websocket_spec.rb
222
- - spec/message_spec.rb
223
- - spec/node_spec.rb
222
+ - spec/node/zmq_pushpull_spec.rb
223
+ - spec/node/zmq_xrepxreq_spec.rb