cassandra-driver 1.0.0.beta.3-java → 1.0.0-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +51 -14
- data/lib/cassandra.rb +164 -78
- data/lib/cassandra/address_resolution.rb +36 -0
- data/lib/cassandra/address_resolution/policies.rb +2 -0
- data/lib/cassandra/address_resolution/policies/ec2_multi_region.rb +56 -0
- data/lib/cassandra/address_resolution/policies/none.rb +35 -0
- data/lib/cassandra/auth.rb +1 -1
- data/lib/cassandra/auth/providers/password.rb +1 -1
- data/lib/cassandra/cluster.rb +18 -5
- data/lib/cassandra/cluster/client.rb +175 -101
- data/lib/cassandra/{client/connection_manager.rb → cluster/connection_pool.rb} +5 -5
- data/lib/cassandra/cluster/connector.rb +142 -56
- data/lib/cassandra/cluster/control_connection.rb +385 -134
- data/lib/cassandra/{client/null_logger.rb → cluster/failed_connection.rb} +12 -14
- data/lib/cassandra/cluster/options.rb +13 -2
- data/lib/cassandra/cluster/registry.rb +19 -9
- data/lib/cassandra/column.rb +5 -0
- data/lib/cassandra/compression.rb +1 -1
- data/lib/cassandra/compression/compressors/lz4.rb +1 -1
- data/lib/cassandra/compression/compressors/snappy.rb +1 -1
- data/lib/cassandra/driver.rb +29 -21
- data/lib/cassandra/errors.rb +325 -35
- data/lib/cassandra/execution/options.rb +13 -6
- data/lib/cassandra/execution/trace.rb +4 -4
- data/lib/cassandra/future.rb +7 -3
- data/lib/cassandra/keyspace.rb +5 -0
- data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +13 -4
- data/lib/cassandra/load_balancing/policies/token_aware.rb +2 -4
- data/lib/cassandra/load_balancing/policies/white_list.rb +3 -6
- data/lib/cassandra/null_logger.rb +35 -0
- data/lib/cassandra/protocol.rb +0 -16
- data/lib/cassandra/protocol/cql_byte_buffer.rb +18 -18
- data/lib/cassandra/protocol/cql_protocol_handler.rb +78 -8
- data/lib/cassandra/protocol/frame_decoder.rb +2 -2
- data/lib/cassandra/protocol/frame_encoder.rb +1 -1
- data/lib/cassandra/protocol/requests/query_request.rb +1 -11
- data/lib/cassandra/protocol/response.rb +1 -1
- data/lib/cassandra/protocol/responses/detailed_error_response.rb +16 -1
- data/lib/cassandra/protocol/responses/error_response.rb +17 -0
- data/lib/cassandra/protocol/responses/event_response.rb +1 -1
- data/lib/cassandra/protocol/responses/raw_rows_result_response.rb +1 -1
- data/lib/cassandra/protocol/responses/result_response.rb +1 -1
- data/lib/cassandra/protocol/responses/rows_result_response.rb +1 -1
- data/lib/cassandra/protocol/type_converter.rb +4 -3
- data/lib/cassandra/reconnection.rb +1 -1
- data/lib/cassandra/result.rb +4 -6
- data/lib/cassandra/retry.rb +3 -5
- data/lib/cassandra/session.rb +14 -5
- data/lib/cassandra/statements/prepared.rb +5 -1
- data/lib/cassandra/table.rb +6 -1
- data/lib/cassandra/time_uuid.rb +21 -83
- data/lib/cassandra/util.rb +131 -1
- data/lib/cassandra/uuid.rb +6 -4
- data/lib/cassandra/uuid/generator.rb +207 -0
- data/lib/cassandra/version.rb +1 -1
- data/lib/cassandra_murmur3.jar +0 -0
- metadata +43 -49
- data/lib/cassandra/client.rb +0 -144
- data/lib/cassandra/client/batch.rb +0 -212
- data/lib/cassandra/client/client.rb +0 -591
- data/lib/cassandra/client/column_metadata.rb +0 -54
- data/lib/cassandra/client/connector.rb +0 -277
- data/lib/cassandra/client/execute_options_decoder.rb +0 -59
- data/lib/cassandra/client/peer_discovery.rb +0 -50
- data/lib/cassandra/client/prepared_statement.rb +0 -314
- data/lib/cassandra/client/query_result.rb +0 -230
- data/lib/cassandra/client/request_runner.rb +0 -71
- data/lib/cassandra/client/result_metadata.rb +0 -48
- data/lib/cassandra/client/void_result.rb +0 -78
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8fb7875e0edf290caf3226ac04b20a6b55702ce0
|
4
|
+
data.tar.gz: 188e96a446ecaf5565f851cf76ea5f0ffa7a5229
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b4c5895f4a5e774cf62b2caf9e199538467124ffcf522a42e2118f77fa09b9490c4f0db0a66922e1dee168e5cc2afddbe71830033ad3c30a2f8fa6f14b4dca84
|
7
|
+
data.tar.gz: 04f3589e992f19720ddcf877499b485a2a819338889e6fba94acba2f66fd7102558dfa519eff76c28ed51497e5cb3bd6c25819e6c3ba3347823579ee59c5c4b2
|
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# Datastax Ruby Driver for Apache Cassandra
|
2
2
|
|
3
|
+
*If you're reading this on GitHub, please note that this is the readme for the development version and that some features described here might not yet have been released. You can [find the documentation for latest version through ruby driver docs](http://datastax.github.io/ruby-driver/) or via the release tags, [e.g. v1.0.0-beta.3](https://github.com/datastax/ruby-driver/tree/v1.0.0-beta.3).*
|
4
|
+
|
3
5
|
[![Build Status](https://travis-ci.org/datastax/ruby-driver.svg?branch=master)](https://travis-ci.org/datastax/ruby-driver)
|
4
6
|
|
5
7
|
A Ruby client driver for Apache Cassandra. This driver works exclusively with
|
@@ -7,10 +9,10 @@ the Cassandra Query Language version 3 (CQL3) and Cassandra's native protocol.
|
|
7
9
|
|
8
10
|
- Code: https://github.com/datastax/ruby-driver
|
9
11
|
- Docs: http://datastax.github.io/ruby-driver/
|
10
|
-
-
|
11
|
-
-
|
12
|
+
- Jira: https://datastax-oss.atlassian.net/browse/RUBY
|
13
|
+
- Mailing List: https://groups.google.com/a/lists.datastax.com/forum/#!forum/ruby-driver-user
|
12
14
|
- IRC: #datastax-drivers on [irc.freenode.net](http://freenode.net>)
|
13
|
-
-
|
15
|
+
- Twitter: Follow the latest news about DataStax Drivers - [@avalanche123](http://twitter.com/avalanche123), [@mfiguiere](http://twitter.com/mfiguiere), [@al3xandru](https://twitter.com/al3xandru)
|
14
16
|
|
15
17
|
This driver is based on [the cql-rb gem](https://github.com/iconara/cql-rb) by [Theo Hultberg](https://github.com/iconara) and we added support for:
|
16
18
|
|
@@ -18,15 +20,17 @@ This driver is based on [the cql-rb gem](https://github.com/iconara/cql-rb) by [
|
|
18
20
|
* one-off, [prepared](http://datastax.github.io/ruby-driver/features/basics/prepared_statements/) and [batch statements](http://datastax.github.io/ruby-driver/features/basics/batch_statements/)
|
19
21
|
* automatic peer discovery and cluster metadata
|
20
22
|
* various [load-balancing](http://datastax.github.io/ruby-driver/features/load_balancing/), [retry](http://datastax.github.io/ruby-driver/features/retry_policies/) and reconnection policies, [with ability to write your own](http://datastax.github.io/ruby-driver/features/load_balancing/implementing_a_policy/)
|
23
|
+
* [SSL encryption](http://datastax.github.io/ruby-driver/features/security/ssl_encryption/)
|
21
24
|
|
22
25
|
## Compability
|
23
26
|
|
24
27
|
This driver works exclusively with the Cassandra Query Language v3 (CQL3) and Cassandra's native protocol. The current version works with:
|
25
28
|
|
26
|
-
* Cassandra versions 1.2 and 2.0
|
27
|
-
*
|
29
|
+
* Apache Cassandra versions 1.2 and 2.0
|
30
|
+
* DataStax Enterprise 3.1, 3.2, 4.0 and 4.5
|
31
|
+
* Ruby (MRI) 1.9.3, 2.0 and 2.1
|
28
32
|
* JRuby 1.7
|
29
|
-
* Rubinius 2.
|
33
|
+
* Rubinius 2.2
|
30
34
|
|
31
35
|
__Note__: JRuby 1.6 is not officially supported, although 1.6.8 should work.
|
32
36
|
|
@@ -35,7 +39,7 @@ __Note__: JRuby 1.6 is not officially supported, although 1.6.8 should work.
|
|
35
39
|
```ruby
|
36
40
|
require 'cassandra'
|
37
41
|
|
38
|
-
cluster = Cassandra.
|
42
|
+
cluster = Cassandra.cluster # connects to localhost by default
|
39
43
|
|
40
44
|
cluster.each_host do |host| # automatically discovers all peers
|
41
45
|
puts "Host #{host.ip}: id=#{host.id} datacenter=#{host.datacenter} rack=#{host.rack}"
|
@@ -57,7 +61,7 @@ The host you specify is just a seed node, the driver will automatically discover
|
|
57
61
|
|
58
62
|
Read more:
|
59
63
|
|
60
|
-
* [`Cassandra.
|
64
|
+
* [`Cassandra.cluster` options](http://datastax.github.io/ruby-driver/api/#cluster-class_method)
|
61
65
|
* [`Session#execute_async` options](http://datastax.github.io/ruby-driver/api/session/#execute_async-instance_method)
|
62
66
|
* [Usage documentation](http://datastax.github.io/ruby-driver/features)
|
63
67
|
|
@@ -72,7 +76,7 @@ gem install cassandra-driver --pre
|
|
72
76
|
Install via Gemfile
|
73
77
|
|
74
78
|
```ruby
|
75
|
-
gem 'cassandra-driver', '~> 1.0.0.
|
79
|
+
gem 'cassandra-driver', '~> 1.0.0.rc'
|
76
80
|
```
|
77
81
|
|
78
82
|
Note: if you want to use compression you should also install [snappy](http://rubygems.org/gems/snappy) or [lz4-ruby](http://rubygems.org/gems/lz4-ruby). [Read more about compression.](http://datastax.github.io/ruby-driver/features/#compression)
|
@@ -82,13 +86,45 @@ Note: if you want to use compression you should also install [snappy](http://rub
|
|
82
86
|
|
83
87
|
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.
|
84
88
|
|
85
|
-
## What's new in v1.0.0
|
89
|
+
## What's new in v1.0.0
|
86
90
|
|
87
91
|
Current release introduces the following new features:
|
88
92
|
|
89
|
-
* [
|
93
|
+
* [Asynchronous execution](http://datastax.github.io/ruby-driver/features/asynchronous_io/)
|
94
|
+
* One-off, [prepared](http://datastax.github.io/ruby-driver/features/basics/prepared_statements/) and [batch statements](http://datastax.github.io/ruby-driver/features/basics/batch_statements/)
|
95
|
+
* Automatic peer discovery and cluster metadata with [support for change notifications](http://datastax.github.io/ruby-driver/features/state_listeners/)
|
96
|
+
* Various [load-balancing](http://datastax.github.io/ruby-driver/features/load_balancing/), [retry](http://datastax.github.io/ruby-driver/features/retry_policies/) and reconnection policies, [with ability to write your own](http://datastax.github.io/ruby-driver/features/load_balancing/implementing_a_policy/)
|
90
97
|
* [SSL encryption](http://datastax.github.io/ruby-driver/features/security/ssl_encryption/)
|
91
|
-
*
|
98
|
+
* [Flexible and robust error handling](http://datastax.github.io/ruby-driver/features/error_handling/)
|
99
|
+
* [Per-request execution information and tracing](http://datastax.github.io/ruby-driver/features/debugging/)
|
100
|
+
* [Configurable address resolution](http://datastax.github.io/ruby-driver/features/address_resolution/)
|
101
|
+
|
102
|
+
## Code examples
|
103
|
+
|
104
|
+
The DataStax Ruby Driver uses the awesome [Cucumber Framework](http://cukes.info/) for both end-to-end, or acceptance, testing and constructing documentation. All of the features supported by the driver have appropriate acceptance tests with easy-to-copy code examples in the `features/` directory.
|
105
|
+
|
106
|
+
## Running tests
|
107
|
+
|
108
|
+
If you don't feel like reading through the following instructions on how to run ruby-driver tests, feel free to [check out .travis.yml for the entire build code](https://github.com/datastax/ruby-driver/blob/master/.travis.yml).
|
109
|
+
|
110
|
+
* Check out the driver codebase and install test dependencies:
|
111
|
+
|
112
|
+
```bash
|
113
|
+
git clone https://github.com/datastax/ruby-driver.git
|
114
|
+
cd ruby-driver
|
115
|
+
bundle install --without docs
|
116
|
+
```
|
117
|
+
|
118
|
+
* [Install ccm](http://www.datastax.com/dev/blog/ccm-a-development-tool-for-creating-local-cassandra-clusters)
|
119
|
+
|
120
|
+
* Run tests:
|
121
|
+
|
122
|
+
```bash
|
123
|
+
bundle exec cucumber # runs end-to-end tests (or bundle exec rake cucumber)
|
124
|
+
bundle exec rspec # runs unit tests (or bundle exec rake rspec)
|
125
|
+
bundle exec rake integration # run integration tests
|
126
|
+
bundle exec rake test # run both as well as integration tests
|
127
|
+
```
|
92
128
|
|
93
129
|
## Changelog & versioning
|
94
130
|
|
@@ -102,13 +138,15 @@ Prereleases will be stable, in the sense that they will have finished and proper
|
|
102
138
|
|
103
139
|
* JRuby 1.6 is not officially supported, although 1.6.8 should work, if you're stuck in JRuby 1.6.8 try and see if it works for you.
|
104
140
|
* Because the driver reactor is using `IO.select`, the maximum number of tcp connections allowed is 1024.
|
141
|
+
* Because the driver uses `IO#write_nonblock`, Windows is not supported.
|
105
142
|
|
143
|
+
Please [refer to the usage documentation for more information on common pitfalls](http://datastax.github.io/ruby-driver/features/)
|
106
144
|
|
107
145
|
## Credits
|
108
146
|
|
109
147
|
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.
|
110
148
|
|
111
|
-
The development effort to provide an up to date, high performance, fully featured Ruby Driver for Apache Cassandra will continue on this project, while [cql-rb](https://github.com/iconara/cql-rb/) will be discontinued.
|
149
|
+
The development effort to provide an up to date, high performance, fully featured Ruby Driver for Apache Cassandra will continue on this project, while [cql-rb](https://github.com/iconara/cql-rb/) will be discontinued.
|
112
150
|
|
113
151
|
|
114
152
|
## Copyright
|
@@ -122,4 +160,3 @@ Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
|
122
160
|
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
123
161
|
|
124
162
|
[1]: http://datastax.github.io/ruby-driver/api
|
125
|
-
|
data/lib/cassandra.rb
CHANGED
@@ -30,9 +30,13 @@ require 'digest'
|
|
30
30
|
require 'stringio'
|
31
31
|
require 'resolv'
|
32
32
|
require 'openssl'
|
33
|
+
require 'securerandom'
|
34
|
+
require 'time'
|
33
35
|
|
34
36
|
module Cassandra
|
35
37
|
# A list of all supported request consistencies
|
38
|
+
# @see http://www.datastax.com/documentation/cassandra/2.0/cassandra/dml/dml_config_consistency_c.html Consistency levels in Apache Cassandra 2.0
|
39
|
+
# @see http://www.datastax.com/documentation/cassandra/1.2/cassandra/dml/dml_config_consistency_c.html Consistency levels in Apache Cassandra 1.2
|
36
40
|
# @see Cassandra::Session#execute_async
|
37
41
|
CONSISTENCIES = [ :any, :one, :two, :three, :quorum, :all, :local_quorum,
|
38
42
|
:each_quorum, :serial, :local_serial, :local_one ].freeze
|
@@ -41,6 +45,12 @@ module Cassandra
|
|
41
45
|
# @see Cassandra::Session#execute_async
|
42
46
|
SERIAL_CONSISTENCIES = [:serial, :local_serial].freeze
|
43
47
|
|
48
|
+
# A list of all possible write types that a
|
49
|
+
# {Cassandra::Errors::WriteTimeoutError} can have.
|
50
|
+
#
|
51
|
+
# @see https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v1.spec#L591-L603 Description of possible types of writes in Apache Cassandra native protocol spec v1
|
52
|
+
WRITE_TYPES = [:simple, :batch, :unlogged_batch, :counter, :batch_log].freeze
|
53
|
+
|
44
54
|
# Creates a {Cassandra::Cluster} instance
|
45
55
|
#
|
46
56
|
# @option options [Array<String, IPAddr>] :hosts (['127.0.0.1']) a list of
|
@@ -50,8 +60,28 @@ module Cassandra
|
|
50
60
|
#
|
51
61
|
# @option options [Integer] :port (9042) cassandra native protocol port.
|
52
62
|
#
|
63
|
+
# @option options [String] :datacenter (nil) name of current datacenter.
|
64
|
+
# First datacenter found will be assumed current by default. Note that you
|
65
|
+
# can skip this option if you specify only hosts from the local datacenter
|
66
|
+
# in `:hosts` option.
|
67
|
+
#
|
53
68
|
# @option options [Numeric] :connect_timeout (10) connection timeout in
|
54
|
-
# seconds.
|
69
|
+
# seconds. Setting value to `nil` will reset it to 5 seconds.
|
70
|
+
#
|
71
|
+
# @option options [Numeric] :timeout (10) request execution timeout in
|
72
|
+
# seconds. Setting value to `nil` will remove request timeout.
|
73
|
+
#
|
74
|
+
# @option options [Numeric] :heartbeat_interval (30) how often should a
|
75
|
+
# heartbeat be sent to determine if a connection is alive. Several things to
|
76
|
+
# note about this option. Only one heartbeat request will ever be
|
77
|
+
# outstanding on a given connection. Each heatbeat will be sent in at least
|
78
|
+
# `:heartbeat_interval` seconds after the last request has been sent on a
|
79
|
+
# given connection. Setting value to `nil` will remove connection timeout.
|
80
|
+
#
|
81
|
+
# @option options [Numeric] :idle_timeout (60) period of inactivity after
|
82
|
+
# which a connection is considered dead. Note that this value should be at
|
83
|
+
# least a few times larger than `:heartbeat_interval`. Setting value to
|
84
|
+
# `nil` will remove automatic connection termination.
|
55
85
|
#
|
56
86
|
# @option options [String] :username (none) username to use for
|
57
87
|
# authentication to cassandra. Note that you must also specify `:password`.
|
@@ -83,12 +113,15 @@ module Cassandra
|
|
83
113
|
# work, you must install 'snappy' or 'lz4-ruby' gems.
|
84
114
|
#
|
85
115
|
# @option options [Cassandra::LoadBalancing::Policy] :load_balancing_policy
|
86
|
-
# default:
|
116
|
+
# default: token aware data center aware round robin.
|
117
|
+
#
|
118
|
+
# @option options [Symbol] :address_resolution (:none) a pre-configured
|
119
|
+
# address resolver to use. Must be one of `:none` or
|
120
|
+
# `:ec2_multi_region`.
|
87
121
|
#
|
88
122
|
# @option options [Cassandra::Reconnection::Policy] :reconnection_policy
|
89
123
|
# default: {Cassandra::Reconnection::Policies::Exponential}. Note that the
|
90
|
-
# default policy is configured with
|
91
|
-
# `Reconnection::Policies::Exponential.new(0.5, 30, 2)`.
|
124
|
+
# default policy is configured with `(0.5, 30, 2)`.
|
92
125
|
#
|
93
126
|
# @option options [Cassandra::Retry::Policy] :retry_policy default:
|
94
127
|
# {Cassandra::Retry::Policies::Default}.
|
@@ -101,50 +134,69 @@ module Cassandra
|
|
101
134
|
# initial listeners. A list of initial cluster state listeners. Note that a
|
102
135
|
# `:load_balancing` policy is automatically registered with the cluster.
|
103
136
|
#
|
104
|
-
# @option options [Symbol] :consistency (:
|
105
|
-
#
|
137
|
+
# @option options [Symbol] :consistency (:one) default consistency to use for
|
138
|
+
# all requests. Must be one of {Cassandra::CONSISTENCIES}.
|
106
139
|
#
|
107
140
|
# @option options [Boolean] :trace (false) whether or not to trace all
|
108
141
|
# requests by default.
|
109
142
|
#
|
110
|
-
# @option options [Integer] :page_size (
|
111
|
-
# queries.
|
143
|
+
# @option options [Integer] :page_size (10000) default page size for all
|
144
|
+
# select queries. Set this value to `nil` to disable paging.
|
112
145
|
#
|
113
146
|
# @option options [Hash{String => String}] :credentials (none) a hash of credentials - to be used with [credentials authentication in cassandra 1.2](https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v1.spec#L238-L250). Note that if you specified `:username` and `:password` options, those credentials are configured automatically.
|
114
147
|
#
|
115
148
|
# @option options [Cassandra::Auth::Provider] :auth_provider (none) a custom auth provider to be used with [SASL authentication in cassandra 2.0](https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v2.spec#L257-L273). Note that if you have specified `:username` and `:password`, then a {Cassandra::Auth::Providers::Password} will be used automatically.
|
116
149
|
#
|
117
|
-
# @option options [Cassandra::Compressor] :compressor (none) a
|
118
|
-
# compressor. Note that if you have specified `:compression`, an
|
150
|
+
# @option options [Cassandra::Compression::Compressor] :compressor (none) a
|
151
|
+
# custom compressor. Note that if you have specified `:compression`, an
|
119
152
|
# appropriate compressor will be provided automatically.
|
120
153
|
#
|
154
|
+
# @option options [Cassandra::AddressResolution::Policy]
|
155
|
+
# :address_resolution_policy default:
|
156
|
+
# {Cassandra::AddressResolution::Policies::None} a custom address resolution
|
157
|
+
# policy. Note that if you have specified `:address_resolution`, an
|
158
|
+
# appropriate address resolution policy will be provided automatically.
|
159
|
+
#
|
121
160
|
# @option options [Object<#all, #error, #value, #promise>] :futures_factory
|
122
|
-
#
|
123
|
-
# futures library. Note that promises returned by this object
|
124
|
-
# to {Cassandra::Promise} api, which is not yet public. Things
|
125
|
-
# use at your own risk.
|
161
|
+
# default: {Cassandra::Future} a futures factory to assist with integration
|
162
|
+
# into existing futures library. Note that promises returned by this object
|
163
|
+
# must conform to {Cassandra::Promise} api, which is not yet public. Things
|
164
|
+
# may change, use at your own risk.
|
126
165
|
#
|
127
166
|
# @example Connecting to localhost
|
128
|
-
# cluster = Cassandra.
|
167
|
+
# cluster = Cassandra.cluster
|
129
168
|
#
|
130
169
|
# @example Configuring {Cassandra::Cluster}
|
131
|
-
# cluster = Cassandra.
|
170
|
+
# cluster = Cassandra.cluster(
|
132
171
|
# username: username,
|
133
172
|
# password: password,
|
134
173
|
# hosts: ['10.0.1.1', '10.0.1.2', '10.0.1.3']
|
135
174
|
# )
|
136
175
|
#
|
137
176
|
# @return [Cassandra::Cluster] a cluster instance
|
138
|
-
def self.
|
139
|
-
options.
|
177
|
+
def self.cluster(options = {})
|
178
|
+
cluster_async(options).get
|
179
|
+
end
|
180
|
+
|
181
|
+
# Creates a {Cassandra::Cluster} instance
|
182
|
+
#
|
183
|
+
# @see Cassandra.cluster
|
184
|
+
#
|
185
|
+
# @return [Cassandra::Future<Cassandra::Cluster>] a future resolving to the
|
186
|
+
# cluster instance.
|
187
|
+
def self.cluster_async(options = {})
|
188
|
+
options = options.select do |key, value|
|
140
189
|
[ :credentials, :auth_provider, :compression, :hosts, :logger, :port,
|
141
190
|
:load_balancing_policy, :reconnection_policy, :retry_policy, :listeners,
|
142
191
|
:consistency, :trace, :page_size, :compressor, :username, :password,
|
143
192
|
:ssl, :server_cert, :client_cert, :private_key, :passphrase,
|
144
|
-
:connect_timeout, :futures_factory
|
193
|
+
:connect_timeout, :futures_factory, :datacenter, :address_resolution,
|
194
|
+
:address_resolution_policy, :idle_timeout, :heartbeat_interval, :timeout
|
145
195
|
].include?(key)
|
146
196
|
end
|
147
197
|
|
198
|
+
futures = options.fetch(:futures_factory, Future)
|
199
|
+
|
148
200
|
has_username = options.has_key?(:username)
|
149
201
|
has_password = options.has_key?(:password)
|
150
202
|
if has_username || has_password
|
@@ -156,11 +208,13 @@ module Cassandra
|
|
156
208
|
raise ::ArgumentError, "both :username and :password options must be specified, but only :password given"
|
157
209
|
end
|
158
210
|
|
159
|
-
username =
|
160
|
-
password =
|
211
|
+
username = options.delete(:username)
|
212
|
+
password = options.delete(:password)
|
161
213
|
|
162
|
-
|
163
|
-
|
214
|
+
Util.assert_instance_of(::String, username) { ":username must be a String, #{username.inspect} given" }
|
215
|
+
Util.assert_instance_of(::String, password) { ":password must be a String, #{password.inspect} given" }
|
216
|
+
Util.assert_not_empty(username) { ":username cannot be empty" }
|
217
|
+
Util.assert_not_empty(password) { ":password cannot be empty" }
|
164
218
|
|
165
219
|
options[:credentials] = {:username => username, :password => password}
|
166
220
|
options[:auth_provider] = Auth::Providers::Password.new(username, password)
|
@@ -169,17 +223,13 @@ module Cassandra
|
|
169
223
|
if options.has_key?(:credentials)
|
170
224
|
credentials = options[:credentials]
|
171
225
|
|
172
|
-
|
173
|
-
raise ::ArgumentError, ":credentials must be a hash, #{credentials.inspect} given"
|
174
|
-
end
|
226
|
+
Util.assert_instance_of(::Hash, credentials) { ":credentials must be a hash, #{credentials.inspect} given" }
|
175
227
|
end
|
176
228
|
|
177
229
|
if options.has_key?(:auth_provider)
|
178
230
|
auth_provider = options[:auth_provider]
|
179
231
|
|
180
|
-
|
181
|
-
raise ::ArgumentError, ":auth_provider #{auth_provider.inspect} must respond to :create_authenticator, but doesn't"
|
182
|
-
end
|
232
|
+
Util.assert_responds_to(:create_authenticator, auth_provider) { ":auth_provider #{auth_provider.inspect} must respond to :create_authenticator, but doesn't" }
|
183
233
|
end
|
184
234
|
|
185
235
|
has_client_cert = options.has_key?(:client_cert)
|
@@ -197,13 +247,8 @@ module Cassandra
|
|
197
247
|
client_cert = ::File.expand_path(options[:client_cert])
|
198
248
|
private_key = ::File.expand_path(options[:private_key])
|
199
249
|
|
200
|
-
|
201
|
-
|
202
|
-
end
|
203
|
-
|
204
|
-
unless ::File.exists?(private_key)
|
205
|
-
raise ::ArgumentError, ":private_key #{private_key.inspect} doesn't exist"
|
206
|
-
end
|
250
|
+
Util.assert_file_exists(client_cert) { ":client_cert #{client_cert.inspect} doesn't exist" }
|
251
|
+
Util.assert_file_exists(private_key) { ":private_key #{private_key.inspect} doesn't exist" }
|
207
252
|
end
|
208
253
|
|
209
254
|
has_server_cert = options.has_key?(:server_cert)
|
@@ -211,9 +256,7 @@ module Cassandra
|
|
211
256
|
if has_server_cert
|
212
257
|
server_cert = ::File.expand_path(options[:server_cert])
|
213
258
|
|
214
|
-
|
215
|
-
raise ::ArgumentError, ":server_cert #{server_cert.inspect} doesn't exist"
|
216
|
-
end
|
259
|
+
Util.assert_file_exists(server_cert) { ":server_cert #{server_cert.inspect} doesn't exist" }
|
217
260
|
end
|
218
261
|
|
219
262
|
if has_client_cert || has_server_cert
|
@@ -240,9 +283,7 @@ module Cassandra
|
|
240
283
|
if options.has_key?(:ssl)
|
241
284
|
ssl = options[:ssl]
|
242
285
|
|
243
|
-
|
244
|
-
raise ":ssl must be a boolean or an OpenSSL::SSL::SSLContext, #{ssl.inspect} given"
|
245
|
-
end
|
286
|
+
Util.assert_instance_of_one_of([::TrueClass, ::FalseClass, ::OpenSSL::SSL::SSLContext], ssl) { ":ssl must be a boolean or an OpenSSL::SSL::SSLContext, #{ssl.inspect} given" }
|
246
287
|
end
|
247
288
|
|
248
289
|
if options.has_key?(:compression)
|
@@ -264,33 +305,59 @@ module Cassandra
|
|
264
305
|
compressor = options[:compressor]
|
265
306
|
methods = [:algorithm, :compress?, :compress, :decompress]
|
266
307
|
|
267
|
-
|
268
|
-
raise ::ArgumentError, ":compressor #{compressor.inspect} must respond to #{methods.inspect}, but doesn't"
|
269
|
-
end
|
308
|
+
Util.assert_responds_to_all(methods, compressor) { ":compressor #{compressor.inspect} must respond to #{methods.inspect}, but doesn't" }
|
270
309
|
end
|
271
310
|
|
272
311
|
if options.has_key?(:logger)
|
273
312
|
logger = options[:logger]
|
274
313
|
methods = [:debug, :info, :warn, :error, :fatal]
|
275
314
|
|
276
|
-
|
277
|
-
raise ::ArgumentError, ":logger #{logger.inspect} must respond to #{methods.inspect}, but doesn't"
|
278
|
-
end
|
315
|
+
Util.assert_responds_to_all(methods, logger) { ":logger #{logger.inspect} must respond to #{methods.inspect}, but doesn't" }
|
279
316
|
end
|
280
317
|
|
281
318
|
if options.has_key?(:port)
|
282
319
|
port = options[:port] = Integer(options[:port])
|
283
320
|
|
284
|
-
|
285
|
-
|
286
|
-
|
321
|
+
Util.assert_one_of(0..65536, port) { ":port must be a valid ip port, #{port} given" }
|
322
|
+
end
|
323
|
+
|
324
|
+
if options.has_key?(:datacenter)
|
325
|
+
options[:datacenter] = String(options[:datacenter])
|
287
326
|
end
|
288
327
|
|
289
328
|
if options.has_key?(:connect_timeout)
|
290
|
-
timeout = options[:connect_timeout]
|
329
|
+
timeout = options[:connect_timeout]
|
330
|
+
|
331
|
+
unless timeout.nil?
|
332
|
+
Util.assert_instance_of(::Numeric, timeout) { ":connect_timeout must be a number of seconds, #{timeout} given" }
|
333
|
+
Util.assert(timeout > 0) { ":connect_timeout must be greater than 0, #{timeout} given" }
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
if options.has_key?(:timeout)
|
338
|
+
timeout = options[:timeout]
|
339
|
+
|
340
|
+
unless timeout.nil?
|
341
|
+
Util.assert_instance_of(::Numeric, timeout) { ":timeout must be a number of seconds, #{timeout} given" }
|
342
|
+
Util.assert(timeout > 0) { ":timeout must be greater than 0, #{timeout} given" }
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
if options.has_key?(:heartbeat_interval)
|
347
|
+
timeout = options[:heartbeat_interval]
|
291
348
|
|
292
|
-
|
293
|
-
|
349
|
+
unless timeout.nil?
|
350
|
+
Util.assert_instance_of(::Numeric, timeout) { ":heartbeat_interval must be a number of seconds, #{timeout} given" }
|
351
|
+
Util.assert(timeout > 0) { ":heartbeat_interval must be greater than 0, #{timeout} given" }
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
if options.has_key?(:idle_timeout)
|
356
|
+
timeout = options[:idle_timeout]
|
357
|
+
|
358
|
+
unless timeout.nil?
|
359
|
+
Util.assert_instance_of(::Numeric, timeout) { ":idle_timeout must be a number of seconds, #{timeout} given" }
|
360
|
+
Util.assert(timeout > 0) { ":idle_timeout must be greater than 0, #{timeout} given" }
|
294
361
|
end
|
295
362
|
end
|
296
363
|
|
@@ -298,42 +365,32 @@ module Cassandra
|
|
298
365
|
load_balancing_policy = options[:load_balancing_policy]
|
299
366
|
methods = [:host_up, :host_down, :host_found, :host_lost, :setup, :distance, :plan]
|
300
367
|
|
301
|
-
|
302
|
-
raise ::ArgumentError, ":load_balancing_policy #{load_balancing_policy.inspect} must respond to #{methods.inspect}, but doesn't"
|
303
|
-
end
|
368
|
+
Util.assert_responds_to_all(methods, load_balancing_policy) { ":load_balancing_policy #{load_balancing_policy.inspect} must respond to #{methods.inspect}, but doesn't" }
|
304
369
|
end
|
305
370
|
|
306
371
|
if options.has_key?(:reconnection_policy)
|
307
372
|
reconnection_policy = options[:reconnection_policy]
|
308
373
|
|
309
|
-
|
310
|
-
raise ::ArgumentError, ":reconnection_policy #{reconnection_policy.inspect} must respond to :schedule, but doesn't"
|
311
|
-
end
|
374
|
+
Util.assert_responds_to(:schedule, reconnection_policy) { ":reconnection_policy #{reconnection_policy.inspect} must respond to :schedule, but doesn't" }
|
312
375
|
end
|
313
376
|
|
314
377
|
if options.has_key?(:retry_policy)
|
315
378
|
retry_policy = options[:retry_policy]
|
316
379
|
methods = [:read_timeout, :write_timeout, :unavailable]
|
317
380
|
|
318
|
-
|
319
|
-
raise ::ArgumentError, ":retry_policy #{retry_policy.inspect} must respond to #{methods.inspect}, but doesn't"
|
320
|
-
end
|
381
|
+
Util.assert_responds_to_all(methods, retry_policy) { ":retry_policy #{retry_policy.inspect} must respond to #{methods.inspect}, but doesn't" }
|
321
382
|
end
|
322
383
|
|
323
384
|
if options.has_key?(:listeners)
|
324
385
|
listeners = options[:listeners]
|
325
386
|
|
326
|
-
|
327
|
-
raise ::ArgumentError, ":listeners must be an Enumerable, #{listeners.inspect} given"
|
328
|
-
end
|
387
|
+
Util.assert_instance_of(::Enumerable, listeners) { ":listeners must be an Enumerable, #{listeners.inspect} given" }
|
329
388
|
end
|
330
389
|
|
331
390
|
if options.has_key?(:consistency)
|
332
391
|
consistency = options[:consistency]
|
333
392
|
|
334
|
-
|
335
|
-
raise ::ArgumentError, ":consistency must be one of #{CONSISTENCIES.inspect}, #{consistency.inspect} given"
|
336
|
-
end
|
393
|
+
Util.assert_one_of(CONSISTENCIES, consistency) { ":consistency must be one of #{CONSISTENCIES.inspect}, #{consistency.inspect} given" }
|
337
394
|
end
|
338
395
|
|
339
396
|
if options.has_key?(:trace)
|
@@ -341,10 +398,11 @@ module Cassandra
|
|
341
398
|
end
|
342
399
|
|
343
400
|
if options.has_key?(:page_size)
|
344
|
-
page_size = options[:page_size]
|
401
|
+
page_size = options[:page_size]
|
345
402
|
|
346
|
-
|
347
|
-
|
403
|
+
unless page_size.nil?
|
404
|
+
page_size = options[:page_size] = Integer(page_size)
|
405
|
+
Util.assert(page_size > 0) { ":page_size must be a positive integer, #{page_size.inspect} given" }
|
348
406
|
end
|
349
407
|
end
|
350
408
|
|
@@ -352,11 +410,28 @@ module Cassandra
|
|
352
410
|
futures_factory = options[:futures_factory]
|
353
411
|
methods = [:error, :value, :promise, :all]
|
354
412
|
|
355
|
-
|
356
|
-
|
413
|
+
Util.assert_responds_to_all(methods, futures_factory) { ":futures_factory #{futures_factory.inspect} must respond to #{methods.inspect}, but doesn't" }
|
414
|
+
end
|
415
|
+
|
416
|
+
if options.has_key?(:address_resolution)
|
417
|
+
address_resolution = options.delete(:address_resolution)
|
418
|
+
|
419
|
+
case address_resolution
|
420
|
+
when :none
|
421
|
+
# do nothing
|
422
|
+
when :ec2_multi_region
|
423
|
+
options[:address_resolution_policy] = AddressResolution::Policies::EC2MultiRegion.new
|
424
|
+
else
|
425
|
+
raise ::ArgumentError, ":address_resolution must be either :none or :ec2_multi_region, #{address_resolution.inspect} given"
|
357
426
|
end
|
358
427
|
end
|
359
428
|
|
429
|
+
if options.has_key?(:address_resolution_policy)
|
430
|
+
address_resolver = options[:address_resolution_policy]
|
431
|
+
|
432
|
+
Util.assert_responds_to(:resolve, address_resolver) { ":address_resolution_policy must respond to :resolve, #{address_resolver.inspect} but doesn't" }
|
433
|
+
end
|
434
|
+
|
360
435
|
hosts = []
|
361
436
|
|
362
437
|
Array(options.fetch(:hosts, '127.0.0.1')).each do |host|
|
@@ -375,8 +450,20 @@ module Cassandra
|
|
375
450
|
if hosts.empty?
|
376
451
|
raise ::ArgumentError, ":hosts #{options[:hosts].inspect} could not be resolved to any ip address"
|
377
452
|
end
|
453
|
+
rescue => e
|
454
|
+
futures.error(e)
|
455
|
+
else
|
456
|
+
promise = futures.promise
|
457
|
+
|
458
|
+
Driver.new(options).connect(hosts).on_complete do |f|
|
459
|
+
if f.resolved?
|
460
|
+
promise.fulfill(f.value)
|
461
|
+
else
|
462
|
+
f.on_failure {|e| promise.break(e)}
|
463
|
+
end
|
464
|
+
end
|
378
465
|
|
379
|
-
|
466
|
+
promise.future
|
380
467
|
end
|
381
468
|
end
|
382
469
|
|
@@ -386,7 +473,7 @@ require 'cassandra/time_uuid'
|
|
386
473
|
require 'cassandra/compression'
|
387
474
|
require 'cassandra/protocol'
|
388
475
|
require 'cassandra/auth'
|
389
|
-
require 'cassandra/
|
476
|
+
require 'cassandra/null_logger'
|
390
477
|
|
391
478
|
require 'cassandra/future'
|
392
479
|
require 'cassandra/cluster'
|
@@ -408,6 +495,7 @@ require 'cassandra/execution/trace'
|
|
408
495
|
require 'cassandra/load_balancing'
|
409
496
|
require 'cassandra/reconnection'
|
410
497
|
require 'cassandra/retry'
|
498
|
+
require 'cassandra/address_resolution'
|
411
499
|
|
412
500
|
require 'cassandra/util'
|
413
501
|
|
@@ -415,8 +503,6 @@ require 'cassandra/util'
|
|
415
503
|
require 'cassandra_murmur3'
|
416
504
|
|
417
505
|
module Cassandra
|
418
|
-
# @private
|
419
|
-
Io = Ione::Io
|
420
506
|
# @private
|
421
507
|
VOID_STATEMENT = Statements::Void.new
|
422
508
|
# @private
|