cassandra-driver 3.0.3-java → 3.1.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 +46 -31
- data/lib/cassandra.rb +35 -44
- data/lib/cassandra/cluster.rb +40 -11
- data/lib/cassandra/cluster/client.rb +193 -159
- data/lib/cassandra/cluster/connector.rb +12 -10
- data/lib/cassandra/cluster/control_connection.rb +38 -10
- data/lib/cassandra/cluster/options.rb +8 -4
- data/lib/cassandra/cluster/registry.rb +1 -2
- data/lib/cassandra/cluster/schema/fetchers.rb +122 -26
- data/lib/cassandra/column_container.rb +9 -4
- data/lib/cassandra/custom_data.rb +24 -22
- data/lib/cassandra/driver.rb +30 -13
- data/lib/cassandra/errors.rb +12 -2
- data/lib/cassandra/execution/options.rb +52 -16
- data/lib/cassandra/execution/profile.rb +150 -0
- data/lib/cassandra/execution/profile_manager.rb +71 -0
- data/lib/cassandra/execution/trace.rb +5 -4
- data/lib/cassandra/executors.rb +1 -1
- data/lib/cassandra/index.rb +1 -1
- data/lib/cassandra/keyspace.rb +36 -1
- data/lib/cassandra/protocol.rb +5 -0
- data/lib/cassandra/protocol/coder.rb +2 -1
- data/lib/cassandra/protocol/cql_byte_buffer.rb +21 -0
- data/lib/cassandra/protocol/responses/read_failure_error_response.rb +10 -4
- data/lib/cassandra/protocol/responses/write_failure_error_response.rb +14 -8
- data/lib/cassandra/protocol/v3.rb +2 -1
- data/lib/cassandra/protocol/v4.rb +58 -20
- data/lib/cassandra/result.rb +1 -1
- data/lib/cassandra/session.rb +43 -16
- data/lib/cassandra/statements/bound.rb +5 -1
- data/lib/cassandra/statements/prepared.rb +8 -3
- data/lib/cassandra/table.rb +72 -0
- data/lib/cassandra/trigger.rb +67 -0
- data/lib/cassandra/types.rb +12 -24
- data/lib/cassandra/udt.rb +3 -6
- data/lib/cassandra/uuid/generator.rb +6 -3
- data/lib/cassandra/version.rb +1 -1
- data/lib/cassandra_murmur3.jar +0 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ac761253a986cd88350b04de1d3ee90bf1f355c3
|
4
|
+
data.tar.gz: 6c9bbff04510173fd06518c7592d7c326534b081
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ddf9b426f9f3e2934f1dc705657af049472ef68474ce1458a80d3a5e7a33b07b75fa34ab27bfb71617e2f4b111f8c774ca96e45c98b495e0cf06cc25606d3757
|
7
|
+
data.tar.gz: 526e8a7fae76a17635ecadc369b62f1a175aef694a9d0d8488262e90722de6363f8243081e0e5d18c4b6c05305932c59bbf3b369511cce1fbef91746f25ebff4
|
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
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
|
3
|
+
*If you're reading this on GitHub, please note that this is the readme for the development version and that some
|
4
|
+
features described here might not yet have been released. You can view the documentation for the latest released
|
5
|
+
version [here](http://docs.datastax.com/en/developer/ruby-driver/latest).*
|
4
6
|
|
5
7
|
[](https://travis-ci.org/datastax/ruby-driver)
|
6
8
|
|
@@ -8,22 +10,22 @@ A Ruby client driver for Apache Cassandra. This driver works exclusively with
|
|
8
10
|
the Cassandra Query Language version 3 (CQL3) and Cassandra's native protocol.
|
9
11
|
|
10
12
|
- Code: https://github.com/datastax/ruby-driver
|
11
|
-
- Docs: http://docs.datastax.com/en/
|
13
|
+
- Docs: http://docs.datastax.com/en/developer/ruby-driver
|
12
14
|
- Jira: https://datastax-oss.atlassian.net/browse/RUBY
|
13
15
|
- Mailing List: https://groups.google.com/a/lists.datastax.com/forum/#!forum/ruby-driver-user
|
14
16
|
- IRC: #datastax-drivers on [irc.freenode.net](http://freenode.net>)
|
15
|
-
- Twitter: Follow the latest news about DataStax Drivers - [@
|
17
|
+
- Twitter: Follow the latest news about DataStax Drivers - [@stamhankar999](http://twitter.com/stamhankar999), [@avalanche123](http://twitter.com/avalanche123), [@al3xandru](https://twitter.com/al3xandru)
|
16
18
|
|
17
19
|
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
20
|
|
19
|
-
* [Asynchronous execution](http://docs.datastax.com/en/developer/ruby-driver/3.0/
|
20
|
-
* One-off, [prepared](http://docs.datastax.com/en/developer/ruby-driver/3.0/
|
21
|
-
* Automatic peer discovery and cluster metadata with [support for change notifications](http://docs.datastax.com/en/developer/ruby-driver/3.0/
|
22
|
-
* Various [load-balancing](http://docs.datastax.com/en/developer/ruby-driver/3.0/
|
23
|
-
* [SSL encryption](http://docs.datastax.com/en/developer/ruby-driver/3.0/
|
24
|
-
* [Flexible and robust error handling](http://docs.datastax.com/en/developer/ruby-driver/3.0/
|
25
|
-
* [Per-request execution information and tracing](http://docs.datastax.com/en/developer/ruby-driver/3.0/
|
26
|
-
* [Configurable address resolution](http://docs.datastax.com/en/developer/ruby-driver/3.0/
|
21
|
+
* [Asynchronous execution](http://docs.datastax.com/en/developer/ruby-driver/3.0/features/asynchronous_io/)
|
22
|
+
* One-off, [prepared](http://docs.datastax.com/en/developer/ruby-driver/3.0/features/basics/prepared_statements/) and [batch statements](http://docs.datastax.com/en/developer/ruby-driver/3.0/features/basics/batch_statements/)
|
23
|
+
* Automatic peer discovery and cluster metadata with [support for change notifications](http://docs.datastax.com/en/developer/ruby-driver/3.0/features/state_listeners/)
|
24
|
+
* Various [load-balancing](http://docs.datastax.com/en/developer/ruby-driver/3.0/features/load_balancing/), [retry](http://docs.datastax.com/en/developer/ruby-driver/3.0/features/retry_policies/) and [reconnection](http://docs.datastax.com/en/developer/ruby-driver/3.0/features/reconnection/) policies with [ability to write your own](http://docs.datastax.com/en/developer/ruby-driver/3.0/features/load_balancing/implementing_a_policy/)
|
25
|
+
* [SSL encryption](http://docs.datastax.com/en/developer/ruby-driver/3.0/features/security/ssl_encryption/)
|
26
|
+
* [Flexible and robust error handling](http://docs.datastax.com/en/developer/ruby-driver/3.0/features/error_handling/)
|
27
|
+
* [Per-request execution information and tracing](http://docs.datastax.com/en/developer/ruby-driver/3.0/features/debugging/)
|
28
|
+
* [Configurable address resolution](http://docs.datastax.com/en/developer/ruby-driver/3.0/features/address_resolution/)
|
27
29
|
|
28
30
|
[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
31
|
|
@@ -36,10 +38,14 @@ This driver works exclusively with the Cassandra Query Language v3 (CQL3) and Ca
|
|
36
38
|
* Ruby (MRI) 2.2, 2.3
|
37
39
|
* JRuby 1.7
|
38
40
|
|
39
|
-
__Note__: JRuby 1.6 is not officially supported, although 1.6.8 should work.
|
40
|
-
MRI 2.0
|
41
|
+
__Note__: JRuby 1.6 is not officially supported, although 1.6.8 should work. Rubinius is not supported.
|
42
|
+
MRI 2.0, 2.1, and JRuby 9k are not officially supported, but they should work. 1.9.3 is deprecated
|
41
43
|
and is likely to break in the release following 3.0.
|
42
44
|
|
45
|
+
## Feedback Requested
|
46
|
+
|
47
|
+
*Help us focus our efforts!* [Provide your input](http://goo.gl/forms/pCs8PTpHLf) on the Ruby Driver Platform and Runtime Survey (we kept it short).
|
48
|
+
|
43
49
|
## Quick start
|
44
50
|
|
45
51
|
```ruby
|
@@ -51,10 +57,10 @@ cluster.each_host do |host| # automatically discovers all peers
|
|
51
57
|
puts "Host #{host.ip}: id=#{host.id} datacenter=#{host.datacenter} rack=#{host.rack}"
|
52
58
|
end
|
53
59
|
|
54
|
-
keyspace = '
|
60
|
+
keyspace = 'system_schema'
|
55
61
|
session = cluster.connect(keyspace) # create session, optionally scoped to a keyspace, to execute queries
|
56
62
|
|
57
|
-
future = session.execute_async('SELECT keyspace_name, table_name FROM
|
63
|
+
future = session.execute_async('SELECT keyspace_name, table_name FROM tables') # fully asynchronous api
|
58
64
|
future.on_success do |rows|
|
59
65
|
rows.each do |row|
|
60
66
|
puts "The keyspace #{row['keyspace_name']} has a table called #{row['table_name']}"
|
@@ -67,9 +73,9 @@ __Note__: The host you specify is just a seed node, the driver will automaticall
|
|
67
73
|
|
68
74
|
Read more:
|
69
75
|
|
70
|
-
* [`Cassandra.cluster` options](http://docs.datastax.com/en/developer/ruby-driver/3.0/
|
71
|
-
* [`Session#execute_async` options](http://docs.datastax.com/en/developer/ruby-driver/3.0/
|
72
|
-
* [Usage documentation](http://docs.datastax.com/en/developer/ruby-driver/3.0/
|
76
|
+
* [`Cassandra.cluster` options](http://docs.datastax.com/en/developer/ruby-driver/3.0/api/cassandra/#cluster-class_method)
|
77
|
+
* [`Session#execute_async` options](http://docs.datastax.com/en/developer/ruby-driver/3.0/api/cassandra/session/#execute_async-instance_method)
|
78
|
+
* [Usage documentation](http://docs.datastax.com/en/developer/ruby-driver/3.0/features)
|
73
79
|
|
74
80
|
## Installation
|
75
81
|
|
@@ -85,16 +91,29 @@ Install via Gemfile
|
|
85
91
|
gem 'cassandra-driver'
|
86
92
|
```
|
87
93
|
|
88
|
-
__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://docs.datastax.com/en/developer/ruby-driver/3.0/
|
94
|
+
__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://docs.datastax.com/en/developer/ruby-driver/3.0/features/#compression)
|
89
95
|
|
90
96
|
|
91
97
|
## Upgrading from cql-rb
|
92
98
|
|
93
|
-
Some of the new features added to the driver have unfortunately led to changes in the original cql-rb API.
|
99
|
+
Some of the new features added to the driver have unfortunately led to changes in the original cql-rb API.
|
100
|
+
In the examples directory, you can find [an example of how to wrap the ruby driver to achieve almost complete
|
101
|
+
interface parity with cql-rb](https://github.com/datastax/ruby-driver/blob/v3.1.0/examples/cql-rb-wrapper.rb)
|
102
|
+
to assist you with gradual upgrade.
|
94
103
|
|
95
|
-
## What's new in v3.
|
104
|
+
## What's new in v3.1
|
105
|
+
|
106
|
+
This minor release introduces features and fixes around resiliency, schema metadata, usability, and performance. One
|
107
|
+
of the most user-impacting of these is the introduction of
|
108
|
+
[execution profiles](http://docs.datastax.com/en/developer/ruby-driver/3.1/features/basics/execution_profiles).
|
109
|
+
Execution profiles allow you to group various execution options into a 'profile' and you reference the desired
|
110
|
+
profile at execution time. Get the scoop
|
111
|
+
[here](http://docs.datastax.com/en/developer/ruby-driver/3.1/features/basics/execution_profiles).
|
96
112
|
|
97
|
-
See the [changelog](https://github.com/datastax/ruby-driver/blob/v3.0
|
113
|
+
See the [changelog](https://github.com/datastax/ruby-driver/blob/v3.1.0/CHANGELOG.md) for more information on all
|
114
|
+
changes in this version and past versions.
|
115
|
+
|
116
|
+
## What's new in v3.0
|
98
117
|
|
99
118
|
### Features:
|
100
119
|
|
@@ -150,10 +169,6 @@ batch.add(query, arguments: {p1: 'val1'})
|
|
150
169
|
* [[RUBY-161](https://datastax-oss.atlassian.net/browse/RUBY-161)] Protocol version negotiation in mixed version clusters should not fall back to v1 unless it is truly warranted.
|
151
170
|
* [[RUBY-214](https://datastax-oss.atlassian.net/browse/RUBY-214)] Ensure client timestamps have microsecond precision in JRuby. Previously, some row updates would get lost in high transaction environments.
|
152
171
|
|
153
|
-
## Feedback Requested
|
154
|
-
|
155
|
-
*Help us focus our efforts!* [Provide your input](http://goo.gl/forms/pCs8PTpHLf) on the Ruby Driver Platform and Runtime Survey (we kept it short).
|
156
|
-
|
157
172
|
## Code examples
|
158
173
|
|
159
174
|
The DataStax Ruby Driver uses the awesome [Cucumber Framework](http://cukes.info/) for
|
@@ -164,7 +179,7 @@ examples in the `features/` directory.
|
|
164
179
|
## Running tests
|
165
180
|
|
166
181
|
If you don't feel like reading through the following instructions on how to run
|
167
|
-
ruby-driver tests, feel free to [check out .travis.yml for the entire build code](https://github.com/datastax/ruby-driver/blob/v3.0
|
182
|
+
ruby-driver tests, feel free to [check out .travis.yml for the entire build code](https://github.com/datastax/ruby-driver/blob/v3.1.0/.travis.yml).
|
168
183
|
|
169
184
|
* Check out the driver codebase and install test dependencies:
|
170
185
|
|
@@ -188,7 +203,7 @@ CASSANDRA_VERSION=2.0.17 bundle exec rake test # run both as well as integration
|
|
188
203
|
## Changelog & versioning
|
189
204
|
|
190
205
|
Check out the [releases on GitHub](https://github.com/datastax/ruby-driver/releases) and
|
191
|
-
[changelog](https://github.com/datastax/ruby-driver/blob/v3.0
|
206
|
+
[changelog](https://github.com/datastax/ruby-driver/blob/v3.1.0/CHANGELOG.md). Version
|
192
207
|
numbering follows the [semantic versioning](http://semver.org/) scheme.
|
193
208
|
|
194
209
|
Private and experimental APIs, defined as whatever is not in the
|
@@ -212,7 +227,7 @@ the release.
|
|
212
227
|
* Because the driver reactor is using `IO.select`, the maximum number of tcp connections allowed is 1024.
|
213
228
|
* Because the driver uses `IO#write_nonblock`, Windows is not supported.
|
214
229
|
|
215
|
-
Please [refer to the usage documentation for more information on common pitfalls](http://docs.datastax.com/en/developer/ruby-driver/3.0/
|
230
|
+
Please [refer to the usage documentation for more information on common pitfalls](http://docs.datastax.com/en/developer/ruby-driver/3.0/features/)
|
216
231
|
|
217
232
|
## Contributing
|
218
233
|
|
@@ -226,7 +241,7 @@ that are common across all other DataStax drivers for Apache Cassandra.
|
|
226
241
|
|
227
242
|
The development effort to provide an up to date, high performance, fully featured Ruby
|
228
243
|
Driver for Apache Cassandra will continue on this project, while
|
229
|
-
[cql-rb](https://github.com/iconara/cql-rb/)
|
244
|
+
[cql-rb](https://github.com/iconara/cql-rb/) has been discontinued.
|
230
245
|
|
231
246
|
## Copyright
|
232
247
|
|
@@ -242,4 +257,4 @@ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
|
|
242
257
|
either express or implied. See the License for the specific language governing permissions
|
243
258
|
and limitations under the License.
|
244
259
|
|
245
|
-
[1]: http://docs.datastax.com/en/developer/ruby-driver/3.0/
|
260
|
+
[1]: http://docs.datastax.com/en/developer/ruby-driver/3.0/api
|
data/lib/cassandra.rb
CHANGED
@@ -56,6 +56,7 @@ module Cassandra
|
|
56
56
|
CLUSTER_OPTIONS = [
|
57
57
|
:address_resolution,
|
58
58
|
:address_resolution_policy,
|
59
|
+
:allow_beta_protocol,
|
59
60
|
:auth_provider,
|
60
61
|
:client_cert,
|
61
62
|
:client_timestamps,
|
@@ -68,6 +69,7 @@ module Cassandra
|
|
68
69
|
:credentials,
|
69
70
|
:custom_types,
|
70
71
|
:datacenter,
|
72
|
+
:execution_profiles,
|
71
73
|
:futures_factory,
|
72
74
|
:heartbeat_interval,
|
73
75
|
:hosts,
|
@@ -117,10 +119,14 @@ module Cassandra
|
|
117
119
|
# found by the default Token-Aware Load Balancing Policy should be
|
118
120
|
# shuffled. See {Cassandra::LoadBalancing::Policies::TokenAware#initialize Token-Aware Load Balancing Policy}.
|
119
121
|
#
|
122
|
+
# @option options [Hash<String|Symbol, ExecutionProfile>] :execution_profiles (nil)
|
123
|
+
# Hash of {Cassandra::Execution::Profile}s that are available for client use (e.g.
|
124
|
+
# {Session#execute}, {Session#execute_async}, {Session#prepare}, and {Session#prepare_async}).
|
125
|
+
#
|
120
126
|
# @option options [Numeric] :connect_timeout (10) connection timeout in
|
121
127
|
# seconds. Setting value to `nil` will reset it to 5 seconds.
|
122
128
|
#
|
123
|
-
# @option options [Numeric] :timeout (
|
129
|
+
# @option options [Numeric] :timeout (12) request execution timeout in
|
124
130
|
# seconds. Setting value to `nil` will remove request timeout.
|
125
131
|
#
|
126
132
|
# @option options [Numeric] :heartbeat_interval (30) how often should a
|
@@ -191,6 +197,9 @@ module Cassandra
|
|
191
197
|
# nodes. By default, this is auto-negotiated to the highest common protocol version
|
192
198
|
# that all nodes in `:hosts` speak.
|
193
199
|
#
|
200
|
+
# @option options [Boolean] :allow_beta_protocol (false) whether the driver should attempt to speak to nodes
|
201
|
+
# with a beta version of the newest protocol (which is still under development). USE WITH CAUTION!
|
202
|
+
#
|
194
203
|
# @option options [Boolean, Cassandra::TimestampGenerator] :client_timestamps (false) whether the driver
|
195
204
|
# should send timestamps for each executed statement and possibly which timestamp generator to use. Enabling this
|
196
205
|
# setting helps mitigate Cassandra cluster clock skew because the timestamp of the client machine will be used.
|
@@ -315,6 +324,12 @@ module Cassandra
|
|
315
324
|
CLUSTER_OPTIONS.include?(key)
|
316
325
|
end
|
317
326
|
|
327
|
+
if options.key?(:execution_profiles)
|
328
|
+
[:load_balancing_policy, :retry_policy, :timeout, :consistency].each do |opt|
|
329
|
+
raise ::ArgumentError, "#{opt} is not allowed when execution profiles are used" if options.key?(opt)
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
318
333
|
has_username = options.key?(:username)
|
319
334
|
has_password = options.key?(:password)
|
320
335
|
if has_username || has_password
|
@@ -503,15 +518,9 @@ module Cassandra
|
|
503
518
|
end
|
504
519
|
end
|
505
520
|
|
506
|
-
if options.key?(:
|
507
|
-
|
508
|
-
|
509
|
-
unless timeout.nil?
|
510
|
-
Util.assert_instance_of(::Numeric, timeout) do
|
511
|
-
":timeout must be a number of seconds, #{timeout.inspect} given"
|
512
|
-
end
|
513
|
-
Util.assert(timeout > 0) { ":timeout must be greater than 0, #{timeout} given" }
|
514
|
-
end
|
521
|
+
if options.key?(:execution_profiles)
|
522
|
+
Util.assert_instance_of(::Hash, options[:execution_profiles],
|
523
|
+
':execution_profiles must be a hash of <name,ExecutionProfile> entries.')
|
515
524
|
end
|
516
525
|
|
517
526
|
if options.key?(:heartbeat_interval)
|
@@ -562,17 +571,6 @@ module Cassandra
|
|
562
571
|
end
|
563
572
|
end
|
564
573
|
|
565
|
-
if options.key?(:load_balancing_policy)
|
566
|
-
load_balancing_policy = options[:load_balancing_policy]
|
567
|
-
methods = [:host_up, :host_down, :host_found, :host_lost, :setup, :teardown,
|
568
|
-
:distance, :plan]
|
569
|
-
|
570
|
-
Util.assert_responds_to_all(methods, load_balancing_policy) do
|
571
|
-
":load_balancing_policy #{load_balancing_policy.inspect} must respond " \
|
572
|
-
"to #{methods.inspect}, but doesn't"
|
573
|
-
end
|
574
|
-
end
|
575
|
-
|
576
574
|
if options.key?(:reconnection_policy)
|
577
575
|
reconnection_policy = options[:reconnection_policy]
|
578
576
|
|
@@ -582,30 +580,15 @@ module Cassandra
|
|
582
580
|
end
|
583
581
|
end
|
584
582
|
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
Util.assert_responds_to_all(methods, retry_policy) do
|
590
|
-
":retry_policy #{retry_policy.inspect} must respond to #{methods.inspect}, " \
|
591
|
-
"but doesn't"
|
592
|
-
end
|
593
|
-
end
|
583
|
+
# Validate options that go in an execution profile. Instantiating one
|
584
|
+
# causes validation automatically.
|
585
|
+
Cassandra::Execution::Profile.new(options)
|
594
586
|
|
595
587
|
options[:listeners] = Array(options[:listeners]) if options.key?(:listeners)
|
596
|
-
|
597
|
-
if options.key?(:consistency)
|
598
|
-
consistency = options[:consistency]
|
599
|
-
|
600
|
-
Util.assert_one_of(CONSISTENCIES, consistency) do
|
601
|
-
":consistency must be one of #{CONSISTENCIES.inspect}, " \
|
602
|
-
"#{consistency.inspect} given"
|
603
|
-
end
|
604
|
-
end
|
605
|
-
|
606
588
|
options[:nodelay] = !!options[:nodelay] if options.key?(:nodelay)
|
607
589
|
options[:trace] = !!options[:trace] if options.key?(:trace)
|
608
590
|
options[:shuffle_replicas] = !!options[:shuffle_replicas] if options.key?(:shuffle_replicas)
|
591
|
+
options[:allow_beta_protocol] = !!options[:allow_beta_protocol] if options.key?(:allow_beta_protocol)
|
609
592
|
|
610
593
|
if options.key?(:page_size)
|
611
594
|
page_size = options[:page_size]
|
@@ -623,12 +606,15 @@ module Cassandra
|
|
623
606
|
protocol_version = options[:protocol_version]
|
624
607
|
unless protocol_version.nil?
|
625
608
|
Util.assert_instance_of(::Integer, protocol_version)
|
626
|
-
Util.assert_one_of(1..
|
627
|
-
|
628
|
-
|
609
|
+
Util.assert_one_of(1..Cassandra::Protocol::Versions::MAX_SUPPORTED_VERSION, protocol_version,
|
610
|
+
':protocol_version must be a positive integer between 1 and ' \
|
611
|
+
"#{Cassandra::Protocol::Versions::MAX_SUPPORTED_VERSION}, #{protocol_version.inspect} given")
|
629
612
|
end
|
630
613
|
end
|
631
614
|
|
615
|
+
Util.assert(!(options[:allow_beta_protocol] && options[:protocol_version]),
|
616
|
+
'only one of :allow_beta_protocol and :protocol_version may be specified, both given')
|
617
|
+
|
632
618
|
if options.key?(:futures_factory)
|
633
619
|
futures_factory = options[:futures_factory]
|
634
620
|
methods = [:error, :value, :promise, :all]
|
@@ -820,9 +806,12 @@ require 'cassandra/table'
|
|
820
806
|
require 'cassandra/materialized_view'
|
821
807
|
require 'cassandra/keyspace'
|
822
808
|
require 'cassandra/index'
|
809
|
+
require 'cassandra/trigger'
|
823
810
|
|
824
811
|
require 'cassandra/execution/info'
|
825
812
|
require 'cassandra/execution/options'
|
813
|
+
require 'cassandra/execution/profile_manager'
|
814
|
+
require 'cassandra/execution/profile'
|
826
815
|
require 'cassandra/execution/trace'
|
827
816
|
|
828
817
|
require 'cassandra/load_balancing'
|
@@ -845,7 +834,9 @@ module Cassandra
|
|
845
834
|
# @private
|
846
835
|
VOID_STATEMENT = Statements::Void.new
|
847
836
|
# @private
|
848
|
-
VOID_OPTIONS = Execution::Options.new(consistency: :one
|
837
|
+
VOID_OPTIONS = Execution::Options.new(consistency: :one,
|
838
|
+
load_balancing_policy: LoadBalancing::Policies::RoundRobin.new,
|
839
|
+
retry_policy: Retry::Policies::Default.new)
|
849
840
|
# @private
|
850
841
|
NO_HOSTS = Errors::NoHostsAvailable.new
|
851
842
|
end
|
data/lib/cassandra/cluster.rb
CHANGED
@@ -36,9 +36,8 @@ module Cassandra
|
|
36
36
|
cluster_metadata,
|
37
37
|
execution_options,
|
38
38
|
connection_options,
|
39
|
-
|
39
|
+
profile_manager,
|
40
40
|
reconnection_policy,
|
41
|
-
retry_policy,
|
42
41
|
address_resolution_policy,
|
43
42
|
connector,
|
44
43
|
futures_factory,
|
@@ -52,9 +51,8 @@ module Cassandra
|
|
52
51
|
@metadata = cluster_metadata
|
53
52
|
@execution_options = execution_options
|
54
53
|
@connection_options = connection_options
|
55
|
-
@
|
54
|
+
@profile_manager = profile_manager
|
56
55
|
@reconnection_policy = reconnection_policy
|
57
|
-
@retry_policy = retry_policy
|
58
56
|
@address_resolver = address_resolution_policy
|
59
57
|
@connector = connector
|
60
58
|
@futures = futures_factory
|
@@ -62,7 +60,7 @@ module Cassandra
|
|
62
60
|
|
63
61
|
@control_connection.on_close do |_cause|
|
64
62
|
begin
|
65
|
-
@
|
63
|
+
@profile_manager.teardown(self)
|
66
64
|
rescue
|
67
65
|
nil
|
68
66
|
end
|
@@ -153,6 +151,40 @@ module Cassandra
|
|
153
151
|
# @return [Boolean] true or false
|
154
152
|
def_delegators :@schema, :keyspace, :has_keyspace?
|
155
153
|
|
154
|
+
# @return [Integer] Cassandra native protocol port
|
155
|
+
def port
|
156
|
+
@connection_options.port
|
157
|
+
end
|
158
|
+
|
159
|
+
# @return [Integer] the version of the native protocol used in communication with nodes
|
160
|
+
def protocol_version
|
161
|
+
@connection_options.protocol_version
|
162
|
+
end
|
163
|
+
|
164
|
+
# @param name [String] Name of profile to retrieve
|
165
|
+
# @return [Cassandra::Execution::Profile] execution profile of the given name
|
166
|
+
def execution_profile(name)
|
167
|
+
@profile_manager.profiles[name]
|
168
|
+
end
|
169
|
+
|
170
|
+
# Yield or enumerate each execution profile defined in this cluster
|
171
|
+
# @overload each_execution_profile
|
172
|
+
# @yieldparam name [String, Symbol] name of current profile
|
173
|
+
# @yieldparam profile [Cassandra::Execution::Profile] current profile
|
174
|
+
# @return [Cassandra::Cluster] self
|
175
|
+
# @overload each_execution_profile
|
176
|
+
# @return [Hash<String, Cassandra::Execution::Profile>] a hash of profiles keyed on name
|
177
|
+
def each_execution_profile(&block)
|
178
|
+
if block_given?
|
179
|
+
@profile_manager.profiles.each_pair(&block)
|
180
|
+
self
|
181
|
+
else
|
182
|
+
# Return a dup of the hash to prevent the user from adding/removing profiles from the profile-manager.
|
183
|
+
@profile_manager.profiles.dup
|
184
|
+
end
|
185
|
+
end
|
186
|
+
alias execution_profiles each_execution_profile
|
187
|
+
|
156
188
|
# @!method refresh_schema_async
|
157
189
|
# Trigger an asynchronous schema metadata refresh
|
158
190
|
# @return [Cassandra::Future<nil>] a future that will be fulfilled when
|
@@ -201,14 +233,13 @@ module Cassandra
|
|
201
233
|
@schema,
|
202
234
|
@io_reactor,
|
203
235
|
@connector,
|
204
|
-
@
|
236
|
+
@profile_manager,
|
205
237
|
@reconnection_policy,
|
206
|
-
@retry_policy,
|
207
238
|
@address_resolver,
|
208
239
|
@connection_options,
|
209
240
|
@futures,
|
210
241
|
@timestamp_generator)
|
211
|
-
session = Session.new(client, @execution_options, @futures)
|
242
|
+
session = Session.new(client, @execution_options, @futures, @profile_manager)
|
212
243
|
promise = @futures.promise
|
213
244
|
|
214
245
|
client.connect.on_complete do |f|
|
@@ -282,9 +313,7 @@ module Cassandra
|
|
282
313
|
"name=#{name.inspect}, " \
|
283
314
|
"port=#{@connection_options.port}, " \
|
284
315
|
"protocol_version=#{@connection_options.protocol_version}, " \
|
285
|
-
"
|
286
|
-
"consistency=#{@execution_options.consistency.inspect}, " \
|
287
|
-
"timeout=#{@execution_options.timeout.inspect}, " \
|
316
|
+
"execution_profiles=#{@profile_manager.profiles.inspect}, " \
|
288
317
|
"hosts=#{hosts.inspect}, " \
|
289
318
|
"keyspaces=#{keyspaces.inspect}>"
|
290
319
|
end
|
@@ -29,9 +29,8 @@ module Cassandra
|
|
29
29
|
cluster_schema,
|
30
30
|
io_reactor,
|
31
31
|
connector,
|
32
|
-
|
32
|
+
profile_manager,
|
33
33
|
reconnection_policy,
|
34
|
-
retry_policy,
|
35
34
|
address_resolution_policy,
|
36
35
|
connection_options,
|
37
36
|
futures_factory,
|
@@ -41,15 +40,14 @@ module Cassandra
|
|
41
40
|
@schema = cluster_schema
|
42
41
|
@reactor = io_reactor
|
43
42
|
@connector = connector
|
44
|
-
@
|
43
|
+
@profile_manager = profile_manager
|
45
44
|
@reconnection_policy = reconnection_policy
|
46
|
-
@retry_policy = retry_policy
|
47
45
|
@address_resolver = address_resolution_policy
|
48
46
|
@connection_options = connection_options
|
49
47
|
@futures = futures_factory
|
50
48
|
@connections = ::Hash.new
|
51
49
|
@prepared_statements = ::Hash.new
|
52
|
-
@preparing_statements = ::Hash.new
|
50
|
+
@preparing_statements = ::Hash.new {|hash, host| hash[host] = {}}
|
53
51
|
@pending_connections = ::Hash.new
|
54
52
|
@keyspace = nil
|
55
53
|
@state = :idle
|
@@ -67,7 +65,7 @@ module Cassandra
|
|
67
65
|
|
68
66
|
@state = :connecting
|
69
67
|
@registry.each_host do |host|
|
70
|
-
distance = @
|
68
|
+
distance = @profile_manager.distance(host)
|
71
69
|
|
72
70
|
case distance
|
73
71
|
when :ignore
|
@@ -85,7 +83,6 @@ module Cassandra
|
|
85
83
|
|
86
84
|
connecting_hosts[host] = pool_size
|
87
85
|
@pending_connections[host] = 0
|
88
|
-
@prepared_statements[host] = {}
|
89
86
|
@preparing_statements[host] = {}
|
90
87
|
@connections[host] = ConnectionPool.new
|
91
88
|
end
|
@@ -168,7 +165,7 @@ module Cassandra
|
|
168
165
|
pool_size = 0
|
169
166
|
|
170
167
|
synchronize do
|
171
|
-
distance = @
|
168
|
+
distance = @profile_manager.distance(host)
|
172
169
|
case distance
|
173
170
|
when :ignore
|
174
171
|
return Ione::Future.resolved
|
@@ -184,7 +181,6 @@ module Cassandra
|
|
184
181
|
end
|
185
182
|
|
186
183
|
@pending_connections[host] ||= 0
|
187
|
-
@prepared_statements[host] = {}
|
188
184
|
@preparing_statements[host] = {}
|
189
185
|
@connections[host] = ConnectionPool.new
|
190
186
|
end
|
@@ -199,7 +195,6 @@ module Cassandra
|
|
199
195
|
return Ione::Future.resolved unless @connections.key?(host)
|
200
196
|
|
201
197
|
@pending_connections.delete(host) unless @pending_connections[host] > 0
|
202
|
-
@prepared_statements.delete(host)
|
203
198
|
@preparing_statements.delete(host)
|
204
199
|
pool = @connections.delete(host)
|
205
200
|
end
|
@@ -227,7 +222,9 @@ module Cassandra
|
|
227
222
|
return @futures.error(
|
228
223
|
Errors::ClientError.new(
|
229
224
|
'Positional arguments are not supported by the current version of ' \
|
230
|
-
'Apache Cassandra'
|
225
|
+
'Apache Cassandra'
|
226
|
+
)
|
227
|
+
)
|
231
228
|
end
|
232
229
|
|
233
230
|
timestamp = @timestamp_generator.next if @timestamp_generator && @connection_options.protocol_version > 2
|
@@ -248,7 +245,7 @@ module Cassandra
|
|
248
245
|
promise = @futures.promise
|
249
246
|
|
250
247
|
keyspace = @keyspace
|
251
|
-
plan
|
248
|
+
plan = options.load_balancing_policy.plan(keyspace, statement, options)
|
252
249
|
|
253
250
|
send_request_by_plan(promise,
|
254
251
|
keyspace,
|
@@ -270,7 +267,7 @@ module Cassandra
|
|
270
267
|
|
271
268
|
keyspace = @keyspace
|
272
269
|
statement = VOID_STATEMENT
|
273
|
-
plan =
|
270
|
+
plan = options.load_balancing_policy.plan(keyspace, statement, options)
|
274
271
|
|
275
272
|
send_request_by_plan(promise,
|
276
273
|
keyspace,
|
@@ -303,7 +300,7 @@ module Cassandra
|
|
303
300
|
promise = @futures.promise
|
304
301
|
|
305
302
|
keyspace = @keyspace
|
306
|
-
plan =
|
303
|
+
plan = options.load_balancing_policy.plan(keyspace, statement, options)
|
307
304
|
|
308
305
|
execute_by_plan(promise, keyspace, statement, options, request, plan, timeout)
|
309
306
|
|
@@ -315,7 +312,9 @@ module Cassandra
|
|
315
312
|
return @futures.error(
|
316
313
|
Errors::ClientError.new(
|
317
314
|
'Batch statements are not supported by the current version of ' \
|
318
|
-
'Apache Cassandra'
|
315
|
+
'Apache Cassandra'
|
316
|
+
)
|
317
|
+
)
|
319
318
|
end
|
320
319
|
|
321
320
|
timestamp = @timestamp_generator.next if @timestamp_generator && @connection_options.protocol_version > 2
|
@@ -329,7 +328,7 @@ module Cassandra
|
|
329
328
|
timestamp,
|
330
329
|
payload)
|
331
330
|
keyspace = @keyspace
|
332
|
-
plan =
|
331
|
+
plan = options.load_balancing_policy.plan(keyspace, statement, options)
|
333
332
|
promise = @futures.promise
|
334
333
|
|
335
334
|
batch_by_plan(promise, keyspace, statement, options, request, plan, timeout)
|
@@ -366,13 +365,15 @@ module Cassandra
|
|
366
365
|
'SELECT peer, rpc_address, schema_version FROM system.peers',
|
367
366
|
EMPTY_LIST,
|
368
367
|
EMPTY_LIST,
|
369
|
-
:one
|
368
|
+
:one
|
369
|
+
)
|
370
370
|
SELECT_SCHEMA_LOCAL =
|
371
371
|
Protocol::QueryRequest.new(
|
372
372
|
"SELECT schema_version FROM system.local WHERE key='local'",
|
373
373
|
EMPTY_LIST,
|
374
374
|
EMPTY_LIST,
|
375
|
-
:one
|
375
|
+
:one
|
376
|
+
)
|
376
377
|
|
377
378
|
def connected(f)
|
378
379
|
if f.resolved?
|
@@ -472,7 +473,7 @@ module Cassandra
|
|
472
473
|
@pending_connections[host] += size
|
473
474
|
end
|
474
475
|
|
475
|
-
@logger.debug("Creating #{size} connections to #{host.ip}")
|
476
|
+
@logger.debug("Creating #{size} request connections to #{host.ip}")
|
476
477
|
futures = size.times.map do
|
477
478
|
@connector.connect(host).recover do |e|
|
478
479
|
FailedConnection.new(e, host)
|
@@ -491,7 +492,7 @@ module Cassandra
|
|
491
492
|
end
|
492
493
|
end
|
493
494
|
|
494
|
-
@logger.debug("Created #{connections.size} connections to #{host.ip}")
|
495
|
+
@logger.debug("Created #{connections.size} request connections to #{host.ip}")
|
495
496
|
|
496
497
|
pool = nil
|
497
498
|
|
@@ -510,6 +511,12 @@ module Cassandra
|
|
510
511
|
|
511
512
|
connections.each do |connection|
|
512
513
|
connection.on_closed do |cause|
|
514
|
+
if cause
|
515
|
+
@logger.info('Request connection closed ' \
|
516
|
+
"(#{cause.class.name}: #{cause.message})")
|
517
|
+
else
|
518
|
+
@logger.info('Request connection closed')
|
519
|
+
end
|
513
520
|
connect_to_host_maybe_retry(host, pool_size) if cause
|
514
521
|
end
|
515
522
|
end
|
@@ -533,13 +540,16 @@ module Cassandra
|
|
533
540
|
plan,
|
534
541
|
timeout,
|
535
542
|
errors = nil,
|
536
|
-
hosts = []
|
543
|
+
hosts = [],
|
544
|
+
retries = -1)
|
537
545
|
unless plan.has_next?
|
538
546
|
promise.break(Errors::NoHostsAvailable.new(errors))
|
539
547
|
return
|
540
548
|
end
|
541
549
|
|
542
550
|
hosts << host = plan.next
|
551
|
+
retries += 1
|
552
|
+
|
543
553
|
pool = nil
|
544
554
|
synchronize { pool = @connections[host] }
|
545
555
|
|
@@ -554,7 +564,8 @@ module Cassandra
|
|
554
564
|
plan,
|
555
565
|
timeout,
|
556
566
|
errors,
|
557
|
-
hosts
|
567
|
+
hosts,
|
568
|
+
retries)
|
558
569
|
end
|
559
570
|
|
560
571
|
connection = pool.random_connection
|
@@ -573,7 +584,8 @@ module Cassandra
|
|
573
584
|
plan,
|
574
585
|
timeout,
|
575
586
|
errors,
|
576
|
-
hosts
|
587
|
+
hosts,
|
588
|
+
retries)
|
577
589
|
else
|
578
590
|
s.on_failure do |e|
|
579
591
|
if e.is_a?(Errors::HostError) ||
|
@@ -588,7 +600,8 @@ module Cassandra
|
|
588
600
|
plan,
|
589
601
|
timeout,
|
590
602
|
errors,
|
591
|
-
hosts
|
603
|
+
hosts,
|
604
|
+
retries)
|
592
605
|
else
|
593
606
|
promise.break(e)
|
594
607
|
end
|
@@ -606,7 +619,8 @@ module Cassandra
|
|
606
619
|
plan,
|
607
620
|
timeout,
|
608
621
|
errors,
|
609
|
-
hosts
|
622
|
+
hosts,
|
623
|
+
retries)
|
610
624
|
end
|
611
625
|
rescue => e
|
612
626
|
errors ||= {}
|
@@ -619,7 +633,8 @@ module Cassandra
|
|
619
633
|
plan,
|
620
634
|
timeout,
|
621
635
|
errors,
|
622
|
-
hosts
|
636
|
+
hosts,
|
637
|
+
retries)
|
623
638
|
end
|
624
639
|
|
625
640
|
def prepare_and_send_request_by_plan(host,
|
@@ -632,17 +647,16 @@ module Cassandra
|
|
632
647
|
plan,
|
633
648
|
timeout,
|
634
649
|
errors,
|
635
|
-
hosts
|
650
|
+
hosts,
|
651
|
+
retries)
|
636
652
|
cql = statement.cql
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
end
|
645
|
-
end
|
653
|
+
|
654
|
+
# Get the prepared statement id for this statement from our cache if possible. We are optimistic
|
655
|
+
# that the statement has previously been prepared on all hosts, so the id will be valid. However, if
|
656
|
+
# we're in the midst of preparing the statement on the given host, we know that executing with the id
|
657
|
+
# will fail. So, act like we don't have the prepared-statement id in that case.
|
658
|
+
|
659
|
+
id = synchronize { @preparing_statements[host][cql] ? nil : @prepared_statements[cql] }
|
646
660
|
|
647
661
|
if id
|
648
662
|
request.id = id
|
@@ -656,20 +670,8 @@ module Cassandra
|
|
656
670
|
plan,
|
657
671
|
timeout,
|
658
672
|
errors,
|
659
|
-
hosts
|
660
|
-
|
661
|
-
# We've hit a race condition where the plan says we can query this host, but the host has gone
|
662
|
-
# down in the mean time. Just execute the plan again on the next host.
|
663
|
-
@logger.debug("#{host} is down; executing plan on next host")
|
664
|
-
execute_by_plan(promise,
|
665
|
-
keyspace,
|
666
|
-
statement,
|
667
|
-
options,
|
668
|
-
request,
|
669
|
-
plan,
|
670
|
-
timeout,
|
671
|
-
errors,
|
672
|
-
hosts)
|
673
|
+
hosts,
|
674
|
+
retries)
|
673
675
|
else
|
674
676
|
prepare = prepare_statement(host, connection, cql, timeout)
|
675
677
|
prepare.on_complete do |_|
|
@@ -685,7 +687,8 @@ module Cassandra
|
|
685
687
|
plan,
|
686
688
|
timeout,
|
687
689
|
errors,
|
688
|
-
hosts
|
690
|
+
hosts,
|
691
|
+
retries)
|
689
692
|
else
|
690
693
|
prepare.on_failure do |e|
|
691
694
|
if e.is_a?(Errors::HostError) ||
|
@@ -700,7 +703,8 @@ module Cassandra
|
|
700
703
|
plan,
|
701
704
|
timeout,
|
702
705
|
errors,
|
703
|
-
hosts
|
706
|
+
hosts,
|
707
|
+
retries)
|
704
708
|
else
|
705
709
|
promise.break(e)
|
706
710
|
end
|
@@ -720,13 +724,15 @@ module Cassandra
|
|
720
724
|
plan,
|
721
725
|
timeout,
|
722
726
|
errors = nil,
|
723
|
-
hosts = []
|
727
|
+
hosts = [],
|
728
|
+
retries = -1)
|
724
729
|
unless plan.has_next?
|
725
730
|
promise.break(Errors::NoHostsAvailable.new(errors))
|
726
731
|
return
|
727
732
|
end
|
728
733
|
|
729
734
|
hosts << host = plan.next
|
735
|
+
retries += 1
|
730
736
|
pool = nil
|
731
737
|
synchronize { pool = @connections[host] }
|
732
738
|
|
@@ -741,7 +747,8 @@ module Cassandra
|
|
741
747
|
plan,
|
742
748
|
timeout,
|
743
749
|
errors,
|
744
|
-
hosts
|
750
|
+
hosts,
|
751
|
+
retries)
|
745
752
|
end
|
746
753
|
|
747
754
|
connection = pool.random_connection
|
@@ -760,7 +767,8 @@ module Cassandra
|
|
760
767
|
plan,
|
761
768
|
timeout,
|
762
769
|
errors,
|
763
|
-
hosts
|
770
|
+
hosts,
|
771
|
+
retries)
|
764
772
|
else
|
765
773
|
s.on_failure do |e|
|
766
774
|
if e.is_a?(Errors::HostError) ||
|
@@ -775,7 +783,8 @@ module Cassandra
|
|
775
783
|
plan,
|
776
784
|
timeout,
|
777
785
|
errors,
|
778
|
-
hosts
|
786
|
+
hosts,
|
787
|
+
retries)
|
779
788
|
else
|
780
789
|
promise.break(e)
|
781
790
|
end
|
@@ -793,7 +802,8 @@ module Cassandra
|
|
793
802
|
plan,
|
794
803
|
timeout,
|
795
804
|
errors,
|
796
|
-
hosts
|
805
|
+
hosts,
|
806
|
+
retries)
|
797
807
|
end
|
798
808
|
rescue => e
|
799
809
|
errors ||= {}
|
@@ -806,7 +816,8 @@ module Cassandra
|
|
806
816
|
plan,
|
807
817
|
timeout,
|
808
818
|
errors,
|
809
|
-
hosts
|
819
|
+
hosts,
|
820
|
+
retries)
|
810
821
|
end
|
811
822
|
|
812
823
|
def batch_and_send_request_by_plan(host,
|
@@ -819,7 +830,8 @@ module Cassandra
|
|
819
830
|
plan,
|
820
831
|
timeout,
|
821
832
|
errors,
|
822
|
-
hosts
|
833
|
+
hosts,
|
834
|
+
retries)
|
823
835
|
request.clear
|
824
836
|
unprepared = Hash.new {|hash, cql| hash[cql] = []}
|
825
837
|
|
@@ -827,29 +839,15 @@ module Cassandra
|
|
827
839
|
cql = statement.cql
|
828
840
|
|
829
841
|
if statement.is_a?(Statements::Bound)
|
830
|
-
|
831
|
-
id
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
id = @prepared_statements[host][cql]
|
837
|
-
end
|
838
|
-
end
|
842
|
+
# Get the prepared statement id for this statement from our cache if possible. We are optimistic
|
843
|
+
# that the statement has previously been prepared on all hosts, so the id will be valid. However, if
|
844
|
+
# we're in the midst of preparing the statement on the given host, we know that executing with the id
|
845
|
+
# will fail. So, act like we don't have the prepared-statement id in that case.
|
846
|
+
|
847
|
+
id = synchronize { @preparing_statements[host][cql] ? nil : @prepared_statements[cql] }
|
839
848
|
|
840
849
|
if id
|
841
850
|
request.add_prepared(id, statement.params, statement.params_types)
|
842
|
-
elsif !host_is_up
|
843
|
-
@logger.debug("#{host} is down; executing on next host in plan")
|
844
|
-
return batch_by_plan(promise,
|
845
|
-
keyspace,
|
846
|
-
batch_statement,
|
847
|
-
options,
|
848
|
-
request,
|
849
|
-
plan,
|
850
|
-
timeout,
|
851
|
-
errors,
|
852
|
-
hosts)
|
853
851
|
else
|
854
852
|
unprepared[cql] << statement
|
855
853
|
end
|
@@ -869,7 +867,8 @@ module Cassandra
|
|
869
867
|
plan,
|
870
868
|
timeout,
|
871
869
|
errors,
|
872
|
-
hosts
|
870
|
+
hosts,
|
871
|
+
retries)
|
873
872
|
else
|
874
873
|
to_prepare = unprepared.to_a
|
875
874
|
futures = to_prepare.map do |cql, _|
|
@@ -897,7 +896,8 @@ module Cassandra
|
|
897
896
|
plan,
|
898
897
|
timeout,
|
899
898
|
errors,
|
900
|
-
hosts
|
899
|
+
hosts,
|
900
|
+
retries)
|
901
901
|
else
|
902
902
|
f.on_failure do |e|
|
903
903
|
if e.is_a?(Errors::HostError) ||
|
@@ -912,7 +912,8 @@ module Cassandra
|
|
912
912
|
plan,
|
913
913
|
timeout,
|
914
914
|
errors,
|
915
|
-
hosts
|
915
|
+
hosts,
|
916
|
+
retries)
|
916
917
|
else
|
917
918
|
promise.break(e)
|
918
919
|
end
|
@@ -930,13 +931,15 @@ module Cassandra
|
|
930
931
|
plan,
|
931
932
|
timeout,
|
932
933
|
errors = nil,
|
933
|
-
hosts = []
|
934
|
+
hosts = [],
|
935
|
+
retries = -1)
|
934
936
|
unless plan.has_next?
|
935
937
|
promise.break(Errors::NoHostsAvailable.new(errors))
|
936
938
|
return
|
937
939
|
end
|
938
940
|
|
939
941
|
hosts << host = plan.next
|
942
|
+
retries += 1
|
940
943
|
pool = nil
|
941
944
|
synchronize { pool = @connections[host] }
|
942
945
|
|
@@ -951,7 +954,8 @@ module Cassandra
|
|
951
954
|
plan,
|
952
955
|
timeout,
|
953
956
|
errors,
|
954
|
-
hosts
|
957
|
+
hosts,
|
958
|
+
retries)
|
955
959
|
end
|
956
960
|
|
957
961
|
connection = pool.random_connection
|
@@ -970,7 +974,8 @@ module Cassandra
|
|
970
974
|
plan,
|
971
975
|
timeout,
|
972
976
|
errors,
|
973
|
-
hosts
|
977
|
+
hosts,
|
978
|
+
retries)
|
974
979
|
else
|
975
980
|
s.on_failure do |e|
|
976
981
|
if e.is_a?(Errors::HostError) ||
|
@@ -985,7 +990,8 @@ module Cassandra
|
|
985
990
|
plan,
|
986
991
|
timeout,
|
987
992
|
errors,
|
988
|
-
hosts
|
993
|
+
hosts,
|
994
|
+
retries)
|
989
995
|
else
|
990
996
|
promise.break(e)
|
991
997
|
end
|
@@ -1003,7 +1009,8 @@ module Cassandra
|
|
1003
1009
|
plan,
|
1004
1010
|
timeout,
|
1005
1011
|
errors,
|
1006
|
-
hosts
|
1012
|
+
hosts,
|
1013
|
+
retries)
|
1007
1014
|
end
|
1008
1015
|
rescue => e
|
1009
1016
|
errors ||= {}
|
@@ -1016,7 +1023,8 @@ module Cassandra
|
|
1016
1023
|
plan,
|
1017
1024
|
timeout,
|
1018
1025
|
errors,
|
1019
|
-
hosts
|
1026
|
+
hosts,
|
1027
|
+
retries)
|
1020
1028
|
end
|
1021
1029
|
|
1022
1030
|
def do_send_request_by_plan(host,
|
@@ -1030,7 +1038,7 @@ module Cassandra
|
|
1030
1038
|
timeout,
|
1031
1039
|
errors,
|
1032
1040
|
hosts,
|
1033
|
-
retries
|
1041
|
+
retries)
|
1034
1042
|
request.retries = retries
|
1035
1043
|
|
1036
1044
|
f = connection.send_request(request, timeout)
|
@@ -1075,37 +1083,43 @@ module Cassandra
|
|
1075
1083
|
|
1076
1084
|
case r
|
1077
1085
|
when Protocol::UnavailableErrorResponse
|
1078
|
-
decision =
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1086
|
+
decision = options.retry_policy.unavailable(statement,
|
1087
|
+
r.consistency,
|
1088
|
+
r.required,
|
1089
|
+
r.alive,
|
1090
|
+
retries)
|
1083
1091
|
when Protocol::WriteTimeoutErrorResponse
|
1084
|
-
decision =
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1092
|
+
decision = options.retry_policy.write_timeout(statement,
|
1093
|
+
r.consistency,
|
1094
|
+
r.write_type,
|
1095
|
+
r.blockfor,
|
1096
|
+
r.received,
|
1097
|
+
retries)
|
1090
1098
|
when Protocol::ReadTimeoutErrorResponse
|
1091
|
-
decision =
|
1092
|
-
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
1099
|
+
decision = options.retry_policy.read_timeout(statement,
|
1100
|
+
r.consistency,
|
1101
|
+
r.blockfor,
|
1102
|
+
r.received,
|
1103
|
+
r.data_present,
|
1104
|
+
retries)
|
1097
1105
|
when Protocol::UnpreparedErrorResponse
|
1098
|
-
cql =
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1106
|
+
cql = nil
|
1107
|
+
if statement.is_a?(Cassandra::Statements::Batch)
|
1108
|
+
# Find the prepared statement with the prepared-statement-id reported by the node.
|
1109
|
+
unprepared_child = statement.statements.select do |s|
|
1110
|
+
(s.is_a?(Cassandra::Statements::Prepared) || s.is_a?(Cassandra::Statements::Bound)) && s.id == r.id
|
1111
|
+
end.first
|
1112
|
+
cql = unprepared_child ? unprepared_child.cql : nil
|
1113
|
+
else
|
1114
|
+
# This is a normal statement, so we have everything we need.
|
1115
|
+
cql = statement.cql
|
1116
|
+
synchronize { @preparing_statements[host].delete(cql) }
|
1103
1117
|
end
|
1104
1118
|
|
1105
1119
|
prepare = prepare_statement(host, connection, cql, timeout)
|
1106
1120
|
prepare.on_complete do |_|
|
1107
1121
|
if prepare.resolved?
|
1108
|
-
request.id = prepare.value
|
1122
|
+
request.id = prepare.value unless request.is_a?(Cassandra::Protocol::BatchRequest)
|
1109
1123
|
do_send_request_by_plan(host,
|
1110
1124
|
connection,
|
1111
1125
|
promise,
|
@@ -1116,7 +1130,8 @@ module Cassandra
|
|
1116
1130
|
plan,
|
1117
1131
|
timeout,
|
1118
1132
|
errors,
|
1119
|
-
hosts
|
1133
|
+
hosts,
|
1134
|
+
retries)
|
1120
1135
|
else
|
1121
1136
|
prepare.on_failure do |e|
|
1122
1137
|
if e.is_a?(Errors::HostError) ||
|
@@ -1130,7 +1145,8 @@ module Cassandra
|
|
1130
1145
|
plan,
|
1131
1146
|
timeout,
|
1132
1147
|
errors,
|
1133
|
-
hosts
|
1148
|
+
hosts,
|
1149
|
+
retries)
|
1134
1150
|
else
|
1135
1151
|
promise.break(e)
|
1136
1152
|
end
|
@@ -1159,7 +1175,8 @@ module Cassandra
|
|
1159
1175
|
plan,
|
1160
1176
|
timeout,
|
1161
1177
|
errors,
|
1162
|
-
hosts
|
1178
|
+
hosts,
|
1179
|
+
retries)
|
1163
1180
|
when Protocol::ExecuteRequest
|
1164
1181
|
execute_by_plan(promise,
|
1165
1182
|
keyspace,
|
@@ -1169,7 +1186,8 @@ module Cassandra
|
|
1169
1186
|
plan,
|
1170
1187
|
timeout,
|
1171
1188
|
errors,
|
1172
|
-
hosts
|
1189
|
+
hosts,
|
1190
|
+
retries)
|
1173
1191
|
when Protocol::BatchRequest
|
1174
1192
|
batch_by_plan(promise,
|
1175
1193
|
keyspace,
|
@@ -1179,7 +1197,8 @@ module Cassandra
|
|
1179
1197
|
plan,
|
1180
1198
|
timeout,
|
1181
1199
|
errors,
|
1182
|
-
hosts
|
1200
|
+
hosts,
|
1201
|
+
retries)
|
1183
1202
|
end
|
1184
1203
|
else
|
1185
1204
|
promise.break(error)
|
@@ -1200,7 +1219,7 @@ module Cassandra
|
|
1200
1219
|
when Protocol::PreparedResultResponse
|
1201
1220
|
cql = request.cql
|
1202
1221
|
synchronize do
|
1203
|
-
@prepared_statements[
|
1222
|
+
@prepared_statements[cql] = r.id
|
1204
1223
|
@preparing_statements[host].delete(cql)
|
1205
1224
|
end
|
1206
1225
|
|
@@ -1209,7 +1228,8 @@ module Cassandra
|
|
1209
1228
|
pk_idx ||= @schema.get_pk_idx(metadata)
|
1210
1229
|
|
1211
1230
|
promise.fulfill(
|
1212
|
-
Statements::Prepared.new(r.
|
1231
|
+
Statements::Prepared.new(r.id,
|
1232
|
+
r.custom_payload,
|
1213
1233
|
r.warnings,
|
1214
1234
|
cql,
|
1215
1235
|
metadata,
|
@@ -1223,7 +1243,8 @@ module Cassandra
|
|
1223
1243
|
request.consistency,
|
1224
1244
|
retries,
|
1225
1245
|
self,
|
1226
|
-
@connection_options)
|
1246
|
+
@connection_options)
|
1247
|
+
)
|
1227
1248
|
when Protocol::RawRowsResultResponse
|
1228
1249
|
r.materialize(statement.result_metadata)
|
1229
1250
|
promise.fulfill(
|
@@ -1239,7 +1260,8 @@ module Cassandra
|
|
1239
1260
|
request.consistency,
|
1240
1261
|
retries,
|
1241
1262
|
self,
|
1242
|
-
@futures)
|
1263
|
+
@futures)
|
1264
|
+
)
|
1243
1265
|
when Protocol::RowsResultResponse
|
1244
1266
|
promise.fulfill(
|
1245
1267
|
Results::Paged.new(r.custom_payload,
|
@@ -1254,7 +1276,8 @@ module Cassandra
|
|
1254
1276
|
request.consistency,
|
1255
1277
|
retries,
|
1256
1278
|
self,
|
1257
|
-
@futures)
|
1279
|
+
@futures)
|
1280
|
+
)
|
1258
1281
|
when Protocol::SchemaChangeResultResponse
|
1259
1282
|
if r.change == 'DROPPED' &&
|
1260
1283
|
r.target == Protocol::Constants::SCHEMA_CHANGE_TARGET_KEYSPACE
|
@@ -1267,7 +1290,8 @@ module Cassandra
|
|
1267
1290
|
unless f.resolved?
|
1268
1291
|
f.on_failure do |e|
|
1269
1292
|
@logger.error(
|
1270
|
-
"Schema agreement failure (#{e.class.name}: #{e.message})"
|
1293
|
+
"Schema agreement failure (#{e.class.name}: #{e.message})"
|
1294
|
+
)
|
1271
1295
|
end
|
1272
1296
|
end
|
1273
1297
|
promise.fulfill(
|
@@ -1281,7 +1305,8 @@ module Cassandra
|
|
1281
1305
|
request.consistency,
|
1282
1306
|
retries,
|
1283
1307
|
self,
|
1284
|
-
@futures)
|
1308
|
+
@futures)
|
1309
|
+
)
|
1285
1310
|
end
|
1286
1311
|
else
|
1287
1312
|
promise.fulfill(Results::Void.new(r.custom_payload,
|
@@ -1330,7 +1355,8 @@ module Cassandra
|
|
1330
1355
|
plan,
|
1331
1356
|
timeout,
|
1332
1357
|
errors,
|
1333
|
-
hosts
|
1358
|
+
hosts,
|
1359
|
+
retries)
|
1334
1360
|
when Protocol::ExecuteRequest
|
1335
1361
|
execute_by_plan(promise,
|
1336
1362
|
keyspace,
|
@@ -1340,7 +1366,8 @@ module Cassandra
|
|
1340
1366
|
plan,
|
1341
1367
|
timeout,
|
1342
1368
|
errors,
|
1343
|
-
hosts
|
1369
|
+
hosts,
|
1370
|
+
retries)
|
1344
1371
|
when Protocol::BatchRequest
|
1345
1372
|
batch_by_plan(promise,
|
1346
1373
|
keyspace,
|
@@ -1350,7 +1377,8 @@ module Cassandra
|
|
1350
1377
|
plan,
|
1351
1378
|
timeout,
|
1352
1379
|
errors,
|
1353
|
-
hosts
|
1380
|
+
hosts,
|
1381
|
+
retries)
|
1354
1382
|
else
|
1355
1383
|
promise.break(e)
|
1356
1384
|
end
|
@@ -1366,7 +1394,8 @@ module Cassandra
|
|
1366
1394
|
request.consistency,
|
1367
1395
|
retries,
|
1368
1396
|
self,
|
1369
|
-
@futures)
|
1397
|
+
@futures)
|
1398
|
+
)
|
1370
1399
|
when Retry::Decisions::Reraise
|
1371
1400
|
promise.break(
|
1372
1401
|
r.to_error(keyspace,
|
@@ -1374,7 +1403,8 @@ module Cassandra
|
|
1374
1403
|
options,
|
1375
1404
|
hosts,
|
1376
1405
|
request.consistency,
|
1377
|
-
retries)
|
1406
|
+
retries)
|
1407
|
+
)
|
1378
1408
|
else
|
1379
1409
|
promise.break(
|
1380
1410
|
r.to_error(keyspace,
|
@@ -1382,7 +1412,8 @@ module Cassandra
|
|
1382
1412
|
options,
|
1383
1413
|
hosts,
|
1384
1414
|
request.consistency,
|
1385
|
-
retries)
|
1415
|
+
retries)
|
1416
|
+
)
|
1386
1417
|
end
|
1387
1418
|
end
|
1388
1419
|
rescue => e
|
@@ -1391,32 +1422,23 @@ module Cassandra
|
|
1391
1422
|
else
|
1392
1423
|
response_future.on_failure do |ex|
|
1393
1424
|
if ex.is_a?(Errors::HostError) ||
|
1394
|
-
|
1425
|
+
(ex.is_a?(Errors::TimeoutError) && statement.idempotent?)
|
1395
1426
|
|
1396
1427
|
errors[host] = ex
|
1397
1428
|
case request
|
1398
|
-
|
1399
|
-
|
1400
|
-
|
1401
|
-
|
1402
|
-
|
1403
|
-
|
1404
|
-
|
1405
|
-
|
1406
|
-
|
1407
|
-
|
1408
|
-
|
1409
|
-
|
1410
|
-
|
1411
|
-
statement,
|
1412
|
-
options,
|
1413
|
-
request,
|
1414
|
-
plan,
|
1415
|
-
timeout,
|
1416
|
-
errors,
|
1417
|
-
hosts)
|
1418
|
-
when Protocol::BatchRequest
|
1419
|
-
batch_by_plan(promise,
|
1429
|
+
when Protocol::QueryRequest, Protocol::PrepareRequest
|
1430
|
+
send_request_by_plan(promise,
|
1431
|
+
keyspace,
|
1432
|
+
statement,
|
1433
|
+
options,
|
1434
|
+
request,
|
1435
|
+
plan,
|
1436
|
+
timeout,
|
1437
|
+
errors,
|
1438
|
+
hosts,
|
1439
|
+
retries)
|
1440
|
+
when Protocol::ExecuteRequest
|
1441
|
+
execute_by_plan(promise,
|
1420
1442
|
keyspace,
|
1421
1443
|
statement,
|
1422
1444
|
options,
|
@@ -1424,9 +1446,21 @@ module Cassandra
|
|
1424
1446
|
plan,
|
1425
1447
|
timeout,
|
1426
1448
|
errors,
|
1427
|
-
hosts
|
1428
|
-
|
1429
|
-
|
1449
|
+
hosts,
|
1450
|
+
retries)
|
1451
|
+
when Protocol::BatchRequest
|
1452
|
+
batch_by_plan(promise,
|
1453
|
+
keyspace,
|
1454
|
+
statement,
|
1455
|
+
options,
|
1456
|
+
request,
|
1457
|
+
plan,
|
1458
|
+
timeout,
|
1459
|
+
errors,
|
1460
|
+
hosts,
|
1461
|
+
retries)
|
1462
|
+
else
|
1463
|
+
promise.break(ex)
|
1430
1464
|
end
|
1431
1465
|
else
|
1432
1466
|
promise.break(ex)
|
@@ -1445,7 +1479,7 @@ module Cassandra
|
|
1445
1479
|
unless local.empty?
|
1446
1480
|
host = @registry.host(connection.host)
|
1447
1481
|
|
1448
|
-
if host && @
|
1482
|
+
if host && @profile_manager.distance(host) != :ignore
|
1449
1483
|
versions << version = local.first['schema_version']
|
1450
1484
|
@logger.debug("Host #{host.ip} schema version is #{version}")
|
1451
1485
|
end
|
@@ -1453,7 +1487,7 @@ module Cassandra
|
|
1453
1487
|
|
1454
1488
|
peers.each do |row|
|
1455
1489
|
host = @registry.host(peer_ip(row))
|
1456
|
-
next unless host && @
|
1490
|
+
next unless host && @profile_manager.distance(host) != :ignore
|
1457
1491
|
|
1458
1492
|
versions << version = row['schema_version']
|
1459
1493
|
@logger.debug("Host #{host.ip} schema version is #{version}")
|
@@ -1533,7 +1567,7 @@ module Cassandra
|
|
1533
1567
|
when Protocol::PreparedResultResponse
|
1534
1568
|
id = r.id
|
1535
1569
|
synchronize do
|
1536
|
-
@prepared_statements[
|
1570
|
+
@prepared_statements[cql] = id
|
1537
1571
|
@preparing_statements[host].delete(cql)
|
1538
1572
|
end
|
1539
1573
|
id
|