cassandra-driver 1.1.1-java → 1.2.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +8 -8
- data/lib/cassandra/cluster/client.rb +97 -74
- data/lib/cassandra/cluster/connector.rb +26 -15
- data/lib/cassandra/protocol/cql_protocol_handler.rb +1 -1
- data/lib/cassandra/protocol/type_converter.rb +7 -3
- data/lib/cassandra/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c4d3013280c22a0d22b0bf77340c1c27c3fc0bbc
|
4
|
+
data.tar.gz: 19450149da8ffdd4eeeb53962ddc3640dc25a1d5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ca9a5a0b9801ba7bfa4ac53cbcd697c45a5dfdc4febb1da959ae4a7b476d2883c0206233d53fa0dc3ab2e0e17c0417776c3302199a4f46dd55887a15ba470476
|
7
|
+
data.tar.gz: 55149c4d71b6b7c2cb544d4267b30438d6d261c20a6ecb4d14327620ff5bed9d9bb4b5111da4d2c1adac59fc4b4cd25b73c3a7edc0d21f7d1460a5fc32bac9f8
|
data/README.md
CHANGED
@@ -93,16 +93,12 @@ __Note__: if you want to use compression you should also install [snappy](http:/
|
|
93
93
|
|
94
94
|
Some of the new features added to the driver have unfortunately led to changes in the original cql-rb API. In the examples directory, you can find [an example of how to wrap the ruby driver to achieve almost complete interface parity with cql-rb](https://github.com/datastax/ruby-driver/blob/master/examples/cql-rb-wrapper.rb) to assist you with gradual upgrade.
|
95
95
|
|
96
|
-
## What's new in v1.
|
96
|
+
## What's new in v1.2.0
|
97
97
|
|
98
|
-
|
98
|
+
Bug Fixes:
|
99
99
|
|
100
|
-
*
|
101
|
-
*
|
102
|
-
* [`Cassandra::LoadBalancing::Policy#teardown`](http://datastax.github.io/ruby-driver/api/load_balancing/policy/#teardown-instance_method) for cleaning up resources
|
103
|
-
* [`Cassandra::Cluster#refresh_schema`](http://datastax.github.io/ruby-driver/api/cluster/#refresh_schema-instance_method) for manually refreshing schema metadata
|
104
|
-
* Host list randomization to prevent hotspots between multiple clients
|
105
|
-
* Future listeners run in a dedicated threadpool to not block the reactor
|
100
|
+
* [RUBY-83] Timestamps loses microseconds when retrieved from database
|
101
|
+
* [RUBY-85] Driver doesn't always reconnect
|
106
102
|
|
107
103
|
## Code examples
|
108
104
|
|
@@ -147,6 +143,10 @@ Prereleases will be stable, in the sense that they will have finished and proper
|
|
147
143
|
|
148
144
|
Please [refer to the usage documentation for more information on common pitfalls](http://datastax.github.io/ruby-driver/features/)
|
149
145
|
|
146
|
+
## Contributing
|
147
|
+
|
148
|
+
For contributing read [CONTRIBUTING.md](https://github.com/datastax/ruby-driver/blob/master/README.md)
|
149
|
+
|
150
150
|
## Credits
|
151
151
|
|
152
152
|
This driver is based on the original work of [Theo Hultberg](https://github.com/iconara) on [cql-rb](https://github.com/iconara/cql-rb/) and adds a series of advanced features that are common across all other DataStax drivers for Apache Cassandra.
|
@@ -36,10 +36,10 @@ module Cassandra
|
|
36
36
|
@address_resolver = address_resolution_policy
|
37
37
|
@connection_options = connection_options
|
38
38
|
@futures = futures_factory
|
39
|
-
@connecting_hosts = ::Hash.new
|
40
39
|
@connections = ::Hash.new
|
41
40
|
@prepared_statements = ::Hash.new
|
42
41
|
@preparing_statements = ::Hash.new
|
42
|
+
@pending_connections = ::Hash.new
|
43
43
|
@keyspace = nil
|
44
44
|
@state = :idle
|
45
45
|
|
@@ -47,6 +47,8 @@ module Cassandra
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def connect
|
50
|
+
connecting_hosts = ::Hash.new
|
51
|
+
|
50
52
|
synchronize do
|
51
53
|
return CLIENT_CLOSED if @state == :closed || @state == :closing
|
52
54
|
return @connected_future if @state == :connecting || @state == :connected
|
@@ -54,9 +56,24 @@ module Cassandra
|
|
54
56
|
@state = :connecting
|
55
57
|
@registry.each_host do |host|
|
56
58
|
distance = @load_balancing_policy.distance(host)
|
57
|
-
next if distance == :ignore
|
58
59
|
|
59
|
-
|
60
|
+
case distance
|
61
|
+
when :ignore
|
62
|
+
next
|
63
|
+
when :local
|
64
|
+
pool_size = @connection_options.connections_per_local_node
|
65
|
+
when :remote
|
66
|
+
pool_size = @connection_options.connections_per_remote_node
|
67
|
+
else
|
68
|
+
@logger.error("Not connecting to #{host.ip} - invalid load balancing distance. Distance must be one of #{LoadBalancing::DISTANCES.inspect}, #{distance.inspect} given")
|
69
|
+
next
|
70
|
+
end
|
71
|
+
|
72
|
+
connecting_hosts[host] = pool_size
|
73
|
+
@pending_connections[host] = 0
|
74
|
+
@prepared_statements[host] = {}
|
75
|
+
@preparing_statements[host] = {}
|
76
|
+
@connections[host] = ConnectionPool.new
|
60
77
|
end
|
61
78
|
end
|
62
79
|
|
@@ -65,8 +82,8 @@ module Cassandra
|
|
65
82
|
@registry.add_listener(self)
|
66
83
|
@schema.add_listener(self)
|
67
84
|
|
68
|
-
futures =
|
69
|
-
f = connect_to_host(host,
|
85
|
+
futures = connecting_hosts.map do |(host, pool_size)|
|
86
|
+
f = connect_to_host(host, pool_size)
|
70
87
|
f.recover do |error|
|
71
88
|
FailedConnection.new(error, host)
|
72
89
|
end
|
@@ -125,30 +142,40 @@ module Cassandra
|
|
125
142
|
end
|
126
143
|
|
127
144
|
def host_up(host)
|
128
|
-
|
145
|
+
pool_size = 0
|
129
146
|
|
130
147
|
synchronize do
|
131
|
-
return Ione::Future.resolved if @connecting_hosts.include?(host)
|
132
|
-
|
133
148
|
distance = @load_balancing_policy.distance(host)
|
134
|
-
|
149
|
+
case distance
|
150
|
+
when :ignore
|
151
|
+
return Ione::Future.resolved
|
152
|
+
when :local
|
153
|
+
pool_size = @connection_options.connections_per_local_node
|
154
|
+
when :remote
|
155
|
+
pool_size = @connection_options.connections_per_remote_node
|
156
|
+
else
|
157
|
+
@logger.error("Not connecting to #{host.ip} - invalid load balancing distance. Distance must be one of #{LoadBalancing::DISTANCES.inspect}, #{distance.inspect} given")
|
158
|
+
return Ione::Future.resolved
|
159
|
+
end
|
135
160
|
|
136
|
-
@
|
161
|
+
@pending_connections[host] ||= 0
|
162
|
+
@prepared_statements[host] = {}
|
163
|
+
@preparing_statements[host] = {}
|
164
|
+
@connections[host] = ConnectionPool.new
|
137
165
|
end
|
138
166
|
|
139
|
-
connect_to_host_maybe_retry(host,
|
167
|
+
connect_to_host_maybe_retry(host, pool_size)
|
140
168
|
end
|
141
169
|
|
142
170
|
def host_down(host)
|
143
171
|
pool = nil
|
144
172
|
|
145
173
|
synchronize do
|
146
|
-
return Ione::Future.resolved
|
174
|
+
return Ione::Future.resolved unless @connections.has_key?(host)
|
147
175
|
|
148
|
-
@
|
176
|
+
@pending_connections.delete(host) unless @pending_connections[host] > 0
|
149
177
|
@prepared_statements.delete(host)
|
150
178
|
@preparing_statements.delete(host)
|
151
|
-
|
152
179
|
pool = @connections.delete(host)
|
153
180
|
end
|
154
181
|
|
@@ -299,93 +326,89 @@ module Cassandra
|
|
299
326
|
Ione::Future.all(*futures).map(self)
|
300
327
|
end
|
301
328
|
|
302
|
-
def connect_to_host_maybe_retry(host,
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
end
|
308
|
-
|
309
|
-
f
|
329
|
+
def connect_to_host_maybe_retry(host, pool_size)
|
330
|
+
connect_to_host(host, pool_size).fallback do |e|
|
331
|
+
@logger.error("Scheduling initial connection retry to #{host.ip} (#{e.class.name}: #{e.message})")
|
332
|
+
connect_to_host_with_retry(host, pool_size, @reconnection_policy.schedule)
|
333
|
+
end.map(nil)
|
310
334
|
end
|
311
335
|
|
312
|
-
def connect_to_host_with_retry(host, schedule)
|
336
|
+
def connect_to_host_with_retry(host, pool_size, schedule)
|
313
337
|
interval = schedule.next
|
314
338
|
|
315
339
|
@logger.debug("Reconnecting to #{host.ip} in #{interval} seconds")
|
316
340
|
|
317
341
|
f = @reactor.schedule_timer(interval)
|
318
342
|
f.flat_map do
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
if @connecting_hosts.include?(host)
|
323
|
-
distance = @load_balancing_policy.distance(host)
|
324
|
-
end
|
325
|
-
end
|
326
|
-
|
327
|
-
if distance && distance != :ignore
|
328
|
-
connect_to_host(host, distance).fallback do |e|
|
329
|
-
connect_to_host_with_retry(host, schedule)
|
330
|
-
end
|
331
|
-
else
|
332
|
-
NO_CONNECTIONS
|
343
|
+
connect_to_host(host, pool_size).fallback do |e|
|
344
|
+
@logger.error("Scheduling connection retry to #{host.ip} (#{e.class.name}: #{e.message})")
|
345
|
+
connect_to_host_with_retry(host, pool_size, schedule)
|
333
346
|
end
|
334
347
|
end
|
335
348
|
end
|
336
349
|
|
337
|
-
def connect_to_host(host,
|
338
|
-
|
339
|
-
when :ignore
|
340
|
-
return NO_CONNECTIONS
|
341
|
-
when :local
|
342
|
-
pool_size = @connection_options.connections_per_local_node
|
343
|
-
when :remote
|
344
|
-
pool_size = @connection_options.connections_per_remote_node
|
345
|
-
else
|
346
|
-
@logger.error("Invalid load balancing distance, not connecting to #{host.ip}. Distance must be one of #{LoadBalancing::DISTANCES.inspect}, #{distance.inspect} given")
|
347
|
-
return NO_CONNECTIONS
|
348
|
-
end
|
349
|
-
|
350
|
-
pool = nil
|
351
|
-
existing_connections = 0
|
350
|
+
def connect_to_host(host, pool_size)
|
351
|
+
size = 0
|
352
352
|
|
353
353
|
synchronize do
|
354
|
+
unless @connections.include?(host)
|
355
|
+
@logger.info("Not connecting to #{host.ip} - host is currently down")
|
356
|
+
return NO_CONNECTIONS
|
357
|
+
end
|
358
|
+
|
354
359
|
pool = @connections[host]
|
355
|
-
|
360
|
+
size = pool_size - pool.size
|
356
361
|
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
362
|
+
if size <= 0
|
363
|
+
@logger.info("Not connecting to #{host.ip} - host is already fully connected")
|
364
|
+
return NO_CONNECTIONS
|
365
|
+
end
|
366
|
+
|
367
|
+
size -= @pending_connections[host]
|
361
368
|
|
362
|
-
|
369
|
+
if size <= 0
|
370
|
+
@logger.info("Not connecting to #{host.ip} - host is already pending connections")
|
371
|
+
return NO_CONNECTIONS
|
372
|
+
end
|
373
|
+
|
374
|
+
@pending_connections[host] += size
|
375
|
+
end
|
376
|
+
|
377
|
+
@logger.debug("Creating #{size} connections to #{host.ip}")
|
378
|
+
f = @connector.connect_many(host, size)
|
363
379
|
|
364
380
|
f.on_value do |connections|
|
381
|
+
@logger.debug("Created #{connections.size} connections to #{host.ip}")
|
382
|
+
|
365
383
|
pool = nil
|
366
384
|
|
367
385
|
synchronize do
|
368
|
-
@
|
369
|
-
@prepared_statements[host] = {}
|
370
|
-
@preparing_statements[host] = {}
|
371
|
-
pool = @connections[host] ||= ConnectionPool.new
|
372
|
-
end
|
386
|
+
@pending_connections[host] -= size
|
373
387
|
|
374
|
-
|
388
|
+
if @connections.include?(host)
|
389
|
+
pool = @connections[host]
|
390
|
+
else
|
391
|
+
@pending_connections.delete(host) unless @pending_connections[host] > 0
|
392
|
+
end
|
393
|
+
end
|
375
394
|
|
376
|
-
|
377
|
-
|
378
|
-
distance = nil
|
395
|
+
if pool
|
396
|
+
pool.add_connections(connections)
|
379
397
|
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
@connecting_hosts[host] = distance unless distance == :ignore
|
384
|
-
end
|
398
|
+
connections.each do |connection|
|
399
|
+
connection.on_closed do |cause|
|
400
|
+
connect_to_host_maybe_retry(host, pool_size) if cause
|
385
401
|
end
|
386
|
-
|
387
|
-
connect_to_host_maybe_retry(host, distance).map(nil) if distance
|
388
402
|
end
|
403
|
+
else
|
404
|
+
connections.each {|c| c.close}
|
405
|
+
end
|
406
|
+
end
|
407
|
+
|
408
|
+
f.on_failure do |error|
|
409
|
+
synchronize do
|
410
|
+
@pending_connections[host] -= size
|
411
|
+
@pending_connections.delete(host) unless @pending_connections[host] > 0 || @connections.include?(host)
|
389
412
|
end
|
390
413
|
end
|
391
414
|
|
@@ -116,12 +116,12 @@ module Cassandra
|
|
116
116
|
UNCLAIMED_TIMEOUT = 5 # close unclaimed connections in five seconds
|
117
117
|
|
118
118
|
def do_connect(host)
|
119
|
-
|
119
|
+
@reactor.connect(host.ip.to_s, @connection_options.port, {:timeout => @connection_options.connect_timeout, :ssl => @connection_options.ssl}) do |connection|
|
120
120
|
raise Errors::ClientError, 'Not connected, reactor stopped' unless connection
|
121
121
|
Protocol::CqlProtocolHandler.new(connection, @reactor, @connection_options.protocol_version, @connection_options.compressor, @connection_options.heartbeat_interval, @connection_options.idle_timeout)
|
122
|
-
end
|
123
|
-
|
124
|
-
|
122
|
+
end.flat_map do |connection|
|
123
|
+
f = request_options(connection)
|
124
|
+
f = f.flat_map do |options|
|
125
125
|
compression = @connection_options.compression
|
126
126
|
supported_algorithms = options['COMPRESSION']
|
127
127
|
|
@@ -135,19 +135,30 @@ module Cassandra
|
|
135
135
|
|
136
136
|
startup_connection(connection, cql_version, compression)
|
137
137
|
end
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
138
|
+
f.fallback do |error|
|
139
|
+
case error
|
140
|
+
when Errors::ProtocolError
|
141
|
+
synchronize do
|
142
|
+
if @connection_options.protocol_version > 1
|
143
|
+
@logger.info("Host #{host.ip} doesn't support protocol version #{@connection_options.protocol_version}, downgrading")
|
144
|
+
@connection_options.protocol_version -= 1
|
145
|
+
do_connect(host)
|
146
|
+
else
|
147
|
+
Ione::Future.failed(error)
|
148
|
+
end
|
149
149
|
end
|
150
|
+
when Errors::TimeoutError
|
151
|
+
future = Ione::CompletableFuture.new
|
152
|
+
connection.close(error).on_complete do |f|
|
153
|
+
future.fail(error)
|
154
|
+
end
|
155
|
+
future
|
156
|
+
else
|
157
|
+
Ione::Future.failed(error)
|
150
158
|
end
|
159
|
+
end
|
160
|
+
end.fallback do |error|
|
161
|
+
case error
|
151
162
|
when Error
|
152
163
|
Ione::Future.failed(error)
|
153
164
|
else
|
@@ -188,7 +188,11 @@ module Cassandra
|
|
188
188
|
def bytes_to_timestamp(buffer, size_bytes)
|
189
189
|
return nil unless read_size(buffer, size_bytes)
|
190
190
|
timestamp = buffer.read_long
|
191
|
-
|
191
|
+
|
192
|
+
seconds = timestamp / 1_000
|
193
|
+
microsenconds = (timestamp % 1_000) * 1_000
|
194
|
+
|
195
|
+
Time.at(seconds, microsenconds)
|
192
196
|
end
|
193
197
|
|
194
198
|
def bytes_to_varchar(buffer, size_bytes)
|
@@ -339,7 +343,7 @@ module Cassandra
|
|
339
343
|
|
340
344
|
def timestamp_to_bytes(buffer, value, size_bytes)
|
341
345
|
if value
|
342
|
-
ms = (value.to_f * 1000).to_i
|
346
|
+
ms = (value.to_r.to_f * 1000).to_i
|
343
347
|
size_to_bytes(buffer, 8, size_bytes)
|
344
348
|
buffer.append_long(ms)
|
345
349
|
else
|
@@ -382,4 +386,4 @@ module Cassandra
|
|
382
386
|
end
|
383
387
|
end
|
384
388
|
end
|
385
|
-
end
|
389
|
+
end
|
data/lib/cassandra/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cassandra-driver
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Theo Hultberg
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2015-01-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ione
|