Permalink
Browse files

Implemented gzip encoding, closes #5

  • Loading branch information...
1 parent cf54d36 commit bb107c2c7d1d5b13b4cbb9d17eedb5ff2e6e51c4 @iconara iconara committed Jun 18, 2012
Showing with 113 additions and 22 deletions.
  1. +51 −12 lib/autobahn/encoder.rb
  2. +1 −1 lib/autobahn/publisher.rb
  3. +61 −9 spec/integration/autobahn_intg_spec.rb
View
@@ -2,10 +2,10 @@
module Autobahn
class StringEncoder
- CONTENT_TYPE = 'application/octet-stream'.freeze
+ PROPERTIES = {:content_type => 'application/octet-stream'.freeze}.freeze
- def content_type
- CONTENT_TYPE
+ def properties
+ PROPERTIES
end
def encodes_batches?
@@ -25,11 +25,11 @@ def decode(str)
require 'json'
class JsonEncoder
- CONTENT_TYPE = 'application/json'.freeze
+ PROPERTIES = {:content_type => 'application/json'.freeze}.freeze
- def content_type
- CONTENT_TYPE
- end
+ def properties
+ PROPERTIES
+ end
def encodes_batches?
true
@@ -50,10 +50,10 @@ def decode(str)
require 'msgpack'
class MsgPackEncoder
- CONTENT_TYPE = 'application/msgpack'.freeze
+ PROPERTIES = {:content_type => 'application/msgpack'.freeze}.freeze
- def content_type
- CONTENT_TYPE
+ def properties
+ PROPERTIES
end
def encodes_batches?
@@ -65,7 +65,7 @@ def encode(obj)
end
def decode(str)
- MessagePack.unpack(str.force_encoding(Encoding::ASCII_8BIT))
+ MessagePack.unpack(str.force_encoding(Encoding::BINARY))
end
end
rescue LoadError
@@ -75,7 +75,7 @@ def decode(str)
require 'bson'
class BsonEncoder
- CONTENT_TYPE = 'application/bson'.freeze
+ PROPERTIES = {:content_type => 'application/bson'.freeze}.freeze
def content_type
CONTENT_TYPE
@@ -95,4 +95,43 @@ def decode(str)
end
rescue LoadError
end
+
+ begin
+ require 'zlib'
+ require 'stringio'
+
+ class GzipEncoder
+ CONTENT_ENCODING = 'gzip'.freeze
+
+ def initialize(decorated_encoder)
+ @decorated_encoder = decorated_encoder
+ end
+
+ def properties
+ @properties ||= begin
+ p = @decorated_encoder.properties.dup
+ p[:content_encoding] = CONTENT_ENCODING
+ p
+ end
+ end
+
+ def encodes_batches?
+ @decorated_encoder.encodes_batches?
+ end
+
+ def encode(obj)
+ io = StringIO.new
+ gz = Zlib::GzipWriter.new(io)
+ gz.print(@decorated_encoder.encode(obj))
+ gz.close
+ io.string
+ end
+
+ def decode(str)
+ io = StringIO.new(str)
+ gz = Zlib::GzipReader.new(io)
+ @decorated_encoder.decode(gz.read).tap { gz.close }
+ end
+ end
+ end
end
@@ -14,7 +14,7 @@ def publish(message)
rk = @strategy.select_routing_key(routing_keys, message)
ex = exchanges_by_routing_key[rk]
em = @encoder.encode(message)
- op = {:routing_key => rk, :properties => {:content_type => @encoder.content_type}}
+ op = {:routing_key => rk, :properties => @encoder.properties}
ex.publish(em, op)
end
@@ -92,16 +92,48 @@ def counting_down(n, options={})
end
context 'with encoded messages' do
+ before do
+ @encoded_transport_system = Autobahn.transport_system(api_uri, exchange_name, :encoder => Autobahn::JsonEncoder.new)
+ end
+
+ after do
+ @encoded_transport_system.disconnect! if @encoded_transport_system
+ end
+
it 'uses the provided encoder to encode messages' do
- begin
- transport_system = Autobahn.transport_system(api_uri, exchange_name, :encoder => Autobahn::JsonEncoder.new)
- publisher = transport_system.publisher
- publisher.publish({'hello' => 'world'})
- sleep(0.1) # allow time for delivery
- @queues.map { |q| h, m = q.get; m }.compact.first.should == '{"hello":"world"}'
- ensure
- transport_system.disconnect! if transport_system
- end
+ publisher = @encoded_transport_system.publisher
+ publisher.publish({'hello' => 'world'})
+ sleep(0.1) # allow time for delivery
+ @queues.map { |q| h, m = q.get; m }.compact.first.should == '{"hello":"world"}'
+ end
+ end
+
+ context 'with compressed messages' do
+ before do
+ encoder = Autobahn::GzipEncoder.new(Autobahn::JsonEncoder.new)
+ options = {:encoder => encoder}
+ @compressed_transport_system = Autobahn.transport_system(api_uri, exchange_name, options)
+ publisher = @compressed_transport_system.publisher
+ publisher.publish({'hello' => 'world'})
+ sleep(0.1) # allow time for delivery
+ end
+
+ after do
+ @compressed_transport_system.disconnect! if @compressed_transport_system
+ end
+
+ it 'uses the provided encoder to also compress messages' do
+ compressed_message = [31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 171, 86, 202, 72, 205, 201, 201, 87, 178, 82, 42, 207, 47, 202, 73, 81, 170, 5, 0, 209, 65, 9, 216, 17, 0, 0, 0].pack('C*')
+ actual_message = @queues.map { |q| h, m = q.get; m }.compact.first
+ actual_message.should == compressed_message
+ end
+
+ it 'sets the content-encoding header' do
+ @queues.map { |q| h, m = q.get; h.properties.content_encoding if h }.compact.first.should == 'gzip'
+ end
+
+ it 'sets the content-type header' do
+ @queues.map { |q| h, m = q.get; h.properties.content_type if h }.compact.first.should == 'application/json'
end
end
@@ -271,6 +303,26 @@ def counting_down(n, options={})
end
end
+ context 'with compressed messages' do
+ before do
+ options = {:encoder => Autobahn::GzipEncoder.new(Autobahn::JsonEncoder.new)}
+ @compressed_transport_system = Autobahn.transport_system(api_uri, exchange_name, options)
+ compressed_message = [31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 171, 86, 202, 72, 205, 201, 201, 87, 178, 82, 42, 207, 47, 202, 73, 81, 170, 5, 0, 209, 65, 9, 216, 17, 0, 0, 0].pack('C*')
+ @exchange.publish(compressed_message, :routing_key => routing_keys.sample)
+ sleep(0.1) # allow time for delivery
+ end
+
+ after do
+ @compressed_transport_system.disconnect! if @compressed_transport_system
+ end
+
+ it 'uses the provided encoder to decode messages' do
+ consumer = @compressed_transport_system.consumer
+ h, m = consumer.next(5)
+ m.should == {'hello' => 'world'}
+ end
+ end
+
context 'with batched messages' do
before do
@encoder = Autobahn::JsonEncoder.new

0 comments on commit bb107c2

Please sign in to comment.