cql-rb 1.0.6 → 1.1.0.pre0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +4 -9
- data/lib/cql.rb +1 -0
- data/lib/cql/byte_buffer.rb +23 -7
- data/lib/cql/client.rb +11 -6
- data/lib/cql/client/asynchronous_client.rb +37 -83
- data/lib/cql/client/asynchronous_prepared_statement.rb +10 -4
- data/lib/cql/client/column_metadata.rb +16 -0
- data/lib/cql/client/request_runner.rb +46 -0
- data/lib/cql/future.rb +4 -5
- data/lib/cql/io.rb +2 -5
- data/lib/cql/io/connection.rb +220 -0
- data/lib/cql/io/io_reactor.rb +213 -185
- data/lib/cql/protocol.rb +1 -0
- data/lib/cql/protocol/cql_protocol_handler.rb +201 -0
- data/lib/cql/protocol/decoding.rb +6 -31
- data/lib/cql/protocol/encoding.rb +1 -5
- data/lib/cql/protocol/request.rb +4 -0
- data/lib/cql/protocol/responses/schema_change_result_response.rb +15 -0
- data/lib/cql/protocol/type_converter.rb +56 -76
- data/lib/cql/time_uuid.rb +104 -0
- data/lib/cql/uuid.rb +4 -2
- data/lib/cql/version.rb +1 -1
- data/spec/cql/client/asynchronous_client_spec.rb +47 -71
- data/spec/cql/client/asynchronous_prepared_statement_spec.rb +68 -0
- data/spec/cql/client/client_shared.rb +3 -3
- data/spec/cql/client/column_metadata_spec.rb +80 -0
- data/spec/cql/client/request_runner_spec.rb +120 -0
- data/spec/cql/future_spec.rb +26 -11
- data/spec/cql/io/connection_spec.rb +460 -0
- data/spec/cql/io/io_reactor_spec.rb +212 -265
- data/spec/cql/protocol/cql_protocol_handler_spec.rb +216 -0
- data/spec/cql/protocol/decoding_spec.rb +9 -28
- data/spec/cql/protocol/encoding_spec.rb +0 -5
- data/spec/cql/protocol/request_spec.rb +16 -0
- data/spec/cql/protocol/response_frame_spec.rb +2 -2
- data/spec/cql/protocol/responses/schema_change_result_response_spec.rb +70 -0
- data/spec/cql/time_uuid_spec.rb +136 -0
- data/spec/cql/uuid_spec.rb +1 -5
- data/spec/integration/client_spec.rb +34 -38
- data/spec/integration/io_spec.rb +283 -0
- data/spec/integration/protocol_spec.rb +53 -113
- data/spec/integration/regression_spec.rb +124 -0
- data/spec/integration/uuid_spec.rb +76 -0
- data/spec/spec_helper.rb +12 -9
- data/spec/support/fake_io_reactor.rb +52 -21
- data/spec/support/fake_server.rb +2 -2
- metadata +33 -10
- checksums.yaml +0 -15
- data/lib/cql/io/node_connection.rb +0 -209
- data/spec/cql/protocol/type_converter_spec.rb +0 -52
checksums.yaml
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
---
|
2
|
-
!binary "U0hBMQ==":
|
3
|
-
metadata.gz: !binary |-
|
4
|
-
ZDk1YTJjZWRjODBkYTMyNjIyYjBhYjZkN2NjYzA5MWE1YzJkNTVjMw==
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
ZjI5MjQ2Mzc1MDE3MzRjYzg4MzVjMmY5YTMyM2U4ODY0ODY4ZTg0OQ==
|
7
|
-
SHA512:
|
8
|
-
metadata.gz: !binary |-
|
9
|
-
Y2IxNTg3NGYxOWM1MzY3ZmViYTY4MjcxNDhkNDAzZjkxMmY5MTBjYjc4YzJi
|
10
|
-
MDMwMjI1Y2NmZjI2OTAyNTM3ZWQ5ODk2M2YwMjNjODU5ODlkNjI5ZDUxNDk2
|
11
|
-
Y2NhNWZlMjk3ZWUzNTU4YzM2Y2UyZWI5M2YyODQyMjVmODczODU=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
YjJhNDIwN2M1NTg4ZjMxMWNiYjA1NGFlMjZiMDc1ODgxZDhmMDAyZTUzZDEx
|
14
|
-
ZDE2OGNlZTAzN2IwNTVmNWYzNjcxYzNhNTdlNzk0Mzg3Zjk4ZDhjZjE1ZmY5
|
15
|
-
MjQ4NzE3NzUyNDQ5NTc5NDE5ODQ4MmE2MGZkMjIyMjlhMjk4NWQ=
|
@@ -1,209 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require 'socket'
|
4
|
-
|
5
|
-
|
6
|
-
module Cql
|
7
|
-
module Io
|
8
|
-
# @private
|
9
|
-
class NodeConnection
|
10
|
-
def initialize(*args)
|
11
|
-
@host, @port, @connection_timeout = args
|
12
|
-
@connected_future = Future.new
|
13
|
-
@io = nil
|
14
|
-
@addrinfo = nil
|
15
|
-
@write_buffer = ByteBuffer.new
|
16
|
-
@read_buffer = ByteBuffer.new
|
17
|
-
@current_frame = Protocol::ResponseFrame.new(@read_buffer)
|
18
|
-
@response_tasks = [nil] * 128
|
19
|
-
@event_listeners = Hash.new { |h, k| h[k] = [] }
|
20
|
-
end
|
21
|
-
|
22
|
-
def open
|
23
|
-
@connection_started_at = Time.now
|
24
|
-
begin
|
25
|
-
addrinfo = Socket.getaddrinfo(@host, @port, Socket::AF_INET, Socket::SOCK_STREAM)
|
26
|
-
_, port, _, ip, address_family, socket_type = addrinfo.first
|
27
|
-
@sockaddr = Socket.sockaddr_in(port, ip)
|
28
|
-
@io = Socket.new(address_family, socket_type, 0)
|
29
|
-
@io.connect_nonblock(@sockaddr)
|
30
|
-
rescue Errno::EINPROGRESS
|
31
|
-
# NOTE not connected yet, this is expected
|
32
|
-
rescue SystemCallError, SocketError => e
|
33
|
-
fail_connection!(e)
|
34
|
-
end
|
35
|
-
@connected_future
|
36
|
-
end
|
37
|
-
|
38
|
-
def connection_id
|
39
|
-
self.object_id
|
40
|
-
end
|
41
|
-
|
42
|
-
def to_io
|
43
|
-
@io
|
44
|
-
end
|
45
|
-
|
46
|
-
def on_event(&listener)
|
47
|
-
@event_listeners[:event] << listener
|
48
|
-
end
|
49
|
-
|
50
|
-
def on_close(&listener)
|
51
|
-
@event_listeners[:close] << listener
|
52
|
-
end
|
53
|
-
|
54
|
-
def connected?
|
55
|
-
@io && !connecting?
|
56
|
-
end
|
57
|
-
|
58
|
-
def connecting?
|
59
|
-
@io && !(@connected_future.complete? || @connected_future.failed?)
|
60
|
-
end
|
61
|
-
|
62
|
-
def closed?
|
63
|
-
@io.nil? && !connecting?
|
64
|
-
end
|
65
|
-
|
66
|
-
def has_capacity?
|
67
|
-
!!next_stream_id && connected?
|
68
|
-
end
|
69
|
-
|
70
|
-
def can_write?
|
71
|
-
@io && (!@write_buffer.empty? || connecting?)
|
72
|
-
end
|
73
|
-
|
74
|
-
def handle_read
|
75
|
-
new_bytes = @io.read_nonblock(2**16)
|
76
|
-
@current_frame << new_bytes
|
77
|
-
while @current_frame.complete?
|
78
|
-
stream_id = @current_frame.stream_id
|
79
|
-
if stream_id == EVENT_STREAM_ID
|
80
|
-
@event_listeners[:event].each { |listener| listener.call(@current_frame.body) }
|
81
|
-
elsif @response_tasks[stream_id]
|
82
|
-
@response_tasks[stream_id].complete!([@current_frame.body, connection_id])
|
83
|
-
@response_tasks[stream_id] = nil
|
84
|
-
else
|
85
|
-
# TODO dropping the request on the floor here, but we didn't send it
|
86
|
-
end
|
87
|
-
@current_frame = Protocol::ResponseFrame.new(@read_buffer)
|
88
|
-
end
|
89
|
-
rescue => e
|
90
|
-
force_close(e)
|
91
|
-
end
|
92
|
-
|
93
|
-
def perform_request(request, future)
|
94
|
-
stream_id = next_stream_id
|
95
|
-
request.encode_frame(stream_id, @write_buffer)
|
96
|
-
@response_tasks[stream_id] = future
|
97
|
-
rescue => e
|
98
|
-
case e
|
99
|
-
when CqlError
|
100
|
-
error = e
|
101
|
-
else
|
102
|
-
error = IoError.new(e.message)
|
103
|
-
error.set_backtrace(e.backtrace)
|
104
|
-
end
|
105
|
-
@response_tasks.delete(stream_id)
|
106
|
-
future.fail!(error)
|
107
|
-
end
|
108
|
-
|
109
|
-
def handle_write
|
110
|
-
if connecting?
|
111
|
-
handle_connecting
|
112
|
-
else
|
113
|
-
if !@write_buffer.empty?
|
114
|
-
bytes_written = @io.write_nonblock(@write_buffer.cheap_peek)
|
115
|
-
@write_buffer.discard(bytes_written)
|
116
|
-
end
|
117
|
-
end
|
118
|
-
rescue => e
|
119
|
-
force_close(e)
|
120
|
-
end
|
121
|
-
|
122
|
-
def handle_connecting
|
123
|
-
if connecting_timed_out?
|
124
|
-
fail_connection!(ConnectionTimeoutError.new("Could not connect to #{@host}:#{@port} within #{@connection_timeout}s"))
|
125
|
-
else
|
126
|
-
@io.connect_nonblock(@sockaddr)
|
127
|
-
succeed_connection!
|
128
|
-
end
|
129
|
-
rescue Errno::EALREADY, Errno::EINPROGRESS
|
130
|
-
# NOTE still not connected
|
131
|
-
rescue Errno::EISCONN
|
132
|
-
succeed_connection!
|
133
|
-
rescue SystemCallError, SocketError => e
|
134
|
-
fail_connection!(e)
|
135
|
-
end
|
136
|
-
|
137
|
-
def close
|
138
|
-
if @io
|
139
|
-
begin
|
140
|
-
@io.close
|
141
|
-
rescue SystemCallError
|
142
|
-
# NOTE nothing to do, it wasn't open
|
143
|
-
end
|
144
|
-
if connecting?
|
145
|
-
succeed_connection!
|
146
|
-
end
|
147
|
-
@io = nil
|
148
|
-
@event_listeners[:close].each { |listener| listener.call(self) }
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
def to_s
|
153
|
-
state = begin
|
154
|
-
if connected? then 'connected'
|
155
|
-
elsif connecting? then 'connecting'
|
156
|
-
else 'not connected'
|
157
|
-
end
|
158
|
-
end
|
159
|
-
%<NodeConnection(#{@host}:#{@port}, #{state})>
|
160
|
-
end
|
161
|
-
|
162
|
-
private
|
163
|
-
|
164
|
-
EVENT_STREAM_ID = -1
|
165
|
-
|
166
|
-
def connecting_timed_out?
|
167
|
-
(Time.now - @connection_started_at) > @connection_timeout
|
168
|
-
end
|
169
|
-
|
170
|
-
def succeed_connection!
|
171
|
-
@connected_future.complete!(connection_id)
|
172
|
-
end
|
173
|
-
|
174
|
-
def fail_connection!(e)
|
175
|
-
case e
|
176
|
-
when ConnectionError
|
177
|
-
error = e
|
178
|
-
else
|
179
|
-
message = "Could not connect to #{@host}:#{@port}: #{e.message} (#{e.class.name})"
|
180
|
-
error = ConnectionError.new(message)
|
181
|
-
error.set_backtrace(e.backtrace)
|
182
|
-
end
|
183
|
-
@connected_future.fail!(error)
|
184
|
-
force_close(error)
|
185
|
-
end
|
186
|
-
|
187
|
-
def force_close(e)
|
188
|
-
case e
|
189
|
-
when CqlError
|
190
|
-
error = e
|
191
|
-
else
|
192
|
-
error = IoError.new(e.message)
|
193
|
-
error.set_backtrace(e.backtrace)
|
194
|
-
end
|
195
|
-
@response_tasks.each do |listener|
|
196
|
-
listener.fail!(error) if listener
|
197
|
-
end
|
198
|
-
close
|
199
|
-
end
|
200
|
-
|
201
|
-
def next_stream_id
|
202
|
-
@response_tasks.each_with_index do |task, index|
|
203
|
-
return index if task.nil?
|
204
|
-
end
|
205
|
-
nil
|
206
|
-
end
|
207
|
-
end
|
208
|
-
end
|
209
|
-
end
|
@@ -1,52 +0,0 @@
|
|
1
|
-
# encoding: ascii-8bit
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
|
6
|
-
module Cql
|
7
|
-
module Protocol
|
8
|
-
describe TypeConverter do
|
9
|
-
let :converter do
|
10
|
-
described_class.new
|
11
|
-
end
|
12
|
-
|
13
|
-
let :buffer do
|
14
|
-
''
|
15
|
-
end
|
16
|
-
|
17
|
-
TYPES = [:ascii, :bigint, :blob, :boolean, :counter, :decimal, :double, :float, :inet, :int, :text, :varchar, :timestamp, :timeuuid, :uuid, :varint].freeze
|
18
|
-
|
19
|
-
describe '#to_bytes' do
|
20
|
-
context 'when encoding normal value' do
|
21
|
-
TYPES.each do |type|
|
22
|
-
it "encodes a null #{type.upcase}" do
|
23
|
-
converter.to_bytes(buffer, type, nil, 4).should == "\xff\xff\xff\xff"
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
it 'encodes a null LIST' do
|
28
|
-
converter.to_bytes(buffer, [:list, :int], nil, 4).should == "\xff\xff\xff\xff"
|
29
|
-
end
|
30
|
-
|
31
|
-
it 'encodes a null MAP' do
|
32
|
-
converter.to_bytes(buffer, [:map, :text, :text], nil, 4).should == "\xff\xff\xff\xff"
|
33
|
-
|
34
|
-
end
|
35
|
-
|
36
|
-
it 'encodes a null SET' do
|
37
|
-
converter.to_bytes(buffer, [:set, :uuid], nil, 4).should == "\xff\xff\xff\xff"
|
38
|
-
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
context 'when encoding collection values' do
|
43
|
-
TYPES.each do |type|
|
44
|
-
it "encodes a null #{type.upcase}" do
|
45
|
-
converter.to_bytes(buffer, type, nil, 2).should == "\xff\xff"
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|