cassandra-driver 3.0.0.rc.2-java → 3.0.2-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 +51 -39
- data/lib/cassandra.rb +74 -32
- data/lib/cassandra/auth.rb +3 -1
- data/lib/cassandra/cluster.rb +14 -3
- data/lib/cassandra/cluster/client.rb +98 -62
- data/lib/cassandra/cluster/connector.rb +7 -9
- data/lib/cassandra/cluster/metadata.rb +1 -1
- data/lib/cassandra/cluster/options.rb +19 -7
- data/lib/cassandra/cluster/schema/cql_type_parser.rb +3 -0
- data/lib/cassandra/cluster/schema/fetchers.rb +1 -1
- data/lib/cassandra/custom_data.rb +51 -0
- data/lib/cassandra/driver.rb +23 -20
- data/lib/cassandra/execution/options.rb +1 -1
- data/lib/cassandra/index.rb +22 -8
- data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +19 -1
- data/lib/cassandra/load_balancing/policies/round_robin.rb +7 -0
- data/lib/cassandra/load_balancing/policies/token_aware.rb +7 -0
- data/lib/cassandra/load_balancing/policies/white_list.rb +7 -0
- data/lib/cassandra/protocol.rb +7 -0
- data/lib/cassandra/protocol/coder.rb +28 -8
- data/lib/cassandra/protocol/cql_byte_buffer.rb +21 -4
- data/lib/cassandra/protocol/cql_protocol_handler.rb +3 -2
- data/lib/cassandra/protocol/requests/batch_request.rb +1 -1
- data/lib/cassandra/protocol/requests/execute_request.rb +1 -1
- data/lib/cassandra/protocol/requests/query_request.rb +1 -1
- data/lib/cassandra/protocol/responses/raw_rows_result_response.rb +4 -2
- data/lib/cassandra/protocol/v1.rb +2 -1
- data/lib/cassandra/protocol/v3.rb +2 -1
- data/lib/cassandra/protocol/v4.rb +5 -3
- data/lib/cassandra/result.rb +2 -2
- data/lib/cassandra/session.rb +10 -15
- data/lib/cassandra/statement.rb +5 -0
- data/lib/cassandra/statements/batch.rb +6 -0
- data/lib/cassandra/statements/bound.rb +5 -0
- data/lib/cassandra/statements/prepared.rb +11 -2
- data/lib/cassandra/statements/simple.rb +5 -0
- data/lib/cassandra/statements/void.rb +5 -0
- data/lib/cassandra/table.rb +5 -5
- data/lib/cassandra/timestamp_generator.rb +37 -0
- data/lib/cassandra/timestamp_generator/simple.rb +38 -0
- data/lib/cassandra/timestamp_generator/ticking_on_duplicate.rb +58 -0
- data/lib/cassandra/tuple.rb +2 -2
- data/lib/cassandra/types.rb +2 -2
- data/lib/cassandra/util.rb +136 -2
- data/lib/cassandra/version.rb +1 -1
- data/lib/cassandra_murmur3.jar +0 -0
- metadata +8 -4
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 78dc265751584f3c23a824f4f8f8cfebd5f98d32
         | 
| 4 | 
            +
              data.tar.gz: 303da68ffd2ec37685f54a22e7c26f0f3568b51d
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 7ecd09602150990d62b56ba5b0c75e1131f54b7c598171f0ca17927dfaf2fc3a2b1bc66c2ffb7b1b61f0164daa6fcbd359c3c6d6528230b05d4e5ba34482665b
         | 
| 7 | 
            +
              data.tar.gz: 64d64fadf8a713b97079096af4aafd966689f9b8e9e0a6e1acae8442229de407599e3d4318eed80614fb30af5fb53db4a98e340c9a8c3490b03ae07e3a363023
         | 
    
        data/README.md
    CHANGED
    
    | @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            # Datastax Ruby Driver for Apache Cassandra
         | 
| 2 2 |  | 
| 3 | 
            -
            *If you're reading this on GitHub, please note that this is the readme for the development version and that some features described here might not yet have been released. You can [find the documentation for latest version through ruby driver docs](http://datastax. | 
| 3 | 
            +
            *If you're reading this on GitHub, please note that this is the readme for the development version and that some features described here might not yet have been released. You can [find the documentation for the latest version through ruby driver docs](http://docs.datastax.com/en/latest-ruby-driver/ruby-driver/whatsNew.html) or via the release tags, [e.g. v3.0.2](https://github.com/datastax/ruby-driver/tree/v3.0.2).*
         | 
| 4 4 |  | 
| 5 5 | 
             
            [](https://travis-ci.org/datastax/ruby-driver)
         | 
| 6 6 |  | 
| @@ -8,7 +8,7 @@ A Ruby client driver for Apache Cassandra. This driver works exclusively with | |
| 8 8 | 
             
            the Cassandra Query Language version 3 (CQL3) and Cassandra's native protocol.
         | 
| 9 9 |  | 
| 10 10 | 
             
            - Code: https://github.com/datastax/ruby-driver
         | 
| 11 | 
            -
            - Docs: http://datastax. | 
| 11 | 
            +
            - Docs: http://docs.datastax.com/en/latest-ruby-driver/ruby-driver/whatsNew.html
         | 
| 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>)
         | 
| @@ -16,14 +16,14 @@ the Cassandra Query Language version 3 (CQL3) and Cassandra's native protocol. | |
| 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 |  | 
| 19 | 
            -
            * [Asynchronous execution](http://datastax. | 
| 20 | 
            -
            * One-off, [prepared](http://datastax. | 
| 21 | 
            -
            * Automatic peer discovery and cluster metadata with [support for change notifications](http://datastax. | 
| 22 | 
            -
            * Various [load-balancing](http://datastax. | 
| 23 | 
            -
            * [SSL encryption](http://datastax. | 
| 24 | 
            -
            * [Flexible and robust error handling](http://datastax. | 
| 25 | 
            -
            * [Per-request execution information and tracing](http://datastax. | 
| 26 | 
            -
            * [Configurable address resolution](http://datastax. | 
| 19 | 
            +
            * [Asynchronous execution](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/asynchronous_io/)
         | 
| 20 | 
            +
            * One-off, [prepared](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/basics/prepared_statements/) and [batch statements](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/basics/batch_statements/)
         | 
| 21 | 
            +
            * Automatic peer discovery and cluster metadata with [support for change notifications](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/state_listeners/)
         | 
| 22 | 
            +
            * Various [load-balancing](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/load_balancing/), [retry](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/retry_policies/) and [reconnection](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/reconnection/) policies with [ability to write your own](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/load_balancing/implementing_a_policy/)
         | 
| 23 | 
            +
            * [SSL encryption](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/security/ssl_encryption/)
         | 
| 24 | 
            +
            * [Flexible and robust error handling](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/error_handling/)
         | 
| 25 | 
            +
            * [Per-request execution information and tracing](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/debugging/)
         | 
| 26 | 
            +
            * [Configurable address resolution](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/address_resolution/)
         | 
| 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 |  | 
| @@ -31,8 +31,8 @@ This driver is based on [the cql-rb gem](https://github.com/iconara/cql-rb) by [ | |
| 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, 2.1, and 3.x
         | 
| 35 | 
            -
            * DataStax Enterprise 4.0 | 
| 34 | 
            +
            * Apache Cassandra versions 1.2, 2.0, 2.1, 2.2, and 3.x
         | 
| 35 | 
            +
            * DataStax Enterprise 4.0 and above.
         | 
| 36 36 | 
             
            * Ruby (MRI) 2.2, 2.3
         | 
| 37 37 | 
             
            * JRuby 1.7
         | 
| 38 38 |  | 
| @@ -67,9 +67,9 @@ __Note__: The host you specify is just a seed node, the driver will automaticall | |
| 67 67 |  | 
| 68 68 | 
             
            Read more:
         | 
| 69 69 |  | 
| 70 | 
            -
            * [`Cassandra.cluster` options](http://datastax. | 
| 71 | 
            -
            * [`Session#execute_async` options](http://datastax. | 
| 72 | 
            -
            * [Usage documentation](http://datastax. | 
| 70 | 
            +
            * [`Cassandra.cluster` options](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/api/cassandra/#cluster-class_method)
         | 
| 71 | 
            +
            * [`Session#execute_async` options](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/api/cassandra/session/#execute_async-instance_method)
         | 
| 72 | 
            +
            * [Usage documentation](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features)
         | 
| 73 73 |  | 
| 74 74 | 
             
            ## Installation
         | 
| 75 75 |  | 
| @@ -85,39 +85,46 @@ Install via Gemfile | |
| 85 85 | 
             
            gem 'cassandra-driver'
         | 
| 86 86 | 
             
            ```
         | 
| 87 87 |  | 
| 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://datastax. | 
| 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/supplemental/features/#compression)
         | 
| 89 89 |  | 
| 90 90 |  | 
| 91 91 | 
             
            ## Upgrading from cql-rb
         | 
| 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/ | 
| 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/v3.0.2/examples/cql-rb-wrapper.rb) to assist you with gradual upgrade.
         | 
| 94 94 |  | 
| 95 | 
            -
            ## What's new in v3.0 | 
| 95 | 
            +
            ## What's new in v3.0
         | 
| 96 | 
            +
             | 
| 97 | 
            +
            See the [changelog](https://github.com/datastax/ruby-driver/blob/v3.0.2/CHANGELOG.md) for details on patch versions.
         | 
| 96 98 |  | 
| 97 99 | 
             
            ### Features:
         | 
| 98 100 |  | 
| 99 | 
            -
            * Apache Cassandra native protocol v4
         | 
| 100 | 
            -
            * Add support for smallint, tinyint, date (Cassandra::Date) and time (Cassandra::Time) data types.
         | 
| 101 | 
            +
            * Add support for Apache Cassandra native protocol v4
         | 
| 102 | 
            +
            * Add support for smallint, tinyint, date (`Cassandra::Date`) and time (`Cassandra::Time`) data types.
         | 
| 101 103 | 
             
            * Include schema metadata for User Defined Functions and User Defined Aggregates.
         | 
| 104 | 
            +
            * Augment the `Cassandra::Table` object to expose many more attributes: `id`, `options`, `keyspace`, `partition_key`, `clustering_columns`, and `clustering_order`. This makes it significantly easier to write administration scripts that report various attributes of your schema, which may help to highlight areas for improvement.
         | 
| 102 105 | 
             
            * 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  | 
| 105 | 
            -
            * Support sending custom payloads when preparing or executing statements using the new  | 
| 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 | 
| 109 | 
            -
            * Add Cassandra::Logger class to make it easy for users to enable debug logging in the client.
         | 
| 110 | 
            -
            * Add protocol_version configuration option to allow the user to force the protocol version to use for communication with nodes.
         | 
| 106 | 
            +
            * Add new retry policy decision `Cassandra::Retry::Policy#try_next_host`.
         | 
| 107 | 
            +
            * Support specifying statement idempotence with the new `idempotent` option when executing.
         | 
| 108 | 
            +
            * Support sending custom payloads when preparing or executing statements using the new `payload` option.
         | 
| 109 | 
            +
            * Expose custom payloads received with responses on server exceptions and `Cassandra::Execution::Info` instances.
         | 
| 110 | 
            +
            * Expose server warnings on server exceptions and `Cassandra::Execution::Info` instances.
         | 
| 111 | 
            +
            * Add `connections_per_local_node`, `connections_per_remote_node`, `requests_per_connection` cluster configuration options to tune parallel query execution and resource usage.
         | 
| 112 | 
            +
            * Add `Cassandra::Logger` class to make it easy for users to enable debug logging in the client.
         | 
| 113 | 
            +
            * Add `protocol_version` configuration option to allow the user to force the protocol version to use for communication with nodes.
         | 
| 111 114 | 
             
            * Add support for materialized views and indexes in the schema metadata.
         | 
| 115 | 
            +
            * Support the `ReadError`, `WriteError`, and `FunctionCallError` Cassandra error responses introduced in Cassandra 2.2.
         | 
| 116 | 
            +
            * Add support for unset variables in bound statements.
         | 
| 117 | 
            +
            * Support DSE security (`DseAuthenticator`, configured for LDAP).
         | 
| 118 | 
            +
            * Add a timeout option to `Cassandra::Future#get`.
         | 
| 112 119 |  | 
| 113 | 
            -
            ### Breaking Changes:
         | 
| 120 | 
            +
            ### Breaking Changes from 2.x:
         | 
| 114 121 |  | 
| 115 | 
            -
            * Cassandra::Future#join is now an alias to Cassandra::Future#get and will raise an error if the future is resolved with one.
         | 
| 122 | 
            +
            * `Cassandra::Future#join` is now an alias to Cassandra::Future#get and will raise an error if the future is resolved with one.
         | 
| 116 123 | 
             
            * Default consistency level is now LOCAL_ONE.
         | 
| 117 124 | 
             
            * Enable tcp no-delay by default.
         | 
| 118 125 | 
             
            * Unavailable errors are retried on the next host in the load balancing plan by default.
         | 
| 119 | 
            -
            * Statement execution no longer retried on timeouts, unless  | 
| 120 | 
            -
            * Cassandra::Statements::Batch#add  | 
| 126 | 
            +
            * Statement execution no longer retried on timeouts, unless the statement is marked as idempotent in the call to `Cassandra::Session#execute*` or when creating a `Cassandra::Statement` object. 
         | 
| 127 | 
            +
            * `Cassandra::Statements::Batch#add` and `Cassandra::Session#execute*` signatures have changed in how one specifies query parameters. Specify the query parameters array as the value of the arguments key:
         | 
| 121 128 |  | 
| 122 129 | 
             
            ```ruby
         | 
| 123 130 | 
             
            batch.add(query, ['val1', 'val2'])
         | 
| @@ -128,6 +135,10 @@ batch.add(query, {p1: 'val1'}) | |
| 128 135 | 
             
            # becomes
         | 
| 129 136 | 
             
            batch.add(query, arguments: {p1: 'val1'})
         | 
| 130 137 | 
             
            ```
         | 
| 138 | 
            +
            * The Datacenter-aware load balancing policy (`Cassandra::LoadBalancing::Policies::DCAwareRoundRobin`) defaults to using
         | 
| 139 | 
            +
              nodes in the local DC only. In prior releases, the policy would fall back to remote nodes after exhausting local nodes.
         | 
| 140 | 
            +
              Specify a positive value (or nil for unlimited) for `max_remote_hosts_to_use` when initializing the policy to allow remote node use.
         | 
| 141 | 
            +
            * Unspecified variables in statements previously resulted in an exception. Now they are essentially ignored or treated as null.
         | 
| 131 142 |  | 
| 132 143 | 
             
            ### Bug Fixes:
         | 
| 133 144 |  | 
| @@ -135,12 +146,13 @@ batch.add(query, arguments: {p1: 'val1'}) | |
| 135 146 | 
             
            * [[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.
         | 
| 136 147 | 
             
            * [[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.
         | 
| 137 148 | 
             
            * [[RUBY-151](https://datastax-oss.atlassian.net/browse/RUBY-151)] Decode incomplete UDTs properly.
         | 
| 138 | 
            -
            * [[RUBY- | 
| 149 | 
            +
            * [[RUBY-155](https://datastax-oss.atlassian.net/browse/RUBY-155)] Request timeout timer should not include request queuing time.
         | 
| 150 | 
            +
            * [[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 | 
            +
            * [[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.
         | 
| 139 152 |  | 
| 140 153 | 
             
            ## Feedback Requested
         | 
| 141 154 |  | 
| 142 | 
            -
            *Help us focus our efforts!* [Provide your input](http://goo.gl/forms/pCs8PTpHLf)
         | 
| 143 | 
            -
            on the Ruby Driver Platform and Runtime Survey (we kept it short).
         | 
| 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).
         | 
| 144 156 |  | 
| 145 157 | 
             
            ## Code examples
         | 
| 146 158 |  | 
| @@ -152,7 +164,7 @@ examples in the `features/` directory. | |
| 152 164 | 
             
            ## Running tests
         | 
| 153 165 |  | 
| 154 166 | 
             
            If you don't feel like reading through the following instructions on how to run
         | 
| 155 | 
            -
            ruby-driver tests, feel free to [check out .travis.yml for the entire build code](https://github.com/datastax/ruby-driver/blob/ | 
| 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.2/.travis.yml).
         | 
| 156 168 |  | 
| 157 169 | 
             
            * Check out the driver codebase and install test dependencies:
         | 
| 158 170 |  | 
| @@ -176,7 +188,7 @@ CASSANDRA_VERSION=2.0.17 bundle exec rake test # run both as well as integration | |
| 176 188 | 
             
            ## Changelog & versioning
         | 
| 177 189 |  | 
| 178 190 | 
             
            Check out the [releases on GitHub](https://github.com/datastax/ruby-driver/releases) and
         | 
| 179 | 
            -
            [changelog](https://github.com/datastax/ruby-driver/blob/ | 
| 191 | 
            +
            [changelog](https://github.com/datastax/ruby-driver/blob/v3.0.2/CHANGELOG.md). Version
         | 
| 180 192 | 
             
            numbering follows the [semantic versioning](http://semver.org/) scheme.
         | 
| 181 193 |  | 
| 182 194 | 
             
            Private and experimental APIs, defined as whatever is not in the
         | 
| @@ -200,7 +212,7 @@ the release. | |
| 200 212 | 
             
            * Because the driver reactor is using `IO.select`, the maximum number of tcp connections allowed is 1024.
         | 
| 201 213 | 
             
            * Because the driver uses `IO#write_nonblock`, Windows is not supported.
         | 
| 202 214 |  | 
| 203 | 
            -
            Please [refer to the usage documentation for more information on common pitfalls](http://datastax. | 
| 215 | 
            +
            Please [refer to the usage documentation for more information on common pitfalls](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/)
         | 
| 204 216 |  | 
| 205 217 | 
             
            ## Contributing
         | 
| 206 218 |  | 
| @@ -230,4 +242,4 @@ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF | |
| 230 242 | 
             
            either express or implied. See the License for the specific language governing permissions
         | 
| 231 243 | 
             
            and limitations under the License.
         | 
| 232 244 |  | 
| 233 | 
            -
              [1]: http://datastax. | 
| 245 | 
            +
              [1]: http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/api
         | 
    
        data/lib/cassandra.rb
    CHANGED
    
    | @@ -66,6 +66,7 @@ module Cassandra | |
| 66 66 | 
             
                :connections_per_remote_node,
         | 
| 67 67 | 
             
                :consistency,
         | 
| 68 68 | 
             
                :credentials,
         | 
| 69 | 
            +
                :custom_types,
         | 
| 69 70 | 
             
                :datacenter,
         | 
| 70 71 | 
             
                :futures_factory,
         | 
| 71 72 | 
             
                :heartbeat_interval,
         | 
| @@ -187,14 +188,17 @@ module Cassandra | |
| 187 188 | 
             
              #   v2 or earlier protocol.
         | 
| 188 189 | 
             
              #
         | 
| 189 190 | 
             
              # @option options [Integer] :protocol_version (nil) Version of protocol to speak to
         | 
| 190 | 
            -
              #   nodes. By default, this is auto-negotiated to the  | 
| 191 | 
            +
              #   nodes. By default, this is auto-negotiated to the highest common protocol version
         | 
| 191 192 | 
             
              #   that all nodes in `:hosts` speak.
         | 
| 192 193 | 
             
              #
         | 
| 193 | 
            -
              # @option options [Boolean] :client_timestamps (false) whether the driver
         | 
| 194 | 
            -
              #   should send timestamps for each executed statement. Enabling this | 
| 195 | 
            -
              #    | 
| 196 | 
            -
              #    | 
| 197 | 
            -
              #    | 
| 194 | 
            +
              # @option options [Boolean, Cassandra::TimestampGenerator] :client_timestamps (false) whether the driver
         | 
| 195 | 
            +
              #   should send timestamps for each executed statement and possibly which timestamp generator to use. Enabling this
         | 
| 196 | 
            +
              #   setting helps mitigate Cassandra cluster clock skew because the timestamp of the client machine will be used.
         | 
| 197 | 
            +
              #   This does not help mitigate application cluster clock skew. Also accepts an initialized
         | 
| 198 | 
            +
              #   {Cassandra::TimestampGenerator}, `:simple` (indicating an instance of {Cassandra::TimestampGenerator::Simple}),
         | 
| 199 | 
            +
              #   or `:monotonic` (indicating an instance of {Cassandra::TimestampGenerator::TickingOnDuplicate}). If set to true,
         | 
| 200 | 
            +
              #   it defaults to {Cassandra::TimestampGenerator::Simple} for all Ruby flavors except JRuby. On JRuby, it defaults to
         | 
| 201 | 
            +
              #   {Cassandra::TimestampGenerator::TickingOnDuplicate}.
         | 
| 198 202 | 
             
              #
         | 
| 199 203 | 
             
              # @option options [Boolean] :synchronize_schema (true) whether the driver
         | 
| 200 204 | 
             
              #   should automatically keep schema metadata synchronized. When enabled, the
         | 
| @@ -290,28 +294,7 @@ module Cassandra | |
| 290 294 | 
             
              # @return [Cassandra::Future<Cassandra::Cluster>] a future resolving to the
         | 
| 291 295 | 
             
              #   cluster instance.
         | 
| 292 296 | 
             
              def self.cluster_async(options = {})
         | 
| 293 | 
            -
                options = validate_and_massage_options(options)
         | 
| 294 | 
            -
                hosts = []
         | 
| 295 | 
            -
             | 
| 296 | 
            -
                Array(options.fetch(:hosts, '127.0.0.1')).each do |host|
         | 
| 297 | 
            -
                  case host
         | 
| 298 | 
            -
                  when ::IPAddr
         | 
| 299 | 
            -
                    hosts << host
         | 
| 300 | 
            -
                  when ::String # ip address or hostname
         | 
| 301 | 
            -
                    Resolv.each_address(host) do |ip|
         | 
| 302 | 
            -
                      hosts << ::IPAddr.new(ip)
         | 
| 303 | 
            -
                    end
         | 
| 304 | 
            -
                  else
         | 
| 305 | 
            -
                    raise ::ArgumentError, ":hosts must be String or IPAddr, #{host.inspect} given"
         | 
| 306 | 
            -
                  end
         | 
| 307 | 
            -
                end
         | 
| 308 | 
            -
             | 
| 309 | 
            -
                if hosts.empty?
         | 
| 310 | 
            -
                  raise ::ArgumentError,
         | 
| 311 | 
            -
                        ":hosts #{options[:hosts].inspect} could not be resolved to any ip address"
         | 
| 312 | 
            -
                end
         | 
| 313 | 
            -
             | 
| 314 | 
            -
                hosts.shuffle!
         | 
| 297 | 
            +
                options, hosts = validate_and_massage_options(options)
         | 
| 315 298 | 
             
              rescue => e
         | 
| 316 299 | 
             
                futures = options.fetch(:futures_factory) { return Future::Error.new(e) }
         | 
| 317 300 | 
             
                futures.error(e)
         | 
| @@ -661,14 +644,14 @@ module Cassandra | |
| 661 644 |  | 
| 662 645 | 
             
                  case address_resolution
         | 
| 663 646 | 
             
                  when :none
         | 
| 664 | 
            -
             | 
| 647 | 
            +
                  # do nothing
         | 
| 665 648 | 
             
                  when :ec2_multi_region
         | 
| 666 649 | 
             
                    options[:address_resolution_policy] =
         | 
| 667 650 | 
             
                      AddressResolution::Policies::EC2MultiRegion.new
         | 
| 668 651 | 
             
                  else
         | 
| 669 652 | 
             
                    raise ::ArgumentError,
         | 
| 670 653 | 
             
                          ':address_resolution must be either :none or :ec2_multi_region, ' \
         | 
| 671 | 
            -
             | 
| 654 | 
            +
                            "#{address_resolution.inspect} given"
         | 
| 672 655 | 
             
                  end
         | 
| 673 656 | 
             
                end
         | 
| 674 657 |  | 
| @@ -682,7 +665,35 @@ module Cassandra | |
| 682 665 | 
             
                end
         | 
| 683 666 |  | 
| 684 667 | 
             
                options[:synchronize_schema] = !!options[:synchronize_schema] if options.key?(:synchronize_schema)
         | 
| 685 | 
            -
             | 
| 668 | 
            +
             | 
| 669 | 
            +
                if options.key?(:client_timestamps)
         | 
| 670 | 
            +
                  timestamp_generator = case options[:client_timestamps]
         | 
| 671 | 
            +
                                        when true
         | 
| 672 | 
            +
                                          if RUBY_ENGINE == 'jruby'
         | 
| 673 | 
            +
                                            Cassandra::TimestampGenerator::TickingOnDuplicate.new
         | 
| 674 | 
            +
                                          else
         | 
| 675 | 
            +
                                            Cassandra::TimestampGenerator::Simple.new
         | 
| 676 | 
            +
                                          end
         | 
| 677 | 
            +
                                        when false
         | 
| 678 | 
            +
                                          nil
         | 
| 679 | 
            +
                                        when :simple
         | 
| 680 | 
            +
                                          Cassandra::TimestampGenerator::Simple.new
         | 
| 681 | 
            +
                                        when :monotonic
         | 
| 682 | 
            +
                                          Cassandra::TimestampGenerator::TickingOnDuplicate.new
         | 
| 683 | 
            +
                                        else
         | 
| 684 | 
            +
                                          # The value must be a generator instance.
         | 
| 685 | 
            +
                                          options[:client_timestamps]
         | 
| 686 | 
            +
                                        end
         | 
| 687 | 
            +
             | 
| 688 | 
            +
                  if timestamp_generator
         | 
| 689 | 
            +
                    Util.assert_responds_to(:next, timestamp_generator) do
         | 
| 690 | 
            +
                      ":client_timestamps #{options[:client_timestamps].inspect} must be a boolean, :simple, :monotonic, or " \
         | 
| 691 | 
            +
                      'an object that responds to :next'
         | 
| 692 | 
            +
                    end
         | 
| 693 | 
            +
                  end
         | 
| 694 | 
            +
                  options.delete(:client_timestamps)
         | 
| 695 | 
            +
                  options[:timestamp_generator] = timestamp_generator
         | 
| 696 | 
            +
                end
         | 
| 686 697 |  | 
| 687 698 | 
             
                if options.key?(:connections_per_local_node)
         | 
| 688 699 | 
             
                  connections_per_node = options[:connections_per_local_node]
         | 
| @@ -726,7 +737,31 @@ module Cassandra | |
| 726 737 | 
             
                    end
         | 
| 727 738 | 
             
                  end
         | 
| 728 739 | 
             
                end
         | 
| 729 | 
            -
             | 
| 740 | 
            +
             | 
| 741 | 
            +
                # Get host addresses.
         | 
| 742 | 
            +
                hosts = []
         | 
| 743 | 
            +
             | 
| 744 | 
            +
                Array(options.fetch(:hosts, '127.0.0.1')).each do |host|
         | 
| 745 | 
            +
                  case host
         | 
| 746 | 
            +
                  when ::IPAddr
         | 
| 747 | 
            +
                    hosts << host
         | 
| 748 | 
            +
                  when ::String # ip address or hostname
         | 
| 749 | 
            +
                    Resolv.each_address(host) do |ip|
         | 
| 750 | 
            +
                      hosts << ::IPAddr.new(ip)
         | 
| 751 | 
            +
                    end
         | 
| 752 | 
            +
                  else
         | 
| 753 | 
            +
                    raise ::ArgumentError, ":hosts must be String or IPAddr, #{host.inspect} given"
         | 
| 754 | 
            +
                  end
         | 
| 755 | 
            +
                end
         | 
| 756 | 
            +
             | 
| 757 | 
            +
                if hosts.empty?
         | 
| 758 | 
            +
                  raise ::ArgumentError,
         | 
| 759 | 
            +
                        ":hosts #{options[:hosts].inspect} could not be resolved to any ip address"
         | 
| 760 | 
            +
                end
         | 
| 761 | 
            +
             | 
| 762 | 
            +
                hosts.shuffle!
         | 
| 763 | 
            +
             | 
| 764 | 
            +
                [options, hosts]
         | 
| 730 765 | 
             
              end
         | 
| 731 766 |  | 
| 732 767 | 
             
              # @private
         | 
| @@ -767,6 +802,7 @@ require 'cassandra/null_logger' | |
| 767 802 | 
             
            require 'cassandra/executors'
         | 
| 768 803 | 
             
            require 'cassandra/future'
         | 
| 769 804 | 
             
            require 'cassandra/cluster'
         | 
| 805 | 
            +
            require 'cassandra/custom_data'
         | 
| 770 806 | 
             
            require 'cassandra/driver'
         | 
| 771 807 | 
             
            require 'cassandra/host'
         | 
| 772 808 | 
             
            require 'cassandra/session'
         | 
| @@ -793,12 +829,18 @@ require 'cassandra/load_balancing' | |
| 793 829 | 
             
            require 'cassandra/reconnection'
         | 
| 794 830 | 
             
            require 'cassandra/retry'
         | 
| 795 831 | 
             
            require 'cassandra/address_resolution'
         | 
| 832 | 
            +
            require 'cassandra/timestamp_generator'
         | 
| 796 833 |  | 
| 797 834 | 
             
            require 'cassandra/util'
         | 
| 798 835 |  | 
| 799 836 | 
             
            # murmur3 hash extension
         | 
| 800 837 | 
             
            require 'cassandra_murmur3'
         | 
| 801 838 |  | 
| 839 | 
            +
            # SortedSet has a race condition where it does some class/global initialization when the first instance is created.
         | 
| 840 | 
            +
            # If this is done in a multi-threaded environment, bad things can happen. So force the initialization here,
         | 
| 841 | 
            +
            # when loading the C* module.
         | 
| 842 | 
            +
            ::SortedSet.new
         | 
| 843 | 
            +
             | 
| 802 844 | 
             
            module Cassandra
         | 
| 803 845 | 
             
              # @private
         | 
| 804 846 | 
             
              VOID_STATEMENT = Statements::Void.new
         | 
    
        data/lib/cassandra/auth.rb
    CHANGED
    
    | @@ -34,7 +34,7 @@ module Cassandra | |
| 34 34 | 
             
                #
         | 
| 35 35 | 
             
                # @see Cassandra::Auth::Providers
         | 
| 36 36 | 
             
                class Provider
         | 
| 37 | 
            -
                  # @!method create_authenticator(authentication_class,  | 
| 37 | 
            +
                  # @!method create_authenticator(authentication_class, host)
         | 
| 38 38 | 
             
                  #
         | 
| 39 39 | 
             
                  # Create a new authenticator object. This method will be called once per
         | 
| 40 40 | 
             
                  # connection that requires authentication. The auth provider can create
         | 
| @@ -45,6 +45,8 @@ module Cassandra | |
| 45 45 | 
             
                  #
         | 
| 46 46 | 
             
                  # @param authentication_class [String] the authentication class used by
         | 
| 47 47 | 
             
                  #   the server.
         | 
| 48 | 
            +
                  # @param host [Cassandra::Host] the node to whom we're authenticating.
         | 
| 49 | 
            +
                  #
         | 
| 48 50 | 
             
                  # @return [Cassandra::Auth::Authenticator, nil] an object with an
         | 
| 49 51 | 
             
                  #   interface matching {Cassandra::Auth::Authenticator} or `nil` if the
         | 
| 50 52 | 
             
                  #   authentication class is not supported.
         | 
    
        data/lib/cassandra/cluster.rb
    CHANGED
    
    | @@ -41,7 +41,8 @@ module Cassandra | |
| 41 41 | 
             
                               retry_policy,
         | 
| 42 42 | 
             
                               address_resolution_policy,
         | 
| 43 43 | 
             
                               connector,
         | 
| 44 | 
            -
                               futures_factory | 
| 44 | 
            +
                               futures_factory,
         | 
| 45 | 
            +
                               timestamp_generator)
         | 
| 45 46 | 
             
                  @logger                = logger
         | 
| 46 47 | 
             
                  @io_reactor            = io_reactor
         | 
| 47 48 | 
             
                  @executor              = executor
         | 
| @@ -57,6 +58,7 @@ module Cassandra | |
| 57 58 | 
             
                  @address_resolver      = address_resolution_policy
         | 
| 58 59 | 
             
                  @connector             = connector
         | 
| 59 60 | 
             
                  @futures               = futures_factory
         | 
| 61 | 
            +
                  @timestamp_generator   = timestamp_generator
         | 
| 60 62 |  | 
| 61 63 | 
             
                  @control_connection.on_close do |_cause|
         | 
| 62 64 | 
             
                    begin
         | 
| @@ -204,7 +206,8 @@ module Cassandra | |
| 204 206 | 
             
                                       @retry_policy,
         | 
| 205 207 | 
             
                                       @address_resolver,
         | 
| 206 208 | 
             
                                       @connection_options,
         | 
| 207 | 
            -
                                       @futures | 
| 209 | 
            +
                                       @futures,
         | 
| 210 | 
            +
                                       @timestamp_generator)
         | 
| 208 211 | 
             
                  session = Session.new(client, @execution_options, @futures)
         | 
| 209 212 | 
             
                  promise = @futures.promise
         | 
| 210 213 |  | 
| @@ -275,7 +278,15 @@ module Cassandra | |
| 275 278 |  | 
| 276 279 | 
             
                # @private
         | 
| 277 280 | 
             
                def inspect
         | 
| 278 | 
            -
                  "#<#{self.class.name}:0x#{object_id.to_s(16)} | 
| 281 | 
            +
                  "#<#{self.class.name}:0x#{object_id.to_s(16)} " \
         | 
| 282 | 
            +
                  "name=#{name.inspect}, " \
         | 
| 283 | 
            +
                  "port=#{@connection_options.port}, " \
         | 
| 284 | 
            +
                  "protocol_version=#{@connection_options.protocol_version}, " \
         | 
| 285 | 
            +
                  "load_balancing_policy=#{@load_balancing_policy.inspect}, " \
         | 
| 286 | 
            +
                  "consistency=#{@execution_options.consistency.inspect}, " \
         | 
| 287 | 
            +
                  "timeout=#{@execution_options.timeout.inspect}, " \
         | 
| 288 | 
            +
                  "hosts=#{hosts.inspect}, " \
         | 
| 289 | 
            +
                  "keyspaces=#{keyspaces.inspect}>"
         | 
| 279 290 | 
             
                end
         | 
| 280 291 | 
             
              end
         | 
| 281 292 | 
             
            end
         | 
| @@ -34,7 +34,8 @@ module Cassandra | |
| 34 34 | 
             
                                 retry_policy,
         | 
| 35 35 | 
             
                                 address_resolution_policy,
         | 
| 36 36 | 
             
                                 connection_options,
         | 
| 37 | 
            -
                                 futures_factory | 
| 37 | 
            +
                                 futures_factory,
         | 
| 38 | 
            +
                                 timestamp_generator)
         | 
| 38 39 | 
             
                    @logger                      = logger
         | 
| 39 40 | 
             
                    @registry                    = cluster_registry
         | 
| 40 41 | 
             
                    @schema                      = cluster_schema
         | 
| @@ -52,6 +53,7 @@ module Cassandra | |
| 52 53 | 
             
                    @pending_connections         = ::Hash.new
         | 
| 53 54 | 
             
                    @keyspace                    = nil
         | 
| 54 55 | 
             
                    @state                       = :idle
         | 
| 56 | 
            +
                    @timestamp_generator         = timestamp_generator
         | 
| 55 57 |  | 
| 56 58 | 
             
                    mon_initialize
         | 
| 57 59 | 
             
                  end
         | 
| @@ -228,11 +230,7 @@ module Cassandra | |
| 228 230 | 
             
                          'Apache Cassandra'))
         | 
| 229 231 | 
             
                    end
         | 
| 230 232 |  | 
| 231 | 
            -
                    timestamp =  | 
| 232 | 
            -
                    if @connection_options.client_timestamps? &&
         | 
| 233 | 
            -
                       @connection_options.protocol_version > 2
         | 
| 234 | 
            -
                      timestamp = ::Time.now
         | 
| 235 | 
            -
                    end
         | 
| 233 | 
            +
                    timestamp = @timestamp_generator.next if @timestamp_generator && @connection_options.protocol_version > 2
         | 
| 236 234 | 
             
                    payload   = nil
         | 
| 237 235 | 
             
                    payload   = options.payload if @connection_options.protocol_version >= 4
         | 
| 238 236 | 
             
                    request   = Protocol::QueryRequest.new(statement.cql,
         | 
| @@ -286,11 +284,7 @@ module Cassandra | |
| 286 284 | 
             
                  end
         | 
| 287 285 |  | 
| 288 286 | 
             
                  def execute(statement, options)
         | 
| 289 | 
            -
                    timestamp =  | 
| 290 | 
            -
                    if @connection_options.client_timestamps? &&
         | 
| 291 | 
            -
                       @connection_options.protocol_version > 2
         | 
| 292 | 
            -
                      timestamp = ::Time.now
         | 
| 293 | 
            -
                    end
         | 
| 287 | 
            +
                    timestamp = @timestamp_generator.next if @timestamp_generator && @connection_options.protocol_version > 2
         | 
| 294 288 | 
             
                    payload         = nil
         | 
| 295 289 | 
             
                    payload         = options.payload if @connection_options.protocol_version >= 4
         | 
| 296 290 | 
             
                    timeout         = options.timeout
         | 
| @@ -324,11 +318,7 @@ module Cassandra | |
| 324 318 | 
             
                          'Apache Cassandra'))
         | 
| 325 319 | 
             
                    end
         | 
| 326 320 |  | 
| 327 | 
            -
                    timestamp =  | 
| 328 | 
            -
                    if @connection_options.client_timestamps? &&
         | 
| 329 | 
            -
                       @connection_options.protocol_version > 2
         | 
| 330 | 
            -
                      timestamp = ::Time.now
         | 
| 331 | 
            -
                    end
         | 
| 321 | 
            +
                    timestamp = @timestamp_generator.next if @timestamp_generator && @connection_options.protocol_version > 2
         | 
| 332 322 | 
             
                    payload   = nil
         | 
| 333 323 | 
             
                    payload   = options.payload if @connection_options.protocol_version >= 4
         | 
| 334 324 | 
             
                    timeout   = options.timeout
         | 
| @@ -644,7 +634,15 @@ module Cassandra | |
| 644 634 | 
             
                                                       errors,
         | 
| 645 635 | 
             
                                                       hosts)
         | 
| 646 636 | 
             
                    cql = statement.cql
         | 
| 647 | 
            -
                    id | 
| 637 | 
            +
                    id = nil
         | 
| 638 | 
            +
                    host_is_up = true
         | 
| 639 | 
            +
                    synchronize do
         | 
| 640 | 
            +
                      if @prepared_statements[host].nil?
         | 
| 641 | 
            +
                        host_is_up = false
         | 
| 642 | 
            +
                      else
         | 
| 643 | 
            +
                        id = @prepared_statements[host][cql]
         | 
| 644 | 
            +
                      end
         | 
| 645 | 
            +
                    end
         | 
| 648 646 |  | 
| 649 647 | 
             
                    if id
         | 
| 650 648 | 
             
                      request.id = id
         | 
| @@ -659,6 +657,19 @@ module Cassandra | |
| 659 657 | 
             
                                              timeout,
         | 
| 660 658 | 
             
                                              errors,
         | 
| 661 659 | 
             
                                              hosts)
         | 
| 660 | 
            +
                    elsif !host_is_up
         | 
| 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)
         | 
| 662 673 | 
             
                    else
         | 
| 663 674 | 
             
                      prepare = prepare_statement(host, connection, cql, timeout)
         | 
| 664 675 | 
             
                      prepare.on_complete do |_|
         | 
| @@ -816,10 +827,29 @@ module Cassandra | |
| 816 827 | 
             
                      cql = statement.cql
         | 
| 817 828 |  | 
| 818 829 | 
             
                      if statement.is_a?(Statements::Bound)
         | 
| 819 | 
            -
                         | 
| 830 | 
            +
                        host_is_up = true
         | 
| 831 | 
            +
                        id = nil
         | 
| 832 | 
            +
                        synchronize do
         | 
| 833 | 
            +
                          if @prepared_statements[host].nil?
         | 
| 834 | 
            +
                            host_is_up = false
         | 
| 835 | 
            +
                          else
         | 
| 836 | 
            +
                            id = @prepared_statements[host][cql]
         | 
| 837 | 
            +
                          end
         | 
| 838 | 
            +
                        end
         | 
| 820 839 |  | 
| 821 840 | 
             
                        if id
         | 
| 822 841 | 
             
                          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)
         | 
| 823 853 | 
             
                        else
         | 
| 824 854 | 
             
                          unprepared[cql] << statement
         | 
| 825 855 | 
             
                        end
         | 
| @@ -1156,17 +1186,17 @@ module Cassandra | |
| 1156 1186 | 
             
                          end
         | 
| 1157 1187 | 
             
                        when Protocol::SetKeyspaceResultResponse
         | 
| 1158 1188 | 
             
                          @keyspace = r.keyspace
         | 
| 1159 | 
            -
                          promise.fulfill(Results::Void.new(r.custom_payload,
         | 
| 1160 | 
            -
             | 
| 1161 | 
            -
             | 
| 1162 | 
            -
             | 
| 1163 | 
            -
             | 
| 1164 | 
            -
             | 
| 1165 | 
            -
             | 
| 1166 | 
            -
             | 
| 1167 | 
            -
             | 
| 1168 | 
            -
             | 
| 1169 | 
            -
             | 
| 1189 | 
            +
                          promise.fulfill(Cassandra::Results::Void.new(r.custom_payload,
         | 
| 1190 | 
            +
                                                                       r.warnings,
         | 
| 1191 | 
            +
                                                                       r.trace_id,
         | 
| 1192 | 
            +
                                                                       keyspace,
         | 
| 1193 | 
            +
                                                                       statement,
         | 
| 1194 | 
            +
                                                                       options,
         | 
| 1195 | 
            +
                                                                       hosts,
         | 
| 1196 | 
            +
                                                                       request.consistency,
         | 
| 1197 | 
            +
                                                                       retries,
         | 
| 1198 | 
            +
                                                                       self,
         | 
| 1199 | 
            +
                                                                       @futures))
         | 
| 1170 1200 | 
             
                        when Protocol::PreparedResultResponse
         | 
| 1171 1201 | 
             
                          cql = request.cql
         | 
| 1172 1202 | 
             
                          synchronize do
         | 
| @@ -1328,7 +1358,7 @@ module Cassandra | |
| 1328 1358 | 
             
                            promise.fulfill(
         | 
| 1329 1359 | 
             
                              Results::Void.new(r.custom_payload,
         | 
| 1330 1360 | 
             
                                                r.warnings,
         | 
| 1331 | 
            -
                                                 | 
| 1361 | 
            +
                                                nil,
         | 
| 1332 1362 | 
             
                                                keyspace,
         | 
| 1333 1363 | 
             
                                                statement,
         | 
| 1334 1364 | 
             
                                                options,
         | 
| @@ -1360,38 +1390,44 @@ module Cassandra | |
| 1360 1390 | 
             
                      end
         | 
| 1361 1391 | 
             
                    else
         | 
| 1362 1392 | 
             
                      response_future.on_failure do |ex|
         | 
| 1363 | 
            -
                         | 
| 1364 | 
            -
             | 
| 1365 | 
            -
             | 
| 1366 | 
            -
                           | 
| 1367 | 
            -
             | 
| 1368 | 
            -
             | 
| 1369 | 
            -
             | 
| 1370 | 
            -
             | 
| 1371 | 
            -
             | 
| 1372 | 
            -
             | 
| 1373 | 
            -
             | 
| 1374 | 
            -
             | 
| 1375 | 
            -
             | 
| 1376 | 
            -
             | 
| 1377 | 
            -
             | 
| 1378 | 
            -
             | 
| 1379 | 
            -
             | 
| 1380 | 
            -
             | 
| 1381 | 
            -
             | 
| 1382 | 
            -
             | 
| 1383 | 
            -
             | 
| 1384 | 
            -
             | 
| 1385 | 
            -
             | 
| 1386 | 
            -
             | 
| 1387 | 
            -
             | 
| 1388 | 
            -
             | 
| 1389 | 
            -
             | 
| 1390 | 
            -
             | 
| 1391 | 
            -
             | 
| 1392 | 
            -
             | 
| 1393 | 
            -
             | 
| 1394 | 
            -
             | 
| 1393 | 
            +
                        if ex.is_a?(Errors::HostError) ||
         | 
| 1394 | 
            +
                            (ex.is_a?(Errors::TimeoutError) && statement.idempotent?)
         | 
| 1395 | 
            +
             | 
| 1396 | 
            +
                          errors[host] = ex
         | 
| 1397 | 
            +
                          case request
         | 
| 1398 | 
            +
                            when Protocol::QueryRequest, Protocol::PrepareRequest
         | 
| 1399 | 
            +
                              send_request_by_plan(promise,
         | 
| 1400 | 
            +
                                                   keyspace,
         | 
| 1401 | 
            +
                                                   statement,
         | 
| 1402 | 
            +
                                                   options,
         | 
| 1403 | 
            +
                                                   request,
         | 
| 1404 | 
            +
                                                   plan,
         | 
| 1405 | 
            +
                                                   timeout,
         | 
| 1406 | 
            +
                                                   errors,
         | 
| 1407 | 
            +
                                                   hosts)
         | 
| 1408 | 
            +
                            when Protocol::ExecuteRequest
         | 
| 1409 | 
            +
                              execute_by_plan(promise,
         | 
| 1410 | 
            +
                                              keyspace,
         | 
| 1411 | 
            +
                                              statement,
         | 
| 1412 | 
            +
                                              options,
         | 
| 1413 | 
            +
                                              request,
         | 
| 1414 | 
            +
                                              plan,
         | 
| 1415 | 
            +
                                              timeout,
         | 
| 1416 | 
            +
                                              errors,
         | 
| 1417 | 
            +
                                              hosts)
         | 
| 1418 | 
            +
                            when Protocol::BatchRequest
         | 
| 1419 | 
            +
                              batch_by_plan(promise,
         | 
| 1420 | 
            +
                                            keyspace,
         | 
| 1421 | 
            +
                                            statement,
         | 
| 1422 | 
            +
                                            options,
         | 
| 1423 | 
            +
                                            request,
         | 
| 1424 | 
            +
                                            plan,
         | 
| 1425 | 
            +
                                            timeout,
         | 
| 1426 | 
            +
                                            errors,
         | 
| 1427 | 
            +
                                            hosts)
         | 
| 1428 | 
            +
                            else
         | 
| 1429 | 
            +
                              promise.break(ex)
         | 
| 1430 | 
            +
                          end
         | 
| 1395 1431 | 
             
                        else
         | 
| 1396 1432 | 
             
                          promise.break(ex)
         | 
| 1397 1433 | 
             
                        end
         |