cassandra-driver 3.0.0.beta.1 → 3.0.0.rc.1
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 +8 -8
- data/README.md +90 -38
- data/ext/cassandra_murmur3/cassandra_murmur3.c +1 -1
- data/lib/cassandra.rb +327 -130
- data/lib/cassandra/address_resolution.rb +1 -1
- data/lib/cassandra/address_resolution/policies/ec2_multi_region.rb +1 -1
- data/lib/cassandra/address_resolution/policies/none.rb +1 -1
- data/lib/cassandra/aggregate.rb +21 -7
- data/lib/cassandra/argument.rb +2 -2
- data/lib/cassandra/auth.rb +4 -4
- data/lib/cassandra/auth/providers.rb +1 -1
- data/lib/cassandra/auth/providers/password.rb +9 -5
- data/lib/cassandra/cassandra_logger.rb +80 -0
- data/lib/cassandra/cluster.rb +38 -9
- data/lib/cassandra/cluster/client.rb +801 -205
- data/lib/cassandra/cluster/connection_pool.rb +2 -2
- data/lib/cassandra/cluster/connector.rb +74 -25
- data/lib/cassandra/cluster/control_connection.rb +217 -82
- data/lib/cassandra/cluster/failed_connection.rb +1 -1
- data/lib/cassandra/cluster/metadata.rb +12 -4
- data/lib/cassandra/cluster/options.rb +60 -11
- data/lib/cassandra/cluster/registry.rb +69 -16
- data/lib/cassandra/cluster/schema.rb +25 -7
- data/lib/cassandra/cluster/schema/cql_type_parser.rb +15 -10
- data/lib/cassandra/cluster/schema/fetchers.rb +263 -106
- data/lib/cassandra/cluster/schema/fqcn_type_parser.rb +41 -36
- data/lib/cassandra/cluster/schema/partitioners.rb +1 -1
- data/lib/cassandra/cluster/schema/partitioners/murmur3.rb +3 -3
- data/lib/cassandra/cluster/schema/partitioners/ordered.rb +1 -1
- data/lib/cassandra/cluster/schema/partitioners/random.rb +1 -1
- data/lib/cassandra/cluster/schema/replication_strategies.rb +1 -1
- data/lib/cassandra/cluster/schema/replication_strategies/network_topology.rb +19 -18
- data/lib/cassandra/cluster/schema/replication_strategies/none.rb +1 -1
- data/lib/cassandra/cluster/schema/replication_strategies/simple.rb +1 -1
- data/lib/cassandra/column.rb +3 -3
- data/lib/cassandra/compression.rb +1 -1
- data/lib/cassandra/compression/compressors/lz4.rb +4 -3
- data/lib/cassandra/compression/compressors/snappy.rb +4 -3
- data/lib/cassandra/driver.rb +103 -41
- data/lib/cassandra/errors.rb +265 -30
- data/lib/cassandra/execution/info.rb +16 -5
- data/lib/cassandra/execution/options.rb +99 -54
- data/lib/cassandra/execution/trace.rb +16 -9
- data/lib/cassandra/executors.rb +1 -1
- data/lib/cassandra/function.rb +19 -13
- data/lib/cassandra/function_collection.rb +85 -0
- data/lib/cassandra/future.rb +106 -48
- data/lib/cassandra/host.rb +10 -4
- data/lib/cassandra/keyspace.rb +90 -33
- data/lib/cassandra/listener.rb +1 -1
- data/lib/cassandra/load_balancing.rb +2 -2
- data/lib/cassandra/load_balancing/policies.rb +1 -1
- data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +18 -18
- data/lib/cassandra/load_balancing/policies/round_robin.rb +1 -1
- data/lib/cassandra/load_balancing/policies/token_aware.rb +15 -13
- data/lib/cassandra/load_balancing/policies/white_list.rb +11 -5
- data/lib/cassandra/null_logger.rb +27 -6
- data/lib/cassandra/protocol.rb +1 -1
- data/lib/cassandra/protocol/coder.rb +78 -39
- data/lib/cassandra/protocol/cql_byte_buffer.rb +50 -33
- data/lib/cassandra/protocol/cql_protocol_handler.rb +44 -45
- data/lib/cassandra/protocol/request.rb +2 -2
- data/lib/cassandra/protocol/requests/auth_response_request.rb +3 -3
- data/lib/cassandra/protocol/requests/batch_request.rb +16 -7
- data/lib/cassandra/protocol/requests/credentials_request.rb +3 -3
- data/lib/cassandra/protocol/requests/execute_request.rb +41 -20
- data/lib/cassandra/protocol/requests/options_request.rb +1 -1
- data/lib/cassandra/protocol/requests/prepare_request.rb +5 -5
- data/lib/cassandra/protocol/requests/query_request.rb +27 -22
- data/lib/cassandra/protocol/requests/register_request.rb +2 -2
- data/lib/cassandra/protocol/requests/startup_request.rb +6 -4
- data/lib/cassandra/protocol/requests/void_query_request.rb +1 -1
- data/lib/cassandra/protocol/response.rb +2 -2
- data/lib/cassandra/protocol/responses/already_exists_error_response.rb +12 -2
- data/lib/cassandra/protocol/responses/auth_challenge_response.rb +1 -1
- data/lib/cassandra/protocol/responses/auth_success_response.rb +1 -1
- data/lib/cassandra/protocol/responses/authenticate_response.rb +1 -1
- data/lib/cassandra/protocol/responses/error_response.rb +101 -13
- data/lib/cassandra/protocol/responses/event_response.rb +1 -1
- data/lib/cassandra/protocol/responses/function_failure_error_response.rb +13 -2
- data/lib/cassandra/protocol/responses/prepared_result_response.rb +11 -5
- data/lib/cassandra/protocol/responses/raw_rows_result_response.rb +14 -9
- data/lib/cassandra/protocol/responses/read_failure_error_response.rb +26 -4
- data/lib/cassandra/protocol/responses/read_timeout_error_response.rb +22 -3
- data/lib/cassandra/protocol/responses/ready_response.rb +3 -3
- data/lib/cassandra/protocol/responses/result_response.rb +4 -2
- data/lib/cassandra/protocol/responses/rows_result_response.rb +5 -3
- data/lib/cassandra/protocol/responses/schema_change_event_response.rb +5 -4
- data/lib/cassandra/protocol/responses/schema_change_result_response.rb +16 -9
- data/lib/cassandra/protocol/responses/set_keyspace_result_response.rb +2 -2
- data/lib/cassandra/protocol/responses/status_change_event_response.rb +2 -2
- data/lib/cassandra/protocol/responses/supported_response.rb +1 -1
- data/lib/cassandra/protocol/responses/topology_change_event_response.rb +1 -1
- data/lib/cassandra/protocol/responses/unavailable_error_response.rb +20 -3
- data/lib/cassandra/protocol/responses/unprepared_error_response.rb +11 -2
- data/lib/cassandra/protocol/responses/void_result_response.rb +1 -1
- data/lib/cassandra/protocol/responses/write_failure_error_response.rb +26 -4
- data/lib/cassandra/protocol/responses/write_timeout_error_response.rb +22 -3
- data/lib/cassandra/protocol/v1.rb +101 -36
- data/lib/cassandra/protocol/v3.rb +124 -51
- data/lib/cassandra/protocol/v4.rb +172 -68
- data/lib/cassandra/reconnection.rb +1 -1
- data/lib/cassandra/reconnection/policies.rb +1 -1
- data/lib/cassandra/reconnection/policies/constant.rb +2 -4
- data/lib/cassandra/reconnection/policies/exponential.rb +6 -6
- data/lib/cassandra/result.rb +53 -19
- data/lib/cassandra/retry.rb +8 -8
- data/lib/cassandra/retry/policies.rb +1 -1
- data/lib/cassandra/retry/policies/default.rb +1 -1
- data/lib/cassandra/retry/policies/downgrading_consistency.rb +7 -3
- data/lib/cassandra/retry/policies/fallthrough.rb +1 -1
- data/lib/cassandra/session.rb +22 -16
- data/lib/cassandra/statement.rb +1 -1
- data/lib/cassandra/statements.rb +1 -1
- data/lib/cassandra/statements/batch.rb +16 -10
- data/lib/cassandra/statements/bound.rb +10 -3
- data/lib/cassandra/statements/prepared.rb +59 -15
- data/lib/cassandra/statements/simple.rb +23 -10
- data/lib/cassandra/statements/void.rb +1 -1
- data/lib/cassandra/table.rb +79 -30
- data/lib/cassandra/time.rb +11 -6
- data/lib/cassandra/time_uuid.rb +7 -7
- data/lib/cassandra/tuple.rb +16 -8
- data/lib/cassandra/types.rb +20 -9
- data/lib/cassandra/udt.rb +32 -36
- data/lib/cassandra/util.rb +20 -13
- data/lib/cassandra/uuid.rb +22 -15
- data/lib/cassandra/uuid/generator.rb +7 -5
- data/lib/cassandra/version.rb +2 -2
- data/lib/datastax/cassandra.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YTFhMzk5ZGFjZWJhYTQzZDFhYjA5ZGM3Mzk0YjY1MWMwODdjMDUyNA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NGE5OTQ1YjYyNjA1ZTVhNDI4OGQzNmJiMmFlMzJlNzRlMzNiMTkyMw==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MWZiZmZiOWNkMzFkMDM3NzE3ZTQxMzUzZWM5NjU1MjA1ODI2ODFkNDkxNzI4
|
10
|
+
YjlmNmJhZGE2OTEyNWY1ZmIyOWQwNjhlNTQyNjdiN2U2Njk3ZDYyMzNhYTg4
|
11
|
+
NmZjYjY5YmZiMDRlNTA2Njg4ZTQ2YTJlZWQ3YjVhY2MwNGE0NjA=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NDJiNzQ1ZTgzN2VkOTBmYWZjOGFmN2QwMDc4OWU3YmQxMjdlYmFjZGQ0OTM5
|
14
|
+
NDlmYmQxMDE1YjczZmNmZjg4MGRjNDY1ODRhZjNlYzBkODE2YTQ5YmM0Njlm
|
15
|
+
N2IyYjhkM2JhZmUwMjUyM2I4ODhlM2VmY2Q5YmNkZTUzZmM1ZGE=
|
data/README.md
CHANGED
@@ -12,7 +12,7 @@ the Cassandra Query Language version 3 (CQL3) and Cassandra's native protocol.
|
|
12
12
|
- Jira: https://datastax-oss.atlassian.net/browse/RUBY
|
13
13
|
- Mailing List: https://groups.google.com/a/lists.datastax.com/forum/#!forum/ruby-driver-user
|
14
14
|
- IRC: #datastax-drivers on [irc.freenode.net](http://freenode.net>)
|
15
|
-
- Twitter: Follow the latest news about DataStax Drivers - [@avalanche123](http://twitter.com/avalanche123), [@
|
15
|
+
- Twitter: Follow the latest news about DataStax Drivers - [@avalanche123](http://twitter.com/avalanche123), [@stamhankar999](http://twitter.com/stamhankar999), [@al3xandru](https://twitter.com/al3xandru)
|
16
16
|
|
17
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:
|
18
18
|
|
@@ -27,17 +27,18 @@ This driver is based on [the cql-rb gem](https://github.com/iconara/cql-rb) by [
|
|
27
27
|
|
28
28
|
[Check out the slides from Ruby Driver Explained](https://speakerdeck.com/avalanche123/ruby-driver-explained) for a detailed overview of the Ruby Driver architecture.
|
29
29
|
|
30
|
-
##
|
30
|
+
## Compatibility
|
31
31
|
|
32
32
|
This driver works exclusively with the Cassandra Query Language v3 (CQL3) and Cassandra's native protocol. The current version works with:
|
33
33
|
|
34
|
-
* Apache Cassandra versions 1.2, 2.0 and
|
35
|
-
* DataStax Enterprise
|
36
|
-
* Ruby (MRI)
|
34
|
+
* Apache Cassandra versions 1.2, 2.0, 2.1, and 3.x
|
35
|
+
* DataStax Enterprise 4.0, 4.5, 4.6, 4.7, and 4.8
|
36
|
+
* Ruby (MRI) 2.2, 2.3
|
37
37
|
* JRuby 1.7
|
38
|
-
* Rubinius 2.2
|
39
38
|
|
40
|
-
__Note__: JRuby 1.6 is not officially supported, although 1.6.8 should work.
|
39
|
+
__Note__: JRuby 1.6 is not officially supported, although 1.6.8 should work. Similarly,
|
40
|
+
MRI 2.0 and 2.1 are not officially supported, but they should work. 1.9.3 is deprecated
|
41
|
+
and is likely to break in the release following 3.0.
|
41
42
|
|
42
43
|
## Quick start
|
43
44
|
|
@@ -53,10 +54,10 @@ end
|
|
53
54
|
keyspace = 'system'
|
54
55
|
session = cluster.connect(keyspace) # create session, optionally scoped to a keyspace, to execute queries
|
55
56
|
|
56
|
-
future = session.execute_async('SELECT keyspace_name,
|
57
|
+
future = session.execute_async('SELECT keyspace_name, table_name FROM system_schema.tables') # fully asynchronous api
|
57
58
|
future.on_success do |rows|
|
58
59
|
rows.each do |row|
|
59
|
-
puts "The keyspace #{row['keyspace_name']} has a table called #{row['
|
60
|
+
puts "The keyspace #{row['keyspace_name']} has a table called #{row['table_name']}"
|
60
61
|
end
|
61
62
|
end
|
62
63
|
future.join
|
@@ -91,31 +92,64 @@ __Note__: if you want to use compression you should also install [snappy](http:/
|
|
91
92
|
|
92
93
|
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.
|
93
94
|
|
94
|
-
## What's new in
|
95
|
-
|
96
|
-
Features:
|
95
|
+
## What's new in v3.0.0
|
96
|
+
|
97
|
+
### Features:
|
98
|
+
|
99
|
+
* Apache Cassandra native protocol v4
|
100
|
+
* Add support for smallint, tinyint, date (Cassandra::Date) and time (Cassandra::Time) data types.
|
101
|
+
* Include schema metadata for User Defined Functions and User Defined Aggregates.
|
102
|
+
* Include client ip addresses in request traces, only on Cassandra 3.x.
|
103
|
+
* Add new retry policy decision Cassandra::Retry::Policy#try_next_host.
|
104
|
+
* Support specifying statement idempotence with the new :idempotent option when executing.
|
105
|
+
* Support sending custom payloads when preparing or executing statements using the new :payload option.
|
106
|
+
* Expose custom payloads received with responses on server exceptions and Cassandra::Execution::Info instances.
|
107
|
+
* Expose server warnings on server exceptions and Cassandra::Execution::Info instances.
|
108
|
+
* Add connections_per_local_node, connections_per_remote_node, requests_per_connection cluster configuration options to tune parallel query execution and resource usage.
|
109
|
+
* Add Cassandra::Logger class to make it easy for users to enable debug logging in the client.
|
110
|
+
|
111
|
+
### Breaking Changes:
|
112
|
+
|
113
|
+
* Cassandra::Future#join is now an alias to Cassandra::Future#get and will raise an error if the future is resolved with one.
|
114
|
+
* Default consistency level is now LOCAL_ONE.
|
115
|
+
* Enable tcp no-delay by default.
|
116
|
+
* Unavailable errors are retried on the next host in the load balancing plan by default.
|
117
|
+
* Statement execution no longer retried on timeouts, unless :idempotent => true has been specified when executing.
|
118
|
+
* Cassandra::Statements::Batch#add signature has changed in how one specifies query parameters. Specify the query parameters array as the value of the arguments key:
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
batch.add(query, ['val1', 'val2'])
|
122
|
+
# becomes
|
123
|
+
batch.add(query, arguments: ['val1', 'val2'])
|
97
124
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
* [Public types api for type definition and introspection](http://datastax.github.io/ruby-driver/api/types/)
|
125
|
+
batch.add(query, {p1: 'val1'})
|
126
|
+
# becomes
|
127
|
+
batch.add(query, arguments: {p1: 'val1'})
|
128
|
+
```
|
103
129
|
|
104
|
-
|
130
|
+
### Bug Fixes:
|
105
131
|
|
106
|
-
*
|
132
|
+
* [[RUBY-120](https://datastax-oss.atlassian.net/browse/RUBY-120)] Tuples and UDTs can be used in sets and hash keys.
|
133
|
+
* [[RUBY-143](https://datastax-oss.atlassian.net/browse/RUBY-143)] Retry querying system table for metadata of new hosts when prior attempts fail, ultimately enabling use of new hosts.
|
134
|
+
* [[RUBY-150](https://datastax-oss.atlassian.net/browse/RUBY-150)] Fixed a protocol decoding error that occurred when multiple messages are available in a stream.
|
135
|
+
* [[RUBY-151](https://datastax-oss.atlassian.net/browse/RUBY-151)] Decode incomplete UDTs properly.
|
107
136
|
|
108
|
-
|
137
|
+
## Feedback Requested
|
109
138
|
|
110
|
-
* [
|
139
|
+
*Help us focus our efforts!* [Provide your input](http://goo.gl/forms/pCs8PTpHLf)
|
140
|
+
on the Ruby Driver Platform and Runtime Survey (we kept it short).
|
111
141
|
|
112
142
|
## Code examples
|
113
143
|
|
114
|
-
The DataStax Ruby Driver uses the awesome [Cucumber Framework](http://cukes.info/) for
|
144
|
+
The DataStax Ruby Driver uses the awesome [Cucumber Framework](http://cukes.info/) for
|
145
|
+
both end-to-end, or acceptance, testing and constructing documentation. All of the
|
146
|
+
features supported by the driver have appropriate acceptance tests with easy-to-copy code
|
147
|
+
examples in the `features/` directory.
|
115
148
|
|
116
149
|
## Running tests
|
117
150
|
|
118
|
-
If you don't feel like reading through the following instructions on how to run
|
151
|
+
If you don't feel like reading through the following instructions on how to run
|
152
|
+
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).
|
119
153
|
|
120
154
|
* Check out the driver codebase and install test dependencies:
|
121
155
|
|
@@ -127,26 +161,37 @@ bundle install --without docs
|
|
127
161
|
|
128
162
|
* [Install ccm](http://www.datastax.com/dev/blog/ccm-a-development-tool-for-creating-local-cassandra-clusters)
|
129
163
|
|
130
|
-
* Run tests:
|
164
|
+
* Run tests against different versions of Cassandra:
|
131
165
|
|
132
166
|
```bash
|
133
|
-
bundle exec cucumber # runs end-to-end tests (or bundle exec rake cucumber)
|
134
|
-
bundle exec rspec # runs unit tests (or bundle exec rake rspec)
|
135
|
-
bundle exec rake integration # run integration tests
|
136
|
-
bundle exec rake test # run both as well as integration tests
|
167
|
+
CASSANDRA_VERSION=3.1.1 bundle exec cucumber # runs end-to-end tests (or bundle exec rake cucumber)
|
168
|
+
CASSANDRA_VERSION=3.0.0 bundle exec rspec # runs unit tests (or bundle exec rake rspec)
|
169
|
+
CASSANDRA_VERSION=2.1.12 bundle exec rake integration # run integration tests
|
170
|
+
CASSANDRA_VERSION=2.0.17 bundle exec rake test # run both as well as integration tests
|
137
171
|
```
|
138
172
|
|
139
173
|
## Changelog & versioning
|
140
174
|
|
141
|
-
Check out the [releases on GitHub](https://github.com/datastax/ruby-driver/releases) and
|
175
|
+
Check out the [releases on GitHub](https://github.com/datastax/ruby-driver/releases) and
|
176
|
+
[changelog](https://github.com/datastax/ruby-driver/blob/master/CHANGELOG.md). Version
|
177
|
+
numbering follows the [semantic versioning](http://semver.org/) scheme.
|
142
178
|
|
143
|
-
Private and experimental APIs, defined as whatever is not in the
|
179
|
+
Private and experimental APIs, defined as whatever is not in the
|
180
|
+
[public API documentation][1], i.e. classes and methods marked as `@private`, will change
|
181
|
+
without warning. If you've been recommended to try an experimental API by the maintainers,
|
182
|
+
please let them know if you depend on that API. Experimental APIs will eventually become
|
183
|
+
public, and knowing how they are used helps in determining their maturity.
|
144
184
|
|
145
|
-
Prereleases will be stable, in the sense that they will have finished and properly tested
|
185
|
+
Prereleases will be stable, in the sense that they will have finished and properly tested
|
186
|
+
features only, but may introduce APIs that will change before the final release. Please
|
187
|
+
use the prereleases and report bugs, but don't deploy them to production without
|
188
|
+
consulting the maintainers, or doing extensive testing yourself. If you do deploy to
|
189
|
+
production please let the maintainers know as this helps in determining the maturity of
|
190
|
+
the release.
|
146
191
|
|
147
192
|
## Known bugs & limitations
|
148
193
|
|
149
|
-
* JRuby 1.6 is not officially supported, although 1.6.8 should work
|
194
|
+
* JRuby 1.6 is not officially supported, although 1.6.8 should work.
|
150
195
|
* Because the driver reactor is using `IO.select`, the maximum number of tcp connections allowed is 1024.
|
151
196
|
* Because the driver uses `IO#write_nonblock`, Windows is not supported.
|
152
197
|
|
@@ -158,19 +203,26 @@ For contributing read [CONTRIBUTING.md](https://github.com/datastax/ruby-driver/
|
|
158
203
|
|
159
204
|
## Credits
|
160
205
|
|
161
|
-
This driver is based on the original work of [Theo Hultberg](https://github.com/iconara)
|
162
|
-
|
163
|
-
|
206
|
+
This driver is based on the original work of [Theo Hultberg](https://github.com/iconara)
|
207
|
+
on [cql-rb](https://github.com/iconara/cql-rb/) and adds a series of advanced features
|
208
|
+
that are common across all other DataStax drivers for Apache Cassandra.
|
164
209
|
|
210
|
+
The development effort to provide an up to date, high performance, fully featured Ruby
|
211
|
+
Driver for Apache Cassandra will continue on this project, while
|
212
|
+
[cql-rb](https://github.com/iconara/cql-rb/) will be discontinued.
|
165
213
|
|
166
214
|
## Copyright
|
167
215
|
|
168
|
-
Copyright 2013-
|
216
|
+
Copyright 2013-2016 DataStax, Inc.
|
169
217
|
|
170
|
-
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
|
218
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
|
219
|
+
except in compliance with the License. You may obtain a copy of the License at
|
171
220
|
|
172
221
|
[http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
173
222
|
|
174
|
-
Unless required by applicable law or agreed to in writing, software distributed under the
|
223
|
+
Unless required by applicable law or agreed to in writing, software distributed under the
|
224
|
+
License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
225
|
+
either express or implied. See the License for the specific language governing permissions
|
226
|
+
and limitations under the License.
|
175
227
|
|
176
228
|
[1]: http://datastax.github.io/ruby-driver/api
|
data/lib/cassandra.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
#--
|
4
|
-
# Copyright 2013-
|
4
|
+
# Copyright 2013-2016 DataStax, Inc.
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
7
|
# you may not use this file except in compliance with the License.
|
@@ -16,7 +16,6 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#++
|
18
18
|
|
19
|
-
|
20
19
|
require 'ione'
|
21
20
|
require 'json'
|
22
21
|
|
@@ -38,8 +37,8 @@ module Cassandra
|
|
38
37
|
# @see http://www.datastax.com/documentation/cassandra/2.0/cassandra/dml/dml_config_consistency_c.html Consistency levels in Apache Cassandra 2.0
|
39
38
|
# @see http://www.datastax.com/documentation/cassandra/1.2/cassandra/dml/dml_config_consistency_c.html Consistency levels in Apache Cassandra 1.2
|
40
39
|
# @see Cassandra::Session#execute_async
|
41
|
-
CONSISTENCIES = [
|
42
|
-
|
40
|
+
CONSISTENCIES = [:any, :one, :two, :three, :quorum, :all, :local_quorum,
|
41
|
+
:each_quorum, :serial, :local_serial, :local_one].freeze
|
43
42
|
|
44
43
|
# A list of all supported serial consistencies
|
45
44
|
# @see Cassandra::Session#execute_async
|
@@ -126,6 +125,22 @@ module Cassandra
|
|
126
125
|
# address resolver to use. Must be one of `:none` or
|
127
126
|
# `:ec2_multi_region`.
|
128
127
|
#
|
128
|
+
# @option options [Integer] :connections_per_local_node (nil) Number of connections to
|
129
|
+
# open to each local node; the value of this option directly correlates to the number
|
130
|
+
# of requests the client can make to the local node concurrently. When `nil`, the
|
131
|
+
# setting is `1` for nodes that use the v3 or later protocol, and `2` for nodes that
|
132
|
+
# use the v2 or earlier protocol.
|
133
|
+
#
|
134
|
+
# @option options [Integer] :connections_per_remote_node (1) Number of connections to
|
135
|
+
# open to each remote node; the value of this option directly correlates to the
|
136
|
+
# number of requests the client can make to the remote node concurrently.
|
137
|
+
#
|
138
|
+
# @option options [Integer] :requests_per_connection (nil) Number of outstanding
|
139
|
+
# requests to support on one connection. Depending on the types of requests, some may
|
140
|
+
# get processed in parallel in the Cassandra node. When `nil`, the setting is `1024`
|
141
|
+
# for nodes that use the v3 or later protocol, and `128` for nodes that use the
|
142
|
+
# v2 or earlier protocol.
|
143
|
+
#
|
129
144
|
# @option options [Boolean] :client_timestamps (false) whether the driver
|
130
145
|
# should send timestamps for each executed statement. Enabling this setting
|
131
146
|
# allows mitigating Cassandra cluster clock skew because the timestamp of
|
@@ -139,7 +154,8 @@ module Cassandra
|
|
139
154
|
# automatic schema updates. Schema metadata is used by the driver to
|
140
155
|
# determine cluster partitioners as well as to find partition keys and
|
141
156
|
# replicas of prepared statements, this information makes token aware load
|
142
|
-
# balancing possible. One can still
|
157
|
+
# balancing possible. One can still
|
158
|
+
# {Cassandra::Cluster#refresh_schema refresh schema manually}.
|
143
159
|
#
|
144
160
|
# @option options [Numeric] :schema_refresh_delay (1) the driver will wait
|
145
161
|
# for `:schema_refresh_delay` before fetching metadata after receiving a
|
@@ -177,9 +193,15 @@ module Cassandra
|
|
177
193
|
# @option options [Integer] :page_size (10000) default page size for all
|
178
194
|
# select queries. Set this value to `nil` to disable paging.
|
179
195
|
#
|
180
|
-
# @option options [Hash{String => String}] :credentials (none) a hash of credentials -
|
196
|
+
# @option options [Hash{String => String}] :credentials (none) a hash of credentials -
|
197
|
+
# to be used with [credentials authentication in cassandra 1.2](https://github.com/apache/cassandra/blob/cassandra-2.0.16/doc/native_protocol_v1.spec#L238-L250).
|
198
|
+
# Note that if you specified `:username` and `:password` options, those credentials
|
199
|
+
# are configured automatically.
|
181
200
|
#
|
182
|
-
# @option options [Cassandra::Auth::Provider] :auth_provider (none) a custom auth
|
201
|
+
# @option options [Cassandra::Auth::Provider] :auth_provider (none) a custom auth
|
202
|
+
# provider to be used with [SASL authentication in cassandra 2.0](https://github.com/apache/cassandra/blob/cassandra-2.0.16/doc/native_protocol_v2.spec#L257-L273).
|
203
|
+
# Note that if you have specified `:username` and `:password`, then a
|
204
|
+
# {Cassandra::Auth::Providers::Password Password Provider} will be used automatically.
|
183
205
|
#
|
184
206
|
# @option options [Cassandra::Compression::Compressor] :compressor (none) a
|
185
207
|
# custom compressor. Note that if you have specified `:compression`, an
|
@@ -187,8 +209,8 @@ module Cassandra
|
|
187
209
|
#
|
188
210
|
# @option options [Cassandra::AddressResolution::Policy]
|
189
211
|
# :address_resolution_policy default:
|
190
|
-
# {Cassandra::AddressResolution::Policies::None No Resolution Policy} a custom address
|
191
|
-
# policy. Note that if you have specified `:address_resolution`, an
|
212
|
+
# {Cassandra::AddressResolution::Policies::None No Resolution Policy} a custom address
|
213
|
+
# resolution policy. Note that if you have specified `:address_resolution`, an
|
192
214
|
# appropriate address resolution policy will be provided automatically.
|
193
215
|
#
|
194
216
|
# @option options [Object<#all, #error, #value, #promise>] :futures_factory
|
@@ -219,78 +241,176 @@ module Cassandra
|
|
219
241
|
# @return [Cassandra::Future<Cassandra::Cluster>] a future resolving to the
|
220
242
|
# cluster instance.
|
221
243
|
def self.cluster_async(options = {})
|
222
|
-
options = options
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
244
|
+
options = validate_and_massage_options(options)
|
245
|
+
hosts = []
|
246
|
+
|
247
|
+
Array(options.fetch(:hosts, '127.0.0.1')).each do |host|
|
248
|
+
case host
|
249
|
+
when ::IPAddr
|
250
|
+
hosts << host
|
251
|
+
when ::String # ip address or hostname
|
252
|
+
Resolv.each_address(host) do |ip|
|
253
|
+
hosts << ::IPAddr.new(ip)
|
254
|
+
end
|
255
|
+
else
|
256
|
+
raise ::ArgumentError, ":hosts must be String or IPAddr, #{host.inspect} given"
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
if hosts.empty?
|
261
|
+
raise ::ArgumentError,
|
262
|
+
":hosts #{options[:hosts].inspect} could not be resolved to any ip address"
|
263
|
+
end
|
264
|
+
|
265
|
+
hosts.shuffle!
|
266
|
+
rescue => e
|
267
|
+
futures = options.fetch(:futures_factory) { return Future::Error.new(e) }
|
268
|
+
futures.error(e)
|
269
|
+
else
|
270
|
+
driver = Driver.new(options)
|
271
|
+
driver.connect(hosts)
|
272
|
+
end
|
273
|
+
|
274
|
+
# @private
|
275
|
+
SSL_CLASSES = [::TrueClass, ::FalseClass, ::OpenSSL::SSL::SSLContext].freeze
|
276
|
+
|
277
|
+
# @private
|
278
|
+
def self.validate_and_massage_options(options)
|
279
|
+
options = options.select do |key, _|
|
280
|
+
[
|
281
|
+
:address_resolution,
|
282
|
+
:address_resolution_policy,
|
283
|
+
:auth_provider,
|
284
|
+
:client_cert,
|
285
|
+
:client_timestamps,
|
286
|
+
:compression,
|
287
|
+
:compressor,
|
288
|
+
:connect_timeout,
|
289
|
+
:connections_per_local_node,
|
290
|
+
:connections_per_remote_node,
|
291
|
+
:consistency,
|
292
|
+
:credentials,
|
293
|
+
:datacenter,
|
294
|
+
:futures_factory,
|
295
|
+
:heartbeat_interval,
|
296
|
+
:hosts,
|
297
|
+
:idle_timeout,
|
298
|
+
:listeners,
|
299
|
+
:load_balancing_policy,
|
300
|
+
:logger,
|
301
|
+
:nodelay,
|
302
|
+
:reconnection_policy,
|
303
|
+
:retry_policy,
|
304
|
+
:page_size,
|
305
|
+
:passphrase,
|
306
|
+
:password,
|
307
|
+
:port,
|
308
|
+
:private_key,
|
309
|
+
:requests_per_connection,
|
310
|
+
:schema_refresh_delay,
|
311
|
+
:schema_refresh_timeout,
|
312
|
+
:server_cert,
|
313
|
+
:shuffle_replicas,
|
314
|
+
:ssl,
|
315
|
+
:synchronize_schema,
|
316
|
+
:timeout,
|
317
|
+
:trace,
|
318
|
+
:username
|
231
319
|
].include?(key)
|
232
320
|
end
|
233
321
|
|
234
|
-
has_username = options.
|
235
|
-
has_password = options.
|
322
|
+
has_username = options.key?(:username)
|
323
|
+
has_password = options.key?(:password)
|
236
324
|
if has_username || has_password
|
237
325
|
if has_username && !has_password
|
238
|
-
raise ::ArgumentError,
|
326
|
+
raise ::ArgumentError,
|
327
|
+
'both :username and :password options must be specified, ' \
|
328
|
+
'but only :username given'
|
239
329
|
end
|
240
330
|
|
241
331
|
if !has_username && has_password
|
242
|
-
raise ::ArgumentError,
|
332
|
+
raise ::ArgumentError,
|
333
|
+
'both :username and :password options must be specified, ' \
|
334
|
+
'but only :password given'
|
243
335
|
end
|
244
336
|
|
245
337
|
username = options.delete(:username)
|
246
338
|
password = options.delete(:password)
|
247
339
|
|
248
|
-
Util.assert_instance_of(::String, username)
|
249
|
-
|
250
|
-
|
251
|
-
Util.
|
340
|
+
Util.assert_instance_of(::String, username) do
|
341
|
+
":username must be a String, #{username.inspect} given"
|
342
|
+
end
|
343
|
+
Util.assert_instance_of(::String, password) do
|
344
|
+
":password must be a String, #{password.inspect} given"
|
345
|
+
end
|
346
|
+
Util.assert_not_empty(username) { ':username cannot be empty' }
|
347
|
+
Util.assert_not_empty(password) { ':password cannot be empty' }
|
252
348
|
|
253
|
-
options[:credentials] = {:
|
349
|
+
options[:credentials] = {username: username, password: password}
|
254
350
|
options[:auth_provider] = Auth::Providers::Password.new(username, password)
|
255
351
|
end
|
256
352
|
|
257
|
-
if options.
|
353
|
+
if options.key?(:credentials)
|
258
354
|
credentials = options[:credentials]
|
259
355
|
|
260
|
-
Util.assert_instance_of(::Hash, credentials)
|
356
|
+
Util.assert_instance_of(::Hash, credentials) do
|
357
|
+
":credentials must be a hash, #{credentials.inspect} given"
|
358
|
+
end
|
261
359
|
end
|
262
360
|
|
263
|
-
if options.
|
361
|
+
if options.key?(:auth_provider)
|
264
362
|
auth_provider = options[:auth_provider]
|
265
363
|
|
266
|
-
Util.assert_responds_to(:create_authenticator, auth_provider)
|
364
|
+
Util.assert_responds_to(:create_authenticator, auth_provider) do
|
365
|
+
":auth_provider #{auth_provider.inspect} must respond to " \
|
366
|
+
":create_authenticator, but doesn't"
|
367
|
+
end
|
267
368
|
end
|
268
369
|
|
269
|
-
has_client_cert = options.
|
270
|
-
has_private_key = options.
|
370
|
+
has_client_cert = options.key?(:client_cert)
|
371
|
+
has_private_key = options.key?(:private_key)
|
271
372
|
|
272
373
|
if has_client_cert || has_private_key
|
273
374
|
if has_client_cert && !has_private_key
|
274
|
-
raise ::ArgumentError,
|
375
|
+
raise ::ArgumentError,
|
376
|
+
'both :client_cert and :private_key options must be specified, ' \
|
377
|
+
'but only :client_cert given'
|
275
378
|
end
|
276
379
|
|
277
380
|
if !has_client_cert && has_private_key
|
278
|
-
raise ::ArgumentError,
|
381
|
+
raise ::ArgumentError,
|
382
|
+
'both :client_cert and :private_key options must be specified, ' \
|
383
|
+
'but only :private_key given'
|
279
384
|
end
|
280
385
|
|
386
|
+
Util.assert_instance_of(::String, options[:client_cert]) do
|
387
|
+
":client_cert must be a string, #{options[:client_cert].inspect} given"
|
388
|
+
end
|
389
|
+
Util.assert_instance_of(::String, options[:private_key]) do
|
390
|
+
":client_cert must be a string, #{options[:private_key].inspect} given"
|
391
|
+
end
|
281
392
|
client_cert = ::File.expand_path(options[:client_cert])
|
282
393
|
private_key = ::File.expand_path(options[:private_key])
|
283
394
|
|
284
|
-
Util.assert_file_exists(client_cert)
|
285
|
-
|
395
|
+
Util.assert_file_exists(client_cert) do
|
396
|
+
":client_cert #{client_cert.inspect} doesn't exist"
|
397
|
+
end
|
398
|
+
Util.assert_file_exists(private_key) do
|
399
|
+
":private_key #{private_key.inspect} doesn't exist"
|
400
|
+
end
|
286
401
|
end
|
287
402
|
|
288
|
-
has_server_cert = options.
|
403
|
+
has_server_cert = options.key?(:server_cert)
|
289
404
|
|
290
405
|
if has_server_cert
|
406
|
+
Util.assert_instance_of(::String, options[:server_cert]) do
|
407
|
+
":server_cert must be a string, #{options[:server_cert].inspect} given"
|
408
|
+
end
|
291
409
|
server_cert = ::File.expand_path(options[:server_cert])
|
292
410
|
|
293
|
-
Util.assert_file_exists(server_cert)
|
411
|
+
Util.assert_file_exists(server_cert) do
|
412
|
+
":server_cert #{server_cert.inspect} doesn't exist"
|
413
|
+
end
|
294
414
|
end
|
295
415
|
|
296
416
|
if has_client_cert || has_server_cert
|
@@ -304,23 +424,26 @@ module Cassandra
|
|
304
424
|
if has_client_cert
|
305
425
|
context.cert = ::OpenSSL::X509::Certificate.new(File.read(client_cert))
|
306
426
|
|
307
|
-
if options.
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
427
|
+
context.key = if options.key?(:passphrase)
|
428
|
+
::OpenSSL::PKey::RSA.new(File.read(private_key),
|
429
|
+
options[:passphrase])
|
430
|
+
else
|
431
|
+
::OpenSSL::PKey::RSA.new(File.read(private_key))
|
432
|
+
end
|
312
433
|
end
|
313
434
|
|
314
435
|
options[:ssl] = context
|
315
436
|
end
|
316
437
|
|
317
|
-
if options.
|
438
|
+
if options.key?(:ssl)
|
318
439
|
ssl = options[:ssl]
|
319
440
|
|
320
|
-
Util.assert_instance_of_one_of(
|
441
|
+
Util.assert_instance_of_one_of(SSL_CLASSES, ssl) do
|
442
|
+
":ssl must be a boolean or an OpenSSL::SSL::SSLContext, #{ssl.inspect} given"
|
443
|
+
end
|
321
444
|
end
|
322
445
|
|
323
|
-
if options.
|
446
|
+
if options.key?(:compression)
|
324
447
|
compression = options.delete(:compression)
|
325
448
|
|
326
449
|
case compression
|
@@ -329,195 +452,267 @@ module Cassandra
|
|
329
452
|
when :lz4
|
330
453
|
options[:compressor] = Compression::Compressors::Lz4.new
|
331
454
|
else
|
332
|
-
raise ::ArgumentError,
|
455
|
+
raise ::ArgumentError,
|
456
|
+
":compression must be either :snappy or :lz4, #{compression.inspect} given"
|
333
457
|
end
|
334
458
|
end
|
335
459
|
|
336
|
-
if options.
|
460
|
+
if options.key?(:compressor)
|
337
461
|
compressor = options[:compressor]
|
338
462
|
methods = [:algorithm, :compress?, :compress, :decompress]
|
339
463
|
|
340
|
-
Util.assert_responds_to_all(methods, compressor)
|
464
|
+
Util.assert_responds_to_all(methods, compressor) do
|
465
|
+
":compressor #{compressor.inspect} must respond to #{methods.inspect}, " \
|
466
|
+
"but doesn't"
|
467
|
+
end
|
341
468
|
end
|
342
469
|
|
343
|
-
if options.
|
344
|
-
|
345
|
-
|
470
|
+
if options.key?(:logger)
|
471
|
+
if options[:logger].nil?
|
472
|
+
# Delete the key because we want to fallback to the default logger in Driver.
|
473
|
+
options.delete(:logger)
|
474
|
+
else
|
475
|
+
# Validate
|
476
|
+
logger = options[:logger]
|
477
|
+
methods = [:debug, :info, :warn, :error, :fatal]
|
346
478
|
|
347
|
-
|
479
|
+
Util.assert_responds_to_all(methods, logger) do
|
480
|
+
":logger #{logger.inspect} must respond to #{methods.inspect}, but doesn't"
|
481
|
+
end
|
482
|
+
end
|
348
483
|
end
|
349
484
|
|
350
|
-
if options.
|
351
|
-
|
352
|
-
|
353
|
-
|
485
|
+
if options.key?(:port)
|
486
|
+
unless options[:port].nil?
|
487
|
+
port = options[:port]
|
488
|
+
Util.assert_instance_of(::Integer, port)
|
489
|
+
Util.assert_one_of(1...2**16, port) do
|
490
|
+
":port must be a valid ip port, #{port} given"
|
491
|
+
end
|
492
|
+
end
|
354
493
|
end
|
355
494
|
|
356
|
-
if options.
|
357
|
-
options[:datacenter] = String(options[:datacenter])
|
358
|
-
end
|
495
|
+
options[:datacenter] = String(options[:datacenter]) if options.key?(:datacenter)
|
359
496
|
|
360
|
-
if options.
|
497
|
+
if options.key?(:connect_timeout)
|
361
498
|
timeout = options[:connect_timeout]
|
362
499
|
|
363
500
|
unless timeout.nil?
|
364
|
-
Util.assert_instance_of(::Numeric, timeout)
|
365
|
-
|
501
|
+
Util.assert_instance_of(::Numeric, timeout) do
|
502
|
+
":connect_timeout must be a number of seconds, #{timeout.inspect} given"
|
503
|
+
end
|
504
|
+
Util.assert(timeout > 0) do
|
505
|
+
":connect_timeout must be greater than 0, #{timeout} given"
|
506
|
+
end
|
366
507
|
end
|
367
508
|
end
|
368
509
|
|
369
|
-
if options.
|
510
|
+
if options.key?(:timeout)
|
370
511
|
timeout = options[:timeout]
|
371
512
|
|
372
513
|
unless timeout.nil?
|
373
|
-
Util.assert_instance_of(::Numeric, timeout)
|
514
|
+
Util.assert_instance_of(::Numeric, timeout) do
|
515
|
+
":timeout must be a number of seconds, #{timeout.inspect} given"
|
516
|
+
end
|
374
517
|
Util.assert(timeout > 0) { ":timeout must be greater than 0, #{timeout} given" }
|
375
518
|
end
|
376
519
|
end
|
377
520
|
|
378
|
-
if options.
|
521
|
+
if options.key?(:heartbeat_interval)
|
379
522
|
timeout = options[:heartbeat_interval]
|
380
523
|
|
381
524
|
unless timeout.nil?
|
382
|
-
Util.assert_instance_of(::Numeric, timeout)
|
383
|
-
|
525
|
+
Util.assert_instance_of(::Numeric, timeout) do
|
526
|
+
":heartbeat_interval must be a number of seconds, #{timeout.inspect} given"
|
527
|
+
end
|
528
|
+
Util.assert(timeout > 0) do
|
529
|
+
":heartbeat_interval must be greater than 0, #{timeout} given"
|
530
|
+
end
|
384
531
|
end
|
385
532
|
end
|
386
533
|
|
387
|
-
if options.
|
534
|
+
if options.key?(:idle_timeout)
|
388
535
|
timeout = options[:idle_timeout]
|
389
536
|
|
390
537
|
unless timeout.nil?
|
391
|
-
Util.assert_instance_of(::Numeric, timeout)
|
392
|
-
|
538
|
+
Util.assert_instance_of(::Numeric, timeout) do
|
539
|
+
":idle_timeout must be a number of seconds, #{timeout.inspect} given"
|
540
|
+
end
|
541
|
+
Util.assert(timeout > 0) do
|
542
|
+
":idle_timeout must be greater than 0, #{timeout} given"
|
543
|
+
end
|
393
544
|
end
|
394
545
|
end
|
395
546
|
|
396
|
-
if options.
|
547
|
+
if options.key?(:schema_refresh_delay)
|
397
548
|
timeout = options[:schema_refresh_delay]
|
398
549
|
|
399
|
-
Util.assert_instance_of(::Numeric, timeout)
|
400
|
-
|
550
|
+
Util.assert_instance_of(::Numeric, timeout) do
|
551
|
+
":schema_refresh_delay must be a number of seconds, #{timeout.inspect} given"
|
552
|
+
end
|
553
|
+
Util.assert(timeout > 0) do
|
554
|
+
":schema_refresh_delay must be greater than 0, #{timeout} given"
|
555
|
+
end
|
401
556
|
end
|
402
557
|
|
403
|
-
if options.
|
558
|
+
if options.key?(:schema_refresh_timeout)
|
404
559
|
timeout = options[:schema_refresh_timeout]
|
405
560
|
|
406
|
-
Util.assert_instance_of(::Numeric, timeout)
|
407
|
-
|
561
|
+
Util.assert_instance_of(::Numeric, timeout) do
|
562
|
+
":schema_refresh_timeout must be a number of seconds, #{timeout.inspect} given"
|
563
|
+
end
|
564
|
+
Util.assert(timeout > 0) do
|
565
|
+
":schema_refresh_timeout must be greater than 0, #{timeout} given"
|
566
|
+
end
|
408
567
|
end
|
409
568
|
|
410
|
-
if options.
|
569
|
+
if options.key?(:load_balancing_policy)
|
411
570
|
load_balancing_policy = options[:load_balancing_policy]
|
412
|
-
methods = [:host_up, :host_down, :host_found, :host_lost, :setup, :teardown,
|
571
|
+
methods = [:host_up, :host_down, :host_found, :host_lost, :setup, :teardown,
|
572
|
+
:distance, :plan]
|
413
573
|
|
414
|
-
Util.assert_responds_to_all(methods, load_balancing_policy)
|
574
|
+
Util.assert_responds_to_all(methods, load_balancing_policy) do
|
575
|
+
":load_balancing_policy #{load_balancing_policy.inspect} must respond " \
|
576
|
+
"to #{methods.inspect}, but doesn't"
|
577
|
+
end
|
415
578
|
end
|
416
579
|
|
417
|
-
if options.
|
580
|
+
if options.key?(:reconnection_policy)
|
418
581
|
reconnection_policy = options[:reconnection_policy]
|
419
582
|
|
420
|
-
Util.assert_responds_to(:schedule, reconnection_policy)
|
583
|
+
Util.assert_responds_to(:schedule, reconnection_policy) do
|
584
|
+
":reconnection_policy #{reconnection_policy.inspect} must respond to " \
|
585
|
+
":schedule, but doesn't"
|
586
|
+
end
|
421
587
|
end
|
422
588
|
|
423
|
-
if options.
|
589
|
+
if options.key?(:retry_policy)
|
424
590
|
retry_policy = options[:retry_policy]
|
425
591
|
methods = [:read_timeout, :write_timeout, :unavailable]
|
426
592
|
|
427
|
-
Util.assert_responds_to_all(methods, retry_policy)
|
593
|
+
Util.assert_responds_to_all(methods, retry_policy) do
|
594
|
+
":retry_policy #{retry_policy.inspect} must respond to #{methods.inspect}, " \
|
595
|
+
"but doesn't"
|
596
|
+
end
|
428
597
|
end
|
429
598
|
|
430
|
-
if options.
|
431
|
-
options[:listeners] = Array(options[:listeners])
|
432
|
-
end
|
599
|
+
options[:listeners] = Array(options[:listeners]) if options.key?(:listeners)
|
433
600
|
|
434
|
-
if options.
|
601
|
+
if options.key?(:consistency)
|
435
602
|
consistency = options[:consistency]
|
436
603
|
|
437
|
-
Util.assert_one_of(CONSISTENCIES, consistency)
|
604
|
+
Util.assert_one_of(CONSISTENCIES, consistency) do
|
605
|
+
":consistency must be one of #{CONSISTENCIES.inspect}, " \
|
606
|
+
"#{consistency.inspect} given"
|
607
|
+
end
|
438
608
|
end
|
439
609
|
|
440
|
-
if options.
|
441
|
-
options[:nodelay] = !!options[:nodelay]
|
442
|
-
end
|
610
|
+
options[:nodelay] = !!options[:nodelay] if options.key?(:nodelay)
|
443
611
|
|
444
|
-
if options.
|
445
|
-
options[:trace] = !!options[:trace]
|
446
|
-
end
|
612
|
+
options[:trace] = !!options[:trace] if options.key?(:trace)
|
447
613
|
|
448
|
-
if options.
|
614
|
+
if options.key?(:shuffle_replicas)
|
449
615
|
options[:shuffle_replicas] = !!options[:shuffle_replicas]
|
450
616
|
end
|
451
617
|
|
452
|
-
if options.
|
618
|
+
if options.key?(:page_size)
|
453
619
|
page_size = options[:page_size]
|
454
620
|
|
455
621
|
unless page_size.nil?
|
456
|
-
page_size = options[:page_size]
|
457
|
-
Util.
|
622
|
+
page_size = options[:page_size]
|
623
|
+
Util.assert_instance_of(::Integer, page_size)
|
624
|
+
Util.assert_one_of(1...2**32, page_size) do
|
625
|
+
":page_size must be a positive integer, #{page_size.inspect} given"
|
626
|
+
end
|
458
627
|
end
|
459
628
|
end
|
460
629
|
|
461
|
-
if options.
|
630
|
+
if options.key?(:futures_factory)
|
462
631
|
futures_factory = options[:futures_factory]
|
463
632
|
methods = [:error, :value, :promise, :all]
|
464
633
|
|
465
|
-
Util.assert_responds_to_all(methods, futures_factory)
|
634
|
+
Util.assert_responds_to_all(methods, futures_factory) do
|
635
|
+
":futures_factory #{futures_factory.inspect} must respond to " \
|
636
|
+
"#{methods.inspect}, but doesn't"
|
637
|
+
end
|
466
638
|
end
|
467
639
|
|
468
|
-
if options.
|
640
|
+
if options.key?(:address_resolution)
|
469
641
|
address_resolution = options.delete(:address_resolution)
|
470
642
|
|
471
643
|
case address_resolution
|
472
644
|
when :none
|
473
645
|
# do nothing
|
474
646
|
when :ec2_multi_region
|
475
|
-
options[:address_resolution_policy] =
|
647
|
+
options[:address_resolution_policy] =
|
648
|
+
AddressResolution::Policies::EC2MultiRegion.new
|
476
649
|
else
|
477
|
-
raise ::ArgumentError,
|
650
|
+
raise ::ArgumentError,
|
651
|
+
':address_resolution must be either :none or :ec2_multi_region, ' \
|
652
|
+
"#{address_resolution.inspect} given"
|
478
653
|
end
|
479
654
|
end
|
480
655
|
|
481
|
-
if options.
|
656
|
+
if options.key?(:address_resolution_policy)
|
482
657
|
address_resolver = options[:address_resolution_policy]
|
483
658
|
|
484
|
-
Util.assert_responds_to(:resolve, address_resolver)
|
659
|
+
Util.assert_responds_to(:resolve, address_resolver) do
|
660
|
+
':address_resolution_policy must respond to :resolve, ' \
|
661
|
+
"#{address_resolver.inspect} but doesn't"
|
662
|
+
end
|
485
663
|
end
|
486
664
|
|
487
|
-
if options.
|
665
|
+
if options.key?(:synchronize_schema)
|
488
666
|
options[:synchronize_schema] = !!options[:synchronize_schema]
|
489
667
|
end
|
490
668
|
|
491
|
-
if options.
|
669
|
+
if options.key?(:client_timestamps)
|
492
670
|
options[:client_timestamps] = !!options[:client_timestamps]
|
493
671
|
end
|
494
672
|
|
495
|
-
|
673
|
+
if options.key?(:connections_per_local_node)
|
674
|
+
connections_per_node = options[:connections_per_local_node]
|
496
675
|
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
hosts << ::IPAddr.new(ip)
|
676
|
+
unless connections_per_node.nil?
|
677
|
+
connections_per_node = options[:connections_per_local_node]
|
678
|
+
Util.assert_instance_of(::Integer, connections_per_node)
|
679
|
+
Util.assert_one_of(1...2**16, connections_per_node) do
|
680
|
+
':connections_per_local_node must be a positive integer between ' \
|
681
|
+
"1 and 65535, #{connections_per_node.inspect} given"
|
504
682
|
end
|
505
|
-
else
|
506
|
-
raise ::ArgumentError, ":hosts must be String or IPAddr, #{host.inspect} given"
|
507
683
|
end
|
508
684
|
end
|
509
685
|
|
510
|
-
if
|
511
|
-
|
686
|
+
if options.key?(:connections_per_remote_node)
|
687
|
+
connections_per_node = options[:connections_per_remote_node]
|
688
|
+
|
689
|
+
unless connections_per_node.nil?
|
690
|
+
connections_per_node = options[:connections_per_remote_node]
|
691
|
+
Util.assert_instance_of(::Integer, connections_per_node)
|
692
|
+
Util.assert_one_of(1...2**16, connections_per_node) do
|
693
|
+
':connections_per_remote_node must be a positive integer between ' \
|
694
|
+
"1 and 65535, #{connections_per_node.inspect} given"
|
695
|
+
end
|
696
|
+
end
|
512
697
|
end
|
513
698
|
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
699
|
+
if options.key?(:requests_per_connection)
|
700
|
+
requests_per_connection = options[:requests_per_connection]
|
701
|
+
|
702
|
+
unless requests_per_connection.nil?
|
703
|
+
requests_per_connection = options[:requests_per_connection]
|
704
|
+
Util.assert_instance_of(::Integer, requests_per_connection)
|
705
|
+
|
706
|
+
# v3 protocol says that max stream-id is 32767 (2^15-1). This setting might be
|
707
|
+
# used to talk to a v2 (or less) node, but then we'll adjust it down.
|
708
|
+
|
709
|
+
Util.assert_one_of(1...2**15, requests_per_connection) do
|
710
|
+
':requests_per_connection must be a positive integer, ' \
|
711
|
+
"#{requests_per_connection.inspect} given"
|
712
|
+
end
|
713
|
+
end
|
714
|
+
end
|
715
|
+
options
|
521
716
|
end
|
522
717
|
|
523
718
|
# @private
|
@@ -535,7 +730,7 @@ module Cassandra
|
|
535
730
|
# => 1970-1-1
|
536
731
|
# ::Date.jd(DATE_OFFSET + 2 ** 32, ::Date::GREGORIAN)
|
537
732
|
# => 5881580-07-12
|
538
|
-
DATE_OFFSET = (::Time.utc(1970, 1, 1).to_date.jd - 2
|
733
|
+
DATE_OFFSET = (::Time.utc(1970, 1, 1).to_date.jd - 2**31)
|
539
734
|
end
|
540
735
|
|
541
736
|
require 'cassandra/uuid'
|
@@ -550,6 +745,7 @@ require 'cassandra/errors'
|
|
550
745
|
require 'cassandra/compression'
|
551
746
|
require 'cassandra/protocol'
|
552
747
|
require 'cassandra/auth'
|
748
|
+
require 'cassandra/cassandra_logger'
|
553
749
|
require 'cassandra/null_logger'
|
554
750
|
|
555
751
|
require 'cassandra/executors'
|
@@ -565,6 +761,7 @@ require 'cassandra/statements'
|
|
565
761
|
require 'cassandra/aggregate'
|
566
762
|
require 'cassandra/argument'
|
567
763
|
require 'cassandra/function'
|
764
|
+
require 'cassandra/function_collection'
|
568
765
|
require 'cassandra/column'
|
569
766
|
require 'cassandra/table'
|
570
767
|
require 'cassandra/keyspace'
|
@@ -587,7 +784,7 @@ module Cassandra
|
|
587
784
|
# @private
|
588
785
|
VOID_STATEMENT = Statements::Void.new
|
589
786
|
# @private
|
590
|
-
VOID_OPTIONS = Execution::Options.new(
|
787
|
+
VOID_OPTIONS = Execution::Options.new(consistency: :one)
|
591
788
|
# @private
|
592
789
|
NO_HOSTS = Errors::NoHostsAvailable.new
|
593
790
|
end
|