riakpb 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ === 0.0.1 2010-05-21
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
data/Manifest.txt ADDED
@@ -0,0 +1,30 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.rdoc
4
+ Rakefile
5
+ lib/riak.rb
6
+ lib/riak/client.rb
7
+ lib/riak/client/rpc.rb
8
+ lib/riak/client_pb.rb
9
+ lib/riak/bucket.rb
10
+ lib/riak/key.rb
11
+ lib/riak/riak_content.rb
12
+ lib/riak/i18n.rb
13
+ lib/riak/locale/en.yml
14
+ lib/riak/util/decode.rb
15
+ lib/riak/util/encode.rb
16
+ lib/riak/util/message_code.rb
17
+ lib/riak/util/translation.rb
18
+ lib/riak/failed_exchange.rb
19
+ lib/riak/failed_request.rb
20
+ lib/riak/sibling_error.rb
21
+ script/console
22
+ script/destroy
23
+ script/generate
24
+ spec/spec_helper.rb
25
+ spec/riak/client_spec.rb
26
+ spec/riak/rpc_spec.rb
27
+ spec/riak/bucket_spec.rb
28
+ spec/riak/key_spec.rb
29
+ spec/riak/riak_content_spec.rb
30
+ spec/riak/map_reduce_spec.rb
data/README.rdoc ADDED
@@ -0,0 +1,156 @@
1
+ = riak Ruby Protocol Buffers Client
2
+
3
+ * http://github.com/aitrus/riak-pbclient
4
+
5
+ == DESCRIPTION:
6
+
7
+ This is a Ruby client for Riak, using protocol buffers instead of REST. It offers some benefit in terms of speed and it abstracts Buckets/Keys differently than does the REST client. Different != Better.
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * It can list buckets! Huzzah!
12
+ * You can destroy a bucket, which basically lists its keys and iterates over them--deleting each.
13
+ * It works, which surely counts for something.
14
+ * It's still rough around the edges, but certainly usable. I'm attempting to polish it, though <b>suggestions welcome</b>.
15
+
16
+ == SYNOPSIS:
17
+
18
+ This is a work in progress and I am current improving the rspec and the documentation, but please have fun and give me some feedback. The below examples give you an overview on how to use this package.
19
+
20
+ === Connect to riak and ping it:
21
+
22
+ >> client = Riak::Client.new # Riak::Client.new({:host => "ubuntu01", :port => 1234})
23
+ => #<Riak::Client:0x0000010328a040 @host="127.0.0.1", @port=8087, @w=nil, @dw=nil, @buckets=[], @bucket_cache={}>
24
+ >> client.ping?
25
+ => true
26
+
27
+ === List Buckets within riak:
28
+ <i>Not suggested for use in production</i>
29
+
30
+ >> client = Riak::Client.new
31
+ => #<Riak::Client:0x00000101439a78 @host="127.0.0.1", @port=8087, @w=nil, @dw=nil, @buckets=[], @bucket_cache={}>
32
+ >> client.buckets
33
+ => ["hb", "goog"]
34
+
35
+ === Fetch a Bucket:
36
+
37
+ >> bucket = client["goog"]
38
+ => #<Riak::Bucket name=goog, props={n_val=>3, allow_mult=false}>
39
+
40
+ === Destroy a Bucket:
41
+
42
+ >> bucket.destroy!
43
+ => true
44
+
45
+ === List Keys within the Bucket:
46
+
47
+ >> bucket = client["goog"]
48
+ => #<Riak::Bucket name=goog, props={n_val=>3, allow_mult=false}>
49
+ >> bucket.keys
50
+ => ["2010-05-03", "2010-03-24", "2010-03-05", "2010-02-25", <b>SNIP 80~ Lines</b>, "2005-02-10", "2005-01-04"]
51
+
52
+ === Fetch a Key:
53
+
54
+ >> key = bucket["2010-04-12"]
55
+ => #<Riak::Key name="2010-04-12", vclock="k\xCEa```\xCC`\xCA\x05R,\xCC\xF3{*2\x98\x12\x19\xF3X\x19N\xCF\xEB8\xCA\x97\x05\x00", contents=[#<#Riak::RiakContent value={"Date"=>Mon, 12 Apr 2010, "Open"=>"567.35", "High"=>"574.00", "Low"=>"566.22", "Close"=>"572.73", "Volume"=>"2352400", "Adj Close"=>"572.73"}, content_type="application/json", vtag="3pbhcnmUtPZvXBSCmo5ESs", links=[], last_mod=1276388043, last_mod_usecs=65345, usermeta={}>]>
56
+
57
+ === Fetch a Key's Content:
58
+ <i>Differs from the REST client. Key+RiakContent = ROjbect</i>
59
+
60
+ >> rcon = key.content
61
+ => #<#Riak::RiakContent value={"Date"=>Mon, 12 Apr 2010, "Open"=>"567.35", "High"=>"574.00", "Low"=>"566.22", "Close"=>"572.73", "Volume"=>"2352400", "Adj Close"=>"572.73"}, content_type="application/json", vtag="3pbhcnmUtPZvXBSCmo5ESs", links=[], last_mod=1276388043, last_mod_usecs=65345, usermeta={}>
62
+
63
+ === Play with the RiakContent's data and save it:
64
+
65
+ >> rcon.value
66
+ => {"Date"=>Mon, 12 Apr 2010, "Open"=>"567.35", "High"=>"574.00", "Low"=>"566.22", "Close"=>"572.73", "Volume"=>"2352400", "Adj Close"=>"572.73"}
67
+ >> rcon.value.class
68
+ => Hash
69
+ >> rcon.value["Date"]
70
+ => Mon, 12 Apr 2010
71
+ >> rcon.value["Date"] += 1.day
72
+ => Tue, 13 Apr 2010
73
+ >> rcon
74
+ => #<#Riak::RiakContent value={"Date"=>Tue, 13 Apr 2010, "Open"=>"567.35", "High"=>"574.00", "Low"=>"566.22", "Close"=>"572.73", "Volume"=>"2352400", "Adj Close"=>"572.73"}, content_type="application/json", vtag="3pbhcnmUtPZvXBSCmo5ESs", links=[], last_mod=1276388043, last_mod_usecs=65345, usermeta={}>
75
+ >> rcon.save
76
+ => true
77
+ >> key = bucket["2010-04-12"]
78
+ => #<Riak::Key name="2010-04-12", vclock="k\xCEa```\xCA`\xCA\x05R,\xCC\xF3{*2\x98\x12\x19\xF3X\x19N\xCF\xEB8\xCA\a\x13\xFE\x9A\xF3\x05*|x)P8\v\x00", contents=[#<#Riak::RiakContent value={"Date"=>Tue, 13 Apr 2010, "Open"=>"567.35", "High"=>"574.00", "Low"=>"566.22", "Close"=>"572.73", "Volume"=>"2352400", "Adj Close"=>"572.73"}, content_type="application/json", vtag="2wCEI09OVZEUcHozcm9XCX", links=[], last_mod=1276389827, last_mod_usecs=762316, usermeta={}>]>
79
+ >> rcon = key.content
80
+ => #<#Riak::RiakContent value={"Date"=>Tue, 13 Apr 2010, "Open"=>"567.35", "High"=>"574.00", "Low"=>"566.22", "Close"=>"572.73", "Volume"=>"2352400", "Adj Close"=>"572.73"}, content_type="application/json", vtag="2wCEI09OVZEUcHozcm9XCX", links=[], last_mod=1276389827, last_mod_usecs=762316, usermeta={}>
81
+ >> rcon.value["Date"] -= 1.day
82
+ => Mon, 12 Apr 2010
83
+ >> rcon.save
84
+ => true
85
+ >> key = bucket["2010-04-12"]
86
+ => #<Riak::Key name="2010-04-12", vclock="k\xCEa```\xCA`\xCA\x05R,\xCC\xF3{*2\x98\x12\x19\xF3X\x19N\xCF\xEB8\xCA\a\x13\xFE\x9A\xF3\x05(\xCC\x04\x14~\xBC\x14(\x9C\x05\x00", contents=[#<#Riak::RiakContent value={"Date"=>Mon, 12 Apr 2010, "Open"=>"567.35", "High"=>"574.00", "Low"=>"566.22", "Close"=>"572.73", "Volume"=>"2352400", "Adj Close"=>"572.73"}, content_type="application/json", vtag="264RmLHrCK89zvhtq4n6Fj", links=[], last_mod=1276389859, last_mod_usecs=810556, usermeta={}>]>
87
+ >> rcon = key.content
88
+ => #<#Riak::RiakContent value={"Date"=>Mon, 12 Apr 2010, "Open"=>"567.35", "High"=>"574.00", "Low"=>"566.22", "Close"=>"572.73", "Volume"=>"2352400", "Adj Close"=>"572.73"}, content_type="application/json", vtag="264RmLHrCK89zvhtq4n6Fj", links=[], last_mod=1276389859, last_mod_usecs=810556, usermeta={}>
89
+ >>
90
+
91
+ === MapReduce:
92
+
93
+ I'm working on ways to simplify M/R requests. It works the same as in ripple. Largely because it's ripped off from it, with very few changes (so far).
94
+
95
+ === Load the GOOG stocks from the riak Fast Track:
96
+
97
+ require 'riak'
98
+ require 'csv'
99
+
100
+ client = Riak::Client.new
101
+ bucket = client["goog"]
102
+
103
+ CSV.foreach('goog.csv', :headers => true) do |row|
104
+ puts row.first[1].to_s
105
+ key = bucket[row.first[1].to_s]
106
+ key.content.value = Hash[row.to_a]
107
+ key.save
108
+ end
109
+
110
+ == REQUIREMENTS:
111
+
112
+ * Rspec >= 2.0.0.beta.9
113
+ * ActiveSupport >= 3.0.0.beta3
114
+ * [Rakefile] hoe >= 2.1.0
115
+ * [Rakefile] newgem
116
+
117
+ == INSTALL:
118
+
119
+ git clone git://github.com/aitrus/riak-pbclient.git
120
+ cd riak-pbclient
121
+ rake gem
122
+ [sudo] gem install -l riak-X.Y.Z.gem
123
+
124
+ == LINKS:
125
+
126
+ * Riak Fast Track: https://wiki.basho.com/display/RIAK/The+Riak+Fast+Track
127
+ * Riak Fast Track GOOG data: https://wiki.basho.com/display/RIAK/Loading+Data+and+Running+MapReduce+Queries
128
+ * Ruby Client for Riak's REST Interface: http://github.com/seancribbs/ripple
129
+
130
+ == THANKS:
131
+
132
+ This is my first public open source whatever, and I appreciate the people in #riak who tolerated me.
133
+
134
+ == LICENSE:
135
+
136
+ Copyright 2010:
137
+ Scott Gonyea
138
+ Sean Cribbs, Sonian Inc.
139
+ Basho Technologies, Inc.
140
+
141
+ The riak-pbclient was pieced together by Scott Gonyea. Big chunks
142
+ of code were lifted / refactored from the riak-client project, by
143
+ Sean Cribbs. Lots of pieces are my own work, but it doesn't really
144
+ matter to me.
145
+
146
+ Licensed under the Apache License, Version 2.0 (the "License");
147
+ you may not use this file except in compliance with the License.
148
+ You may obtain a copy of the License at
149
+
150
+ http://www.apache.org/licenses/LICENSE-2.0
151
+
152
+ Unless required by applicable law or agreed to in writing, software
153
+ distributed under the License is distributed on an "AS IS" BASIS,
154
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
155
+ See the License for the specific language governing permissions and
156
+ limitations under the License.
data/Rakefile ADDED
@@ -0,0 +1,43 @@
1
+ require 'rubygems'
2
+ gem 'hoe', '>= 2.1.0'
3
+ require 'hoe'
4
+ require 'fileutils'
5
+ require './lib/riak'
6
+
7
+ Hoe.plugin :newgem
8
+ # Hoe.plugin :website
9
+ # Hoe.plugin :cucumberfeatures
10
+
11
+ # Generate all the Rake tasks
12
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
13
+ $hoe = Hoe.spec 'riakpb' do
14
+ self.developer 'Scott Gonyea', 'me@sgonyea.com'
15
+ self.rubyforge_name = self.name
16
+ self.summary = 'riak-pbclient is a protocol buffer client for Riak--the distributed database by Basho.'
17
+ self.url = 'http://github.com/aitrus/riak-pbclient'
18
+ end
19
+
20
+ require 'rspec/core'
21
+ require 'rspec/core/rake_task'
22
+
23
+ desc "Run Unit Specs Only"
24
+ Rspec::Core::RakeTask.new(:spec) do |spec|
25
+ spec.pattern = "spec/riak/**/*_spec.rb"
26
+ end
27
+
28
+ namespace :spec do
29
+ desc "Run Integration Specs Only"
30
+ Rspec::Core::RakeTask.new(:integration) do |spec|
31
+ spec.pattern = "spec/integration/**/*_spec.rb"
32
+ end
33
+
34
+ desc "Run All Specs"
35
+ Rspec::Core::RakeTask.new(:all) do |spec|
36
+ spec.pattern = Rake::FileList["spec/**/*_spec.rb"]
37
+ end
38
+ end
39
+
40
+ # TODO - want other tests/tasks run by default? Add them to the list
41
+ # remove_task :default
42
+ # task :default => [:spec, :features]
43
+
@@ -0,0 +1,177 @@
1
+ require 'riak'
2
+
3
+ module Riak
4
+ # Represents and encapsulates operations on a Riak bucket. You may retrieve a bucket
5
+ # using {Client#bucket}, or create it manually and retrieve its meta-information later.
6
+ class Bucket
7
+ include Util::Translation
8
+ include Util::MessageCode
9
+
10
+ # @return [Riak::Client] the associated client
11
+ attr_reader :client
12
+
13
+ # @return [String] the bucket name
14
+ attr_reader :name
15
+
16
+ # @return [Fixnum] the number of replicas for objects in this bucket
17
+ attr_reader :n_val
18
+
19
+ # @return [TrueClass/FalseClass] whether or not a key's siblings are to be retrieved
20
+ attr_reader :allow_mult
21
+
22
+ attr_reader :key_cache
23
+
24
+ # Create a Riak bucket manually.
25
+ # @param [Client] client the {Riak::Client} for this bucket
26
+ # @param [String] name the name of the bucket
27
+ def initialize(client, name, options={})
28
+ options.assert_valid_keys(:n_val, :allow_mult)
29
+ raise ArgumentError, t("client_type", :client => client.inspect) unless client.is_a?(Client)
30
+ raise ArgumentError, t("string_type", :string => name.inspect) unless name.is_a?(String)
31
+
32
+ @client = client
33
+ @name = name
34
+ @n_val = options[:n_val] || nil
35
+ @allow_mult = options[:allow_mult] || nil
36
+ @key_cache = Hash.new{|k,v| k[v] = Riak::Key.new(self, v)}
37
+ end
38
+
39
+ # Load information for the bucket from a response given by the {Riak::Client::HTTPBackend}.
40
+ # Used mostly internally - use {Riak::Client#bucket} to get a {Bucket} instance.
41
+ # @param [RpbHash] response a response from {Riak::Client::HTTPBackend}
42
+ # @return [Bucket] self
43
+ # @see Client#bucket
44
+ def load(response)
45
+ raise ArgumentError, t("response_type") unless response.is_a?(Riak::RpbGetBucketResp)
46
+
47
+ self.n_val = response.props.n_val
48
+ self.allow_mult = response.props.allow_mult
49
+
50
+ return(self)
51
+ end
52
+
53
+ # Accesses or retrieves a list of keys in this bucket. Needs to have expiration / cacheing, though not now.
54
+ # @return [Array<String>] Keys in this bucket
55
+ def keys
56
+ @keys ||= @client.keys_in @name
57
+ end
58
+
59
+ # Accesses or retrieves a list of keys in this bucket. Needs to have expiration / cacheing, though not now.
60
+ # @return [Array<String>] Keys in this bucket
61
+ def keys!
62
+ @keys = @client.keys_in @name
63
+ end
64
+
65
+ # Retrieve an object from within the bucket.
66
+ # @param [String] key the key of the object to retrieve
67
+ # @param [Fixnum] r - the read quorum for the request - how many nodes should concur on the read
68
+ # @return [Riak::Key] the object
69
+ def key(key, options={})
70
+ raise ArgumentError, t("fixnum_invalid", :num => options[:r]) unless options[:r].is_a?(NilClass) or options[:r].is_a?(Fixnum)
71
+ raise ArgumentError, t("string_invalid", :string => key) unless key.is_a?(String)
72
+
73
+ if options[:safely] == true and not @key_cache[key].empty?
74
+ return(@key_cache[key])
75
+ end
76
+
77
+ response = @client.get_request @name, key, options[:r]
78
+
79
+ @key_cache[key].load(response)
80
+ end
81
+ alias :[] :key
82
+
83
+ # Retrieve an object from within the bucket. Will raise an error message if key does not exist.
84
+ # @param [String] key the key of the object to retrieve
85
+ # @param [Fixnum] quorum - the read quorum for the request - how many nodes should concur on the read
86
+ # @return [Riak::Key] the object
87
+ def key!(key, r=nil)
88
+ raise ArgumentError, t("string_invalid", :string => key) unless key.is_a?(String)
89
+ raise ArgumentError, t("fixnum_invalid", :num => r) unless r.is_a?(Fixnum)
90
+
91
+ response = @client.get_request @name, key, r
92
+
93
+ Riak::Key.new(self, key).load!(response)
94
+ end
95
+
96
+ # Retrieves a Key from the given Bucket. Originally written for link retrieval.
97
+ # @param [String] bucket the name of the bucket, in which the Key is contained
98
+ # @param [String] key the name of the key to retrieve
99
+ # @option options [Fixnum] :quorum read quorum- num of replicas need to agree when retrieving the object
100
+ # @return [Riak::Key] the object
101
+ def get_linked(bucket, key, options=nil)
102
+ @client[bucket].key(key, options)
103
+ end
104
+
105
+ # Retrieves a Key from the given Bucket. Originally written for link retrieval.
106
+ # Inserts a key in this bucket's namespace, into riak.
107
+ # @option options [Fixnum] :w (write quorum) how many replicas to write to before returning a successful response.
108
+ # @option options [Fixnum :dw how many replicas to commit to durable storage before returning a successful response.
109
+ # @option options [Boolean] :return_body whether to return the contents of the stored object.
110
+ # @return [RpbPutResp] the response confirming Key storage and (optionally) the Key's updated/new data.
111
+ def store(options)
112
+ options[:bucket] = @name
113
+ @client.put_request(options)
114
+ end
115
+
116
+ # Deletes a key from the bucket
117
+ # @param [String] key the key to delete
118
+ # @param [Hash] options quorum options
119
+ # @option options [Fixnum] :rw - the read/write quorum for the delete
120
+ def delete(key, rw=nil)
121
+ key = key.name if key.is_a?(Riak::Key)
122
+
123
+ @client.del_request(@name, key, rw)
124
+ end
125
+
126
+ # Wipes out all keys stored in the bucket, as of execution
127
+ # @param [String] key the key to delete
128
+ # @param [Hash] options quorum options
129
+ # @option options [Fixnum] :rw - the read/write quorum for the delete
130
+ def destroy!(rw=nil)
131
+ keys!
132
+
133
+ @keys.each do |key|
134
+ @client.del_request(@name, key, rw)
135
+ end
136
+ # super.destroy
137
+ end
138
+
139
+ # @return [true, false] whether the bucket allows divergent siblings
140
+ def allow_mult
141
+ @allow_mult
142
+ end
143
+
144
+ # Set the allow_mult property. *NOTE* This will result in a PUT request to Riak.
145
+ # @param [true, false] value whether the bucket should allow siblings
146
+ def allow_mult=(value)
147
+ return(@allow_mult = value) if value.is_a?(TrueClass) or value.is_a?(FalseClass)
148
+
149
+ raise ArgumentError, t("boolean_type")
150
+ end
151
+
152
+ # @return [Fixnum] the N value, or number of replicas for this bucket
153
+ def n_val
154
+ @n_val
155
+ end
156
+
157
+ # Set the N value (number of replicas).
158
+ # Saving this value after the bucket has objects stored in it may have unpredictable results.
159
+ # @param [Fixnum] value the number of replicas the bucket should keep of each object
160
+ def n_val=(value)
161
+ raise ArgumentError, t("fixnum_type", :value => value) unless value.is_a?(Fixnum)
162
+
163
+ @n_val = value
164
+ end
165
+
166
+ # @return [String] a representation suitable for IRB and debugging output
167
+ def inspect
168
+ "#<Riak::Bucket name=#{@name}, props={n_val=>#{@n_val}, allow_mult=#{@allow_mult}}>"
169
+ end
170
+
171
+ # @return [String] a representation suitable for IRB and debugging output, including keys within this bucket
172
+ def inspect!
173
+ "#<Riak::Bucket name=#{@name}, props={n_val=>#{@n_val}, allow_mult=#{@allow_mult}}, keys=#{keys.inspect}>"
174
+ end
175
+
176
+ end
177
+ end
@@ -0,0 +1,127 @@
1
+ # Special thanks to:
2
+ #
3
+ # - Radar in #ruby-lang
4
+ # - xnotdotorg / arilerner[at]gmail.com -
5
+ # http://blog.xnot.org/2008/11/16/communicating-from-ruby-to-erlang/
6
+ #
7
+ require 'socket'
8
+
9
+ module Riak
10
+ class Client
11
+ class Rpc
12
+ include Riak::Util::MessageCode
13
+ include Riak::Util::Translation
14
+ include Riak::Util::Encode
15
+ include Riak::Util::Decode
16
+
17
+ RECV_LIMIT=1638400
18
+
19
+ attr_reader :req_message, :response, :resp_message_codes, :resp_message, :status
20
+
21
+ # Establishes a Client ID with the Riak node, for the life of the RPC connection.
22
+ # @param [Client] the Riak::Client object in which this Rpc instance lives
23
+ def initialize(client)
24
+ @status = false
25
+ @client = client
26
+ @client_id = request(Util::MessageCode::GET_CLIENT_ID_REQUEST).client_id
27
+ @set_client_id = Riak::RpbSetClientIdReq.new(:client_id => @client_id)
28
+
29
+ # Request / Response Data
30
+ @resp_message_codes = -1
31
+ @resp_message = ''
32
+ @req_message_code = -1
33
+ @req_message = ''
34
+ @response = ''
35
+ end
36
+
37
+ # Clears the request / response data, in preparation for a new request
38
+ def clear
39
+ @resp_message_codes = -1
40
+ @resp_message = ''
41
+ @req_message_code = -1
42
+ @req_message = ''
43
+ @response = ''
44
+ @status = false
45
+ end
46
+
47
+ # Opens a TCPSocket connection with the riak host/node
48
+ # @yield [TCPSocket] hands off the socket connection
49
+ # @return [TCPSocket] data that was exchanged with the host/node
50
+ def with_socket(&block)
51
+ socket = TCPSocket.open(@client.host, @client.port)
52
+ set_client_id(socket) if @set_client_id
53
+
54
+ out = yield(socket)
55
+ socket.close
56
+
57
+ return(out)
58
+ end
59
+
60
+ # Sets the Client ID for the TCPSocket session
61
+ # @param [TCPSocket] socket connection for which the Client ID will be set
62
+ # @return [True/False] whether or not the set client id request succeeded
63
+ def set_client_id(socket)
64
+ @set_c_id_req ||= assemble_request( Util::MessageCode::SET_CLIENT_ID_REQUEST,
65
+ @set_client_id.serialize_to_string)
66
+
67
+ socket.send(@set_c_id_req, 0)
68
+ set_c_id_resp = socket.recv(RECV_LIMIT)
69
+
70
+ resp_code, resp_msg = decode_message(set_c_id_resp)
71
+
72
+ return(resp_code == Util::MessageCode::SET_CLIENT_ID_RESPONSE)
73
+ end
74
+
75
+ # Sends the request to the riak node
76
+ # @param [Fixnum] mc The message code that identifies the request
77
+ # @param [Protobuf::Message] pb_msg The protobuf message, if applicable, for the message code
78
+ # @return [True/False] whether or not the set client id request succeeded
79
+ def request(mc, pb_msg=nil)
80
+ clear
81
+
82
+ @req_message_code = mc
83
+ @response = RESPONSE_CLASS_FOR[mc].new unless RESPONSE_CLASS_FOR[mc].nil?
84
+
85
+ with_socket do |socket|
86
+ begin
87
+ @req_message = assemble_request mc, (pb_msg.serialize_to_string rescue '')
88
+
89
+ socket.send(@req_message, 0)
90
+ self.response = socket.recv(RECV_LIMIT)
91
+
92
+ end while(false == (@response.done rescue true))
93
+ end # with_socket
94
+
95
+ return(@response)
96
+ end # stream_request
97
+
98
+ # Handles the response from the Riak node
99
+ # @param [String] value The message returned from the Riak node over the TCP Socket
100
+ # @return [Protobuf::Message] @response the processed response (if any) from the Riak node
101
+ def response=(value)
102
+ @resp_message = value
103
+
104
+ response_chunk, @resp_message_codes = decode_message(value)
105
+
106
+ @resp_message_codes.each do |resp_mc|
107
+ if resp_mc.equal?(ERROR_RESPONSE)
108
+ raise FailedRequest.new(MC_RESPONSE_FOR[@req_message_code], @resp_message_codes, response_chunk)
109
+ end
110
+
111
+ # The below should never really happen
112
+ if resp_mc != MC_RESPONSE_FOR[@req_message_code]
113
+ raise FailedExchange.new(MC_RESPONSE_FOR[@req_message_code], @resp_message_codes, response_chunk, "failed_request")
114
+ end
115
+ end
116
+
117
+ if response_chunk.size > 0
118
+ @response.parse_from_string response_chunk
119
+ end
120
+
121
+ @status = true
122
+ return(@response)
123
+ end
124
+
125
+ end # class Client
126
+ end # module Rpc
127
+ end # module RiakPbclient