cql-rb 1.1.0.pre3 → 1.1.0.pre6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +2 -2
- data/lib/cql/client.rb +9 -5
- data/lib/cql/client/asynchronous_client.rb +105 -192
- data/lib/cql/client/asynchronous_prepared_statement.rb +51 -9
- data/lib/cql/client/connection_helper.rb +155 -0
- data/lib/cql/client/connection_manager.rb +56 -0
- data/lib/cql/client/keyspace_changer.rb +27 -0
- data/lib/cql/client/null_logger.rb +21 -0
- data/lib/cql/client/request_runner.rb +5 -3
- data/lib/cql/client/synchronous_client.rb +5 -5
- data/lib/cql/client/synchronous_prepared_statement.rb +4 -8
- data/lib/cql/future.rb +320 -210
- data/lib/cql/io/connection.rb +5 -5
- data/lib/cql/io/io_reactor.rb +21 -23
- data/lib/cql/protocol/cql_protocol_handler.rb +69 -38
- data/lib/cql/protocol/encoding.rb +5 -1
- data/lib/cql/protocol/requests/register_request.rb +2 -0
- data/lib/cql/protocol/type_converter.rb +1 -0
- data/lib/cql/version.rb +1 -1
- data/spec/cql/client/asynchronous_client_spec.rb +368 -175
- data/spec/cql/client/asynchronous_prepared_statement_spec.rb +132 -22
- data/spec/cql/client/connection_helper_spec.rb +335 -0
- data/spec/cql/client/connection_manager_spec.rb +118 -0
- data/spec/cql/client/keyspace_changer_spec.rb +50 -0
- data/spec/cql/client/request_runner_spec.rb +12 -12
- data/spec/cql/client/synchronous_client_spec.rb +15 -15
- data/spec/cql/client/synchronous_prepared_statement_spec.rb +15 -11
- data/spec/cql/future_spec.rb +529 -301
- data/spec/cql/io/connection_spec.rb +12 -12
- data/spec/cql/io/io_reactor_spec.rb +61 -61
- data/spec/cql/protocol/cql_protocol_handler_spec.rb +26 -12
- data/spec/cql/protocol/encoding_spec.rb +5 -0
- data/spec/cql/protocol/type_converter_spec.rb +1 -1
- data/spec/cql/time_uuid_spec.rb +7 -7
- data/spec/integration/client_spec.rb +2 -2
- data/spec/integration/io_spec.rb +20 -20
- data/spec/integration/protocol_spec.rb +17 -17
- data/spec/integration/regression_spec.rb +6 -0
- data/spec/integration/uuid_spec.rb +4 -0
- data/spec/support/fake_io_reactor.rb +38 -8
- data/spec/support/fake_server.rb +3 -3
- metadata +12 -2
@@ -11,19 +11,19 @@ module Cql
|
|
11
11
|
end
|
12
12
|
|
13
13
|
let :unblocker do
|
14
|
-
|
14
|
+
double(:unblocker, unblock!: nil)
|
15
15
|
end
|
16
16
|
|
17
17
|
let :socket_impl do
|
18
|
-
|
18
|
+
double(:socket_impl)
|
19
19
|
end
|
20
20
|
|
21
21
|
let :clock do
|
22
|
-
|
22
|
+
double(:clock, now: 0)
|
23
23
|
end
|
24
24
|
|
25
25
|
let :socket do
|
26
|
-
|
26
|
+
double(:socket)
|
27
27
|
end
|
28
28
|
|
29
29
|
before do
|
@@ -76,10 +76,10 @@ module Cql
|
|
76
76
|
end
|
77
77
|
|
78
78
|
shared_examples 'on successfull connection' do
|
79
|
-
it '
|
79
|
+
it 'fulfilles the returned future and returns itself' do
|
80
80
|
f = handler.connect
|
81
|
-
f.should
|
82
|
-
f.
|
81
|
+
f.should be_resolved
|
82
|
+
f.value.should equal(handler)
|
83
83
|
end
|
84
84
|
|
85
85
|
it 'is connected' do
|
@@ -108,7 +108,7 @@ module Cql
|
|
108
108
|
it 'it does nothing' do
|
109
109
|
socket.stub(:connect_nonblock).and_raise(Errno::EALREADY)
|
110
110
|
f = handler.connect
|
111
|
-
f.should_not
|
111
|
+
f.should_not be_resolved
|
112
112
|
f.should_not be_failed
|
113
113
|
end
|
114
114
|
end
|
@@ -133,7 +133,7 @@ module Cql
|
|
133
133
|
it 'fails if there are no more addresses to try' do
|
134
134
|
socket.stub(:connect_nonblock).and_raise(Errno::EINVAL)
|
135
135
|
f = handler.connect
|
136
|
-
expect { f.
|
136
|
+
expect { f.value }.to raise_error(ConnectionError)
|
137
137
|
end
|
138
138
|
end
|
139
139
|
|
@@ -145,7 +145,7 @@ module Cql
|
|
145
145
|
|
146
146
|
it 'fails the future with a ConnectionError' do
|
147
147
|
f = handler.connect
|
148
|
-
expect { f.
|
148
|
+
expect { f.value }.to raise_error(ConnectionError)
|
149
149
|
end
|
150
150
|
|
151
151
|
it 'closes the socket' do
|
@@ -180,7 +180,7 @@ module Cql
|
|
180
180
|
|
181
181
|
it 'fails the returned future with a ConnectionError' do
|
182
182
|
f = handler.connect
|
183
|
-
expect { f.
|
183
|
+
expect { f.value }.to raise_error(ConnectionError)
|
184
184
|
end
|
185
185
|
|
186
186
|
it 'calls the close listener' do
|
@@ -217,7 +217,7 @@ module Cql
|
|
217
217
|
clock.stub(:now).and_return(7)
|
218
218
|
handler.connect
|
219
219
|
f.should be_failed
|
220
|
-
expect { f.
|
220
|
+
expect { f.value }.to raise_error(ConnectionTimeoutError)
|
221
221
|
end
|
222
222
|
|
223
223
|
it 'closes the connection' do
|
@@ -11,7 +11,7 @@ module Cql
|
|
11
11
|
end
|
12
12
|
|
13
13
|
let :protocol_handler_factory do
|
14
|
-
|
14
|
+
double(:protocol_handler_factory)
|
15
15
|
end
|
16
16
|
|
17
17
|
let! :selector do
|
@@ -19,61 +19,61 @@ module Cql
|
|
19
19
|
end
|
20
20
|
|
21
21
|
let :clock do
|
22
|
-
|
22
|
+
double(:clock, now: 0)
|
23
23
|
end
|
24
24
|
|
25
25
|
describe '#start' do
|
26
26
|
after do
|
27
|
-
reactor.stop.
|
27
|
+
reactor.stop.value if reactor.running?
|
28
28
|
end
|
29
29
|
|
30
|
-
it 'returns a future that
|
31
|
-
reactor.start.
|
30
|
+
it 'returns a future that is resolved when the reactor has started' do
|
31
|
+
reactor.start.value
|
32
32
|
end
|
33
33
|
|
34
34
|
it 'returns a future that resolves to the reactor' do
|
35
|
-
reactor.start.
|
35
|
+
reactor.start.value.should equal(reactor)
|
36
36
|
end
|
37
37
|
|
38
38
|
it 'is running after being started' do
|
39
|
-
reactor.start.
|
39
|
+
reactor.start.value
|
40
40
|
reactor.should be_running
|
41
41
|
end
|
42
42
|
|
43
43
|
it 'cannot be started again once stopped' do
|
44
|
-
reactor.start.
|
45
|
-
reactor.stop.
|
44
|
+
reactor.start.value
|
45
|
+
reactor.stop.value
|
46
46
|
expect { reactor.start }.to raise_error(ReactorError)
|
47
47
|
end
|
48
48
|
|
49
49
|
it 'calls the selector' do
|
50
50
|
called = false
|
51
51
|
selector.handler { called = true; [[], [], []] }
|
52
|
-
reactor.start.
|
52
|
+
reactor.start.value
|
53
53
|
await { called }
|
54
|
-
reactor.stop.
|
54
|
+
reactor.stop.value
|
55
55
|
called.should be_true, 'expected the selector to have been called'
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
59
|
describe '#stop' do
|
60
60
|
after do
|
61
|
-
reactor.stop.
|
61
|
+
reactor.stop.value if reactor.running?
|
62
62
|
end
|
63
63
|
|
64
|
-
it 'returns a future
|
65
|
-
reactor.start.
|
66
|
-
reactor.stop.
|
64
|
+
it 'returns a future that is resolved when the reactor has stopped' do
|
65
|
+
reactor.start.value
|
66
|
+
reactor.stop.value
|
67
67
|
end
|
68
68
|
|
69
69
|
it 'returns a future which resolves to the reactor' do
|
70
|
-
reactor.start.
|
71
|
-
reactor.stop.
|
70
|
+
reactor.start.value
|
71
|
+
reactor.stop.value.should equal(reactor)
|
72
72
|
end
|
73
73
|
|
74
74
|
it 'is not running after being stopped' do
|
75
|
-
reactor.start.
|
76
|
-
reactor.stop.
|
75
|
+
reactor.start.value
|
76
|
+
reactor.stop.value
|
77
77
|
reactor.should_not be_running
|
78
78
|
end
|
79
79
|
|
@@ -81,24 +81,24 @@ module Cql
|
|
81
81
|
connection = nil
|
82
82
|
protocol_handler_factory.stub(:new) do |sh|
|
83
83
|
connection = sh
|
84
|
-
|
84
|
+
double(:protocol_handler)
|
85
85
|
end
|
86
|
-
reactor.start.
|
86
|
+
reactor.start.value
|
87
87
|
reactor.connect('example.com', 9999, 5)
|
88
|
-
reactor.stop.
|
88
|
+
reactor.stop.value
|
89
89
|
connection.should be_closed
|
90
90
|
end
|
91
91
|
|
92
92
|
it 'cancels all active timers' do
|
93
|
-
reactor.start.
|
93
|
+
reactor.start.value
|
94
94
|
clock.stub(:now).and_return(1)
|
95
95
|
expired_timer = reactor.schedule_timer(1)
|
96
96
|
active_timer1 = reactor.schedule_timer(999)
|
97
97
|
active_timer2 = reactor.schedule_timer(111)
|
98
|
-
expired_timer.should_not_receive(:fail
|
98
|
+
expired_timer.should_not_receive(:fail)
|
99
99
|
clock.stub(:now).and_return(2)
|
100
|
-
await { expired_timer.
|
101
|
-
reactor.stop.
|
100
|
+
await { expired_timer.completed? }
|
101
|
+
reactor.stop.value
|
102
102
|
active_timer1.should be_failed
|
103
103
|
active_timer2.should be_failed
|
104
104
|
end
|
@@ -119,7 +119,7 @@ module Cql
|
|
119
119
|
|
120
120
|
it 'calls the listener immediately when the reactor has already crashed' do
|
121
121
|
error = nil
|
122
|
-
reactor.start.
|
122
|
+
reactor.start.value
|
123
123
|
await { !reactor.running? }
|
124
124
|
reactor.on_error { |e| error = e }
|
125
125
|
await { error }
|
@@ -137,7 +137,7 @@ module Cql
|
|
137
137
|
|
138
138
|
describe '#connect' do
|
139
139
|
let :protocol_handler do
|
140
|
-
|
140
|
+
double(:protocol_handler)
|
141
141
|
end
|
142
142
|
|
143
143
|
before do
|
@@ -166,14 +166,14 @@ module Cql
|
|
166
166
|
end
|
167
167
|
|
168
168
|
it 'returns a future that resolves to a new protocol handler' do
|
169
|
-
reactor.start.
|
169
|
+
reactor.start.value
|
170
170
|
f = reactor.connect('example.com', 9999, 5)
|
171
|
-
f.
|
171
|
+
f.value.should equal(protocol_handler)
|
172
172
|
end
|
173
173
|
|
174
174
|
it 'returns a new protocol handler which wraps a socket handler' do
|
175
|
-
reactor.start.
|
176
|
-
protocol_handler = reactor.connect('example.com', 9999, 5).
|
175
|
+
reactor.start.value
|
176
|
+
protocol_handler = reactor.connect('example.com', 9999, 5).value
|
177
177
|
protocol_handler.connection.should_not be_nil
|
178
178
|
protocol_handler.connection.host.should == 'example.com'
|
179
179
|
protocol_handler.connection.port.should == 9999
|
@@ -183,18 +183,18 @@ module Cql
|
|
183
183
|
|
184
184
|
describe '#schedule_timer' do
|
185
185
|
before do
|
186
|
-
reactor.start.
|
186
|
+
reactor.start.value
|
187
187
|
end
|
188
188
|
|
189
189
|
after do
|
190
|
-
reactor.stop.
|
190
|
+
reactor.stop.value
|
191
191
|
end
|
192
192
|
|
193
|
-
it 'returns a future that
|
193
|
+
it 'returns a future that is resolved after the specified duration' do
|
194
194
|
clock.stub(:now).and_return(1)
|
195
195
|
f = reactor.schedule_timer(0.1)
|
196
196
|
clock.stub(:now).and_return(1.1)
|
197
|
-
await { f.
|
197
|
+
await { f.resolved? }
|
198
198
|
end
|
199
199
|
end
|
200
200
|
|
@@ -218,15 +218,15 @@ module Cql
|
|
218
218
|
end
|
219
219
|
|
220
220
|
let :selector do
|
221
|
-
|
221
|
+
double(:selector)
|
222
222
|
end
|
223
223
|
|
224
224
|
let :clock do
|
225
|
-
|
225
|
+
double(:clock, now: 0)
|
226
226
|
end
|
227
227
|
|
228
228
|
let :socket do
|
229
|
-
|
229
|
+
double(:socket, connected?: false, connecting?: false, writable?: false, closed?: false)
|
230
230
|
end
|
231
231
|
|
232
232
|
describe '#tick' do
|
@@ -295,32 +295,32 @@ module Cql
|
|
295
295
|
it 'completes timers that have expired' do
|
296
296
|
selector.stub(:select).and_return([nil, nil, nil])
|
297
297
|
clock.stub(:now).and_return(1)
|
298
|
-
|
299
|
-
loop_body.schedule_timer(1,
|
298
|
+
promise = Promise.new
|
299
|
+
loop_body.schedule_timer(1, promise)
|
300
300
|
loop_body.tick
|
301
|
-
future.should_not
|
301
|
+
promise.future.should_not be_completed
|
302
302
|
clock.stub(:now).and_return(2)
|
303
303
|
loop_body.tick
|
304
|
-
future.should
|
304
|
+
promise.future.should be_completed
|
305
305
|
end
|
306
306
|
|
307
307
|
it 'clears out timers that have expired' do
|
308
308
|
selector.stub(:select).and_return([nil, nil, nil])
|
309
309
|
clock.stub(:now).and_return(1)
|
310
|
-
|
311
|
-
loop_body.schedule_timer(1,
|
310
|
+
promise = Promise.new
|
311
|
+
loop_body.schedule_timer(1, promise)
|
312
312
|
clock.stub(:now).and_return(2)
|
313
313
|
loop_body.tick
|
314
|
-
future.should
|
315
|
-
|
314
|
+
promise.future.should be_completed
|
315
|
+
promise.should_not_receive(:fulfill)
|
316
316
|
loop_body.tick
|
317
317
|
end
|
318
318
|
end
|
319
319
|
|
320
320
|
describe '#close_sockets' do
|
321
321
|
it 'closes all sockets' do
|
322
|
-
socket1 =
|
323
|
-
socket2 =
|
322
|
+
socket1 = double(:socket1, closed?: false)
|
323
|
+
socket2 = double(:socket2, closed?: false)
|
324
324
|
socket1.should_receive(:close)
|
325
325
|
socket2.should_receive(:close)
|
326
326
|
loop_body.add_socket(socket1)
|
@@ -329,8 +329,8 @@ module Cql
|
|
329
329
|
end
|
330
330
|
|
331
331
|
it 'closes all sockets, even when one of them raises an error' do
|
332
|
-
socket1 =
|
333
|
-
socket2 =
|
332
|
+
socket1 = double(:socket1, closed?: false)
|
333
|
+
socket2 = double(:socket2, closed?: false)
|
334
334
|
socket1.stub(:close).and_raise('Blurgh')
|
335
335
|
socket2.should_receive(:close)
|
336
336
|
loop_body.add_socket(socket1)
|
@@ -352,20 +352,20 @@ module Cql
|
|
352
352
|
end
|
353
353
|
|
354
354
|
it 'fails all active timers with a CancelledError' do
|
355
|
-
|
356
|
-
|
357
|
-
|
355
|
+
p1 = Promise.new
|
356
|
+
p2 = Promise.new
|
357
|
+
p3 = Promise.new
|
358
358
|
clock.stub(:now).and_return(1)
|
359
|
-
loop_body.schedule_timer(1,
|
360
|
-
loop_body.schedule_timer(3,
|
361
|
-
loop_body.schedule_timer(3,
|
359
|
+
loop_body.schedule_timer(1, p1)
|
360
|
+
loop_body.schedule_timer(3, p2)
|
361
|
+
loop_body.schedule_timer(3, p3)
|
362
362
|
clock.stub(:now).and_return(2)
|
363
363
|
loop_body.tick
|
364
364
|
loop_body.cancel_timers
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
expect {
|
365
|
+
p1.future.should be_completed
|
366
|
+
p2.future.should be_failed
|
367
|
+
p3.future.should be_failed
|
368
|
+
expect { p3.future.value }.to raise_error(CancelledError)
|
369
369
|
end
|
370
370
|
end
|
371
371
|
end
|
@@ -11,7 +11,7 @@ module Cql
|
|
11
11
|
end
|
12
12
|
|
13
13
|
let :connection do
|
14
|
-
|
14
|
+
double(:connection)
|
15
15
|
end
|
16
16
|
|
17
17
|
let :request do
|
@@ -48,6 +48,20 @@ module Cql
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
+
describe '#host' do
|
52
|
+
it 'delegates to the connection' do
|
53
|
+
connection.stub(:host).and_return('example.com')
|
54
|
+
protocol_handler.host.should == 'example.com'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe '#port' do
|
59
|
+
it 'delegates to the connection' do
|
60
|
+
connection.stub(:port).and_return(9042)
|
61
|
+
protocol_handler.port.should == 9042
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
51
65
|
describe '#send_request' do
|
52
66
|
before do
|
53
67
|
connection.stub(:write).and_yield(buffer)
|
@@ -71,27 +85,27 @@ module Cql
|
|
71
85
|
protocol_handler.send_request(request).should be_a(Future)
|
72
86
|
end
|
73
87
|
|
74
|
-
it '
|
88
|
+
it 'succeeds the future when it receives a response frame with the corresponding stream ID' do
|
75
89
|
3.times { protocol_handler.send_request(request) }
|
76
90
|
future = protocol_handler.send_request(request)
|
77
91
|
connection.data_listener.call([0x81, 0, 3, 2, 0].pack('C4N'))
|
78
|
-
await(0.1) { future.
|
92
|
+
await(0.1) { future.resolved? }
|
79
93
|
end
|
80
94
|
|
81
95
|
it 'handles multiple response frames in the same data packet' do
|
82
96
|
futures = Array.new(4) { protocol_handler.send_request(request) }
|
83
97
|
connection.data_listener.call([0x81, 0, 2, 2, 0].pack('C4N') + [0x81, 0, 3, 2, 0].pack('C4N'))
|
84
|
-
await(0.1) { futures[2].
|
98
|
+
await(0.1) { futures[2].resolved? && futures[3].resolved? }
|
85
99
|
end
|
86
100
|
|
87
101
|
it 'queues the request when there are too many in flight, sending it as soon as a stream is available' do
|
88
102
|
connection.stub(:write)
|
89
103
|
futures = Array.new(130) { protocol_handler.send_request(request) }
|
90
104
|
128.times { |i| connection.data_listener.call([0x81, 0, i, 2, 0].pack('C4N')) }
|
91
|
-
futures[127].should
|
92
|
-
futures[128].should_not
|
105
|
+
futures[127].should be_resolved
|
106
|
+
futures[128].should_not be_resolved
|
93
107
|
2.times { |i| connection.data_listener.call([0x81, 0, i, 2, 0].pack('C4N')) }
|
94
|
-
futures[128].should
|
108
|
+
futures[128].should be_resolved
|
95
109
|
end
|
96
110
|
|
97
111
|
context 'when the protocol handler closes' do
|
@@ -113,7 +127,7 @@ module Cql
|
|
113
127
|
connection.data_listener.call([0x81, 0, 0, 2, 0].pack('C4N'))
|
114
128
|
connection.closed_listener.call(nil)
|
115
129
|
begin
|
116
|
-
future.
|
130
|
+
future.value
|
117
131
|
rescue => e
|
118
132
|
e.should be_a(Cql::Io::ConnectionClosedError)
|
119
133
|
else
|
@@ -134,7 +148,7 @@ module Cql
|
|
134
148
|
it 'fails all requests with NotConnectedError' do
|
135
149
|
connection.stub(:closed?).and_return(true)
|
136
150
|
f = protocol_handler.send_request(request)
|
137
|
-
expect { f.
|
151
|
+
expect { f.value }.to raise_error(NotConnectedError)
|
138
152
|
end
|
139
153
|
end
|
140
154
|
end
|
@@ -145,11 +159,11 @@ module Cql
|
|
145
159
|
protocol_handler.close
|
146
160
|
end
|
147
161
|
|
148
|
-
it 'returns a future which
|
162
|
+
it 'returns a future which succeeds when the socket has closed' do
|
149
163
|
connection.stub(:close) do
|
150
164
|
connection.closed_listener.call(nil)
|
151
165
|
end
|
152
|
-
protocol_handler.close.
|
166
|
+
protocol_handler.close.value
|
153
167
|
end
|
154
168
|
end
|
155
169
|
|
@@ -167,7 +181,7 @@ module Cql
|
|
167
181
|
it 'registers the keyspace it has changed to' do
|
168
182
|
f = protocol_handler.send_request(Protocol::QueryRequest.new('USE hello', :one))
|
169
183
|
connection.data_listener.call([0x81, 0, 0, 8, 4 + 2 + 5, 3, 5].pack('C4N2n') + 'hello')
|
170
|
-
f.
|
184
|
+
f.value
|
171
185
|
protocol_handler.keyspace.should == 'hello'
|
172
186
|
end
|
173
187
|
end
|