cassandra-driver 3.0.0.beta.1-java → 3.0.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (138) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +106 -39
  3. data/lib/cassandra.rb +396 -148
  4. data/lib/cassandra/address_resolution.rb +1 -1
  5. data/lib/cassandra/address_resolution/policies/ec2_multi_region.rb +1 -1
  6. data/lib/cassandra/address_resolution/policies/none.rb +1 -1
  7. data/lib/cassandra/aggregate.rb +21 -7
  8. data/lib/cassandra/argument.rb +2 -2
  9. data/lib/cassandra/attr_boolean.rb +33 -0
  10. data/lib/cassandra/auth.rb +6 -5
  11. data/lib/cassandra/auth/providers.rb +1 -1
  12. data/lib/cassandra/auth/providers/password.rb +5 -13
  13. data/lib/cassandra/cassandra_logger.rb +80 -0
  14. data/lib/cassandra/cluster.rb +49 -9
  15. data/lib/cassandra/cluster/client.rb +835 -209
  16. data/lib/cassandra/cluster/connection_pool.rb +2 -2
  17. data/lib/cassandra/cluster/connector.rb +86 -27
  18. data/lib/cassandra/cluster/control_connection.rb +222 -95
  19. data/lib/cassandra/cluster/failed_connection.rb +1 -1
  20. data/lib/cassandra/cluster/metadata.rb +14 -8
  21. data/lib/cassandra/cluster/options.rb +68 -22
  22. data/lib/cassandra/cluster/registry.rb +81 -17
  23. data/lib/cassandra/cluster/schema.rb +70 -8
  24. data/lib/cassandra/cluster/schema/cql_type_parser.rb +15 -10
  25. data/lib/cassandra/cluster/schema/fetchers.rb +601 -241
  26. data/lib/cassandra/cluster/schema/fqcn_type_parser.rb +39 -38
  27. data/lib/cassandra/cluster/schema/partitioners.rb +1 -1
  28. data/lib/cassandra/cluster/schema/partitioners/murmur3.rb +6 -8
  29. data/lib/cassandra/cluster/schema/partitioners/ordered.rb +1 -1
  30. data/lib/cassandra/cluster/schema/partitioners/random.rb +1 -1
  31. data/lib/cassandra/cluster/schema/replication_strategies.rb +1 -1
  32. data/lib/cassandra/cluster/schema/replication_strategies/network_topology.rb +19 -18
  33. data/lib/cassandra/cluster/schema/replication_strategies/none.rb +1 -1
  34. data/lib/cassandra/cluster/schema/replication_strategies/simple.rb +1 -1
  35. data/lib/cassandra/column.rb +4 -23
  36. data/lib/cassandra/column_container.rb +322 -0
  37. data/lib/cassandra/compression.rb +1 -1
  38. data/lib/cassandra/compression/compressors/lz4.rb +7 -8
  39. data/lib/cassandra/compression/compressors/snappy.rb +4 -3
  40. data/lib/cassandra/driver.rb +107 -46
  41. data/lib/cassandra/errors.rb +303 -52
  42. data/lib/cassandra/execution/info.rb +16 -5
  43. data/lib/cassandra/execution/options.rb +102 -55
  44. data/lib/cassandra/execution/trace.rb +16 -9
  45. data/lib/cassandra/executors.rb +1 -1
  46. data/lib/cassandra/function.rb +19 -13
  47. data/lib/cassandra/function_collection.rb +85 -0
  48. data/lib/cassandra/future.rb +101 -49
  49. data/lib/cassandra/host.rb +25 -5
  50. data/lib/cassandra/index.rb +118 -0
  51. data/lib/cassandra/keyspace.rb +169 -33
  52. data/lib/cassandra/listener.rb +1 -1
  53. data/lib/cassandra/load_balancing.rb +2 -2
  54. data/lib/cassandra/load_balancing/policies.rb +1 -1
  55. data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +39 -25
  56. data/lib/cassandra/load_balancing/policies/round_robin.rb +8 -1
  57. data/lib/cassandra/load_balancing/policies/token_aware.rb +22 -13
  58. data/lib/cassandra/load_balancing/policies/white_list.rb +18 -5
  59. data/lib/cassandra/materialized_view.rb +90 -0
  60. data/lib/cassandra/null_logger.rb +27 -6
  61. data/lib/cassandra/protocol.rb +1 -1
  62. data/lib/cassandra/protocol/coder.rb +81 -42
  63. data/lib/cassandra/protocol/cql_byte_buffer.rb +58 -44
  64. data/lib/cassandra/protocol/cql_protocol_handler.rb +57 -54
  65. data/lib/cassandra/protocol/request.rb +6 -7
  66. data/lib/cassandra/protocol/requests/auth_response_request.rb +3 -3
  67. data/lib/cassandra/protocol/requests/batch_request.rb +17 -8
  68. data/lib/cassandra/protocol/requests/credentials_request.rb +3 -3
  69. data/lib/cassandra/protocol/requests/execute_request.rb +39 -20
  70. data/lib/cassandra/protocol/requests/options_request.rb +1 -1
  71. data/lib/cassandra/protocol/requests/prepare_request.rb +5 -5
  72. data/lib/cassandra/protocol/requests/query_request.rb +28 -23
  73. data/lib/cassandra/protocol/requests/register_request.rb +2 -2
  74. data/lib/cassandra/protocol/requests/startup_request.rb +8 -8
  75. data/lib/cassandra/protocol/requests/void_query_request.rb +1 -1
  76. data/lib/cassandra/protocol/response.rb +3 -4
  77. data/lib/cassandra/protocol/responses/already_exists_error_response.rb +12 -2
  78. data/lib/cassandra/protocol/responses/auth_challenge_response.rb +4 -5
  79. data/lib/cassandra/protocol/responses/auth_success_response.rb +4 -5
  80. data/lib/cassandra/protocol/responses/authenticate_response.rb +4 -5
  81. data/lib/cassandra/protocol/responses/error_response.rb +104 -17
  82. data/lib/cassandra/protocol/responses/event_response.rb +3 -4
  83. data/lib/cassandra/protocol/responses/function_failure_error_response.rb +13 -2
  84. data/lib/cassandra/protocol/responses/prepared_result_response.rb +14 -9
  85. data/lib/cassandra/protocol/responses/raw_rows_result_response.rb +14 -9
  86. data/lib/cassandra/protocol/responses/read_failure_error_response.rb +26 -4
  87. data/lib/cassandra/protocol/responses/read_timeout_error_response.rb +22 -3
  88. data/lib/cassandra/protocol/responses/ready_response.rb +6 -7
  89. data/lib/cassandra/protocol/responses/result_response.rb +11 -10
  90. data/lib/cassandra/protocol/responses/rows_result_response.rb +8 -7
  91. data/lib/cassandra/protocol/responses/schema_change_event_response.rb +8 -8
  92. data/lib/cassandra/protocol/responses/schema_change_result_response.rb +19 -13
  93. data/lib/cassandra/protocol/responses/set_keyspace_result_response.rb +5 -6
  94. data/lib/cassandra/protocol/responses/status_change_event_response.rb +5 -6
  95. data/lib/cassandra/protocol/responses/supported_response.rb +4 -5
  96. data/lib/cassandra/protocol/responses/topology_change_event_response.rb +4 -5
  97. data/lib/cassandra/protocol/responses/unavailable_error_response.rb +20 -3
  98. data/lib/cassandra/protocol/responses/unprepared_error_response.rb +11 -2
  99. data/lib/cassandra/protocol/responses/void_result_response.rb +4 -5
  100. data/lib/cassandra/protocol/responses/write_failure_error_response.rb +26 -4
  101. data/lib/cassandra/protocol/responses/write_timeout_error_response.rb +22 -3
  102. data/lib/cassandra/protocol/v1.rb +98 -37
  103. data/lib/cassandra/protocol/v3.rb +121 -50
  104. data/lib/cassandra/protocol/v4.rb +172 -68
  105. data/lib/cassandra/reconnection.rb +1 -1
  106. data/lib/cassandra/reconnection/policies.rb +1 -1
  107. data/lib/cassandra/reconnection/policies/constant.rb +2 -4
  108. data/lib/cassandra/reconnection/policies/exponential.rb +6 -6
  109. data/lib/cassandra/result.rb +55 -20
  110. data/lib/cassandra/retry.rb +8 -8
  111. data/lib/cassandra/retry/policies.rb +1 -1
  112. data/lib/cassandra/retry/policies/default.rb +1 -1
  113. data/lib/cassandra/retry/policies/downgrading_consistency.rb +4 -2
  114. data/lib/cassandra/retry/policies/fallthrough.rb +1 -1
  115. data/lib/cassandra/session.rb +24 -16
  116. data/lib/cassandra/statement.rb +1 -1
  117. data/lib/cassandra/statements.rb +1 -1
  118. data/lib/cassandra/statements/batch.rb +16 -10
  119. data/lib/cassandra/statements/bound.rb +10 -3
  120. data/lib/cassandra/statements/prepared.rb +62 -18
  121. data/lib/cassandra/statements/simple.rb +23 -10
  122. data/lib/cassandra/statements/void.rb +1 -1
  123. data/lib/cassandra/table.rb +53 -185
  124. data/lib/cassandra/time.rb +11 -6
  125. data/lib/cassandra/time_uuid.rb +12 -14
  126. data/lib/cassandra/timestamp_generator.rb +37 -0
  127. data/lib/cassandra/timestamp_generator/simple.rb +38 -0
  128. data/lib/cassandra/timestamp_generator/ticking_on_duplicate.rb +58 -0
  129. data/lib/cassandra/tuple.rb +4 -4
  130. data/lib/cassandra/types.rb +109 -71
  131. data/lib/cassandra/udt.rb +66 -50
  132. data/lib/cassandra/util.rb +155 -15
  133. data/lib/cassandra/uuid.rb +20 -21
  134. data/lib/cassandra/uuid/generator.rb +7 -5
  135. data/lib/cassandra/version.rb +2 -2
  136. data/lib/cassandra_murmur3.jar +0 -0
  137. data/lib/datastax/cassandra.rb +1 -1
  138. metadata +27 -16
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  #--
4
- # Copyright 2013-2015 DataStax, Inc.
4
+ # Copyright 2013-2016 DataStax, Inc.
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  #--
4
- # Copyright 2013-2015 DataStax, Inc.
4
+ # Copyright 2013-2016 DataStax, Inc.
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  #--
4
- # Copyright 2013-2015 DataStax, Inc.
4
+ # Copyright 2013-2016 DataStax, Inc.
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  #--
4
- # Copyright 2013-2015 DataStax, Inc.
4
+ # Copyright 2013-2016 DataStax, Inc.
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
@@ -40,7 +40,14 @@ module Cassandra
40
40
  attr_reader :final_function
41
41
 
42
42
  # @private
43
- def initialize(keyspace, name, type, argument_types, state_type, initial_state, state_function, final_function)
43
+ def initialize(keyspace,
44
+ name,
45
+ type,
46
+ argument_types,
47
+ state_type,
48
+ initial_state,
49
+ state_function,
50
+ final_function)
44
51
  @keyspace = keyspace
45
52
  @name = name
46
53
  @type = type
@@ -63,7 +70,7 @@ module Cassandra
63
70
  @state_function == other.state_function && \
64
71
  @final_function == other.final_function
65
72
  end
66
- alias :== :eql?
73
+ alias == eql?
67
74
 
68
75
  # @private
69
76
  def hash
@@ -83,12 +90,19 @@ module Cassandra
83
90
 
84
91
  # @private
85
92
  def inspect
86
- "#<Cassandra::Aggregate:0x#{self.object_id.to_s(16)} @keyspace=#{@keyspace.inspect}, @name=#{@name.inspect}, @type=#{@type.inspect}, @argument_types=#{@argument_types.inspect}, @initial_state=#{@initial_state.inspect}, @state_function=#{@state_function.inspect}, @final_function=#{@final_function.inspect}>"
93
+ "#<Cassandra::Aggregate:0x#{object_id.to_s(16)} " \
94
+ "@keyspace=#{@keyspace.inspect}, " \
95
+ "@name=#{@name.inspect}, " \
96
+ "@type=#{@type.inspect}, " \
97
+ "@argument_types=#{@argument_types.inspect}, " \
98
+ "@initial_state=#{@initial_state.inspect}, " \
99
+ "@state_function=#{@state_function.inspect}, " \
100
+ "@final_function=#{@final_function.inspect}>"
87
101
  end
88
102
 
89
103
  # @return [String] a cql representation of this aggregate
90
104
  def to_cql
91
- cql = "CREATE AGGREGATE simplex.average("
105
+ cql = 'CREATE AGGREGATE simplex.average('
92
106
  first = true
93
107
  @argument_types.each do |type|
94
108
  if first
@@ -98,12 +112,12 @@ module Cassandra
98
112
  end
99
113
  cql << type.to_s
100
114
  end
101
- cql << ")"
115
+ cql << ')'
102
116
  cql << "\n SFUNC #{@state_function.name}"
103
117
  cql << "\n STYPE #{@state_type}"
104
118
  cql << "\n FINALFUNC #{@final_function.name}" if @final_function
105
119
  cql << "\n INITCOND #{@initial_state}"
106
- cql << ";"
120
+ cql << ';'
107
121
  end
108
122
  end
109
123
  end
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  #--
4
- # Copyright 2013-2015 DataStax, Inc.
4
+ # Copyright 2013-2016 DataStax, Inc.
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
@@ -36,7 +36,7 @@ module Cassandra
36
36
  @name == other.name && \
37
37
  @type == other.type
38
38
  end
39
- alias :== :eql?
39
+ alias == eql?
40
40
 
41
41
  # @private
42
42
  def hash
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+
3
+ #--
4
+ # Copyright 2013-2016 DataStax, Inc.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #++
18
+
19
+ # This file monkey-patches Module to have an attr_boolean method to make it easy
20
+ # for classes to define boolean instance variables with "foo?" reader methods.
21
+ # Inspired by http://stackoverflow.com/questions/4013591/attr-reader-with-question-mark-in-a-name
22
+ module Cassandra
23
+ module AttrBoolean
24
+ def attr_boolean(*names)
25
+ names.each do |name|
26
+ define_method(:"#{name}?") do
27
+ res = instance_variable_get(:"@#{name}")
28
+ !res.nil? && res != false
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  #--
4
- # Copyright 2013-2015 DataStax, Inc.
4
+ # Copyright 2013-2016 DataStax, Inc.
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
@@ -18,9 +18,9 @@
18
18
 
19
19
  module Cassandra
20
20
  module Auth
21
- # An auth provider is a factory for {Cassandra::Auth::Authenticator authenticator} instances (or objects matching that interface). Its
22
- # {#create_authenticator} will be called once for each connection that
23
- # requires authentication.
21
+ # An auth provider is a factory for {Cassandra::Auth::Authenticator authenticator}
22
+ # instances (or objects matching that interface). Its {#create_authenticator} will
23
+ # be called once for each connection that requires authentication.
24
24
  #
25
25
  # If the authentication requires keeping state, keep that in the
26
26
  # authenticator instances, not in the auth provider.
@@ -59,7 +59,8 @@ module Cassandra
59
59
  # subclasses of this class, but need to implement the same methods. This
60
60
  # class exists only for documentation purposes.
61
61
  #
62
- # @see https://github.com/apache/cassandra/blob/cassandra-2.0.16/doc/native_protocol_v2.spec#L257-L273 Cassandra native protocol v2 SASL authentication
62
+ # @see https://github.com/apache/cassandra/blob/cassandra-2.0.16/doc/native_protocol_v2.spec#L257-L273 Cassandra
63
+ # native protocol v2 SASL authentication
63
64
  # @see Cassandra::Auth::Provider#create_authenticator
64
65
  class Authenticator
65
66
  # @!method initial_response
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright 2013-2015 DataStax, Inc.
2
+ # Copyright 2013-2016 DataStax, Inc.
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
5
5
  # you may not use this file except in compliance with the License.
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  #--
4
- # Copyright 2013-2015 DataStax, Inc.
4
+ # Copyright 2013-2016 DataStax, Inc.
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
@@ -53,20 +53,12 @@ module Cassandra
53
53
  @password = password
54
54
  end
55
55
 
56
- # Returns a Password Authenticator only if `org.apache.cassandra.auth.PasswordAuthenticator` is given.
57
- # @param authentication_class [String] must equal to `org.apache.cassandra.auth.PasswordAuthenticator`
58
- # @return [Cassandra::Auth::Authenticator] when `authentication_class == "org.apache.cassandra.auth.PasswordAuthenticator"`
59
- # @return [nil] for all other values of `authentication_class`
56
+ # Returns a Password Authenticator
57
+ # @param authentication_class [String] ignored
58
+ # @return [Cassandra::Auth::Authenticator]
60
59
  def create_authenticator(authentication_class)
61
- if authentication_class == PASSWORD_AUTHENTICATOR_FQCN
62
- Authenticator.new(@username, @password)
63
- end
60
+ Authenticator.new(@username, @password)
64
61
  end
65
-
66
- private
67
-
68
- # @private
69
- PASSWORD_AUTHENTICATOR_FQCN = 'org.apache.cassandra.auth.PasswordAuthenticator'.freeze
70
62
  end
71
63
  end
72
64
  end
@@ -0,0 +1,80 @@
1
+ # encoding: utf-8
2
+
3
+ #--
4
+ # Copyright 2013-2016 DataStax, Inc.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #++
18
+
19
+ require 'logger'
20
+ module Cassandra
21
+ # This class is a logger that may be used by the client to log the driver's actions.
22
+ # It is a subclass of the standard Ruby Logger class, so it is instantiated the
23
+ # same way.
24
+ #
25
+ # The format of log output is set to include the timestamp, thread-id, log severity,
26
+ # and message. <b>This format may change in newer versions of the driver to account
27
+ # for new/deprecated metadata.</b>
28
+ #
29
+ # @example Configuring {Cassandra::Cluster} to use a logger.
30
+ # cluster = Cassandra.cluster(logger: Cassandra::Logger.new($stderr))
31
+ #
32
+ # @example The log format may be changed the same way as in the standard Ruby Logger class
33
+ # logger = Cassandra::Logger.new($stderr)
34
+ # logger.formatter = proc { |severity, time, program_name, message|
35
+ # "[%s]: %s\n" % [severity, message]
36
+ # }
37
+ #
38
+ # @example Create a logger and use it in your own business logic
39
+ # logger = Cassandra::Logger.new($stderr)
40
+ # cluster = Cassandra.cluster(logger: logger)
41
+ # <various logic>
42
+ # logger.debug("something interesting happened.")
43
+
44
+ class Logger < ::Logger
45
+ # @private
46
+ # This class is mostly copied from the Ruby Logger::Format class.
47
+ class Formatter
48
+ Format = "[%s#%d] %5s: %s\n".freeze
49
+
50
+ def call(severity, time, _, msg)
51
+ format(Format,
52
+ format_datetime(time),
53
+ Thread.current.object_id,
54
+ severity,
55
+ msg2str(msg))
56
+ end
57
+
58
+ def format_datetime(time)
59
+ time.strftime('%H:%M:%S.') << format('%06d ', time.usec)
60
+ end
61
+
62
+ def msg2str(msg)
63
+ case msg
64
+ when ::String
65
+ msg
66
+ when ::Exception
67
+ "#{msg.message} (#{msg.class})\n" <<
68
+ (msg.backtrace || []).join("\n")
69
+ else
70
+ msg.inspect
71
+ end
72
+ end
73
+ end
74
+
75
+ def initialize(*args)
76
+ super(*args)
77
+ self.formatter = Formatter.new
78
+ end
79
+ end
80
+ end
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  #--
4
- # Copyright 2013-2015 DataStax, Inc.
4
+ # Copyright 2013-2016 DataStax, Inc.
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
@@ -17,7 +17,8 @@
17
17
  #++
18
18
 
19
19
  module Cassandra
20
- # Cluster represents a cassandra cluster. It serves as a {Cassandra::Session session factory} factory and a collection of metadata.
20
+ # Cluster represents a cassandra cluster. It serves as a
21
+ # {Cassandra::Session session factory} factory and a collection of metadata.
21
22
  #
22
23
  # @see Cassandra::Cluster#connect Creating a new session
23
24
  # @see Cassandra::Cluster#each_host Getting all peers in the cluster
@@ -26,7 +27,22 @@ module Cassandra
26
27
  extend Forwardable
27
28
 
28
29
  # @private
29
- def initialize(logger, io_reactor, executor, control_connection, cluster_registry, cluster_schema, cluster_metadata, execution_options, connection_options, load_balancing_policy, reconnection_policy, retry_policy, address_resolution_policy, connector, futures_factory)
30
+ def initialize(logger,
31
+ io_reactor,
32
+ executor,
33
+ control_connection,
34
+ cluster_registry,
35
+ cluster_schema,
36
+ cluster_metadata,
37
+ execution_options,
38
+ connection_options,
39
+ load_balancing_policy,
40
+ reconnection_policy,
41
+ retry_policy,
42
+ address_resolution_policy,
43
+ connector,
44
+ futures_factory,
45
+ timestamp_generator)
30
46
  @logger = logger
31
47
  @io_reactor = io_reactor
32
48
  @executor = executor
@@ -42,9 +58,14 @@ module Cassandra
42
58
  @address_resolver = address_resolution_policy
43
59
  @connector = connector
44
60
  @futures = futures_factory
61
+ @timestamp_generator = timestamp_generator
45
62
 
46
- @control_connection.on_close do |cause|
47
- @load_balancing_policy.teardown(self) rescue nil
63
+ @control_connection.on_close do |_cause|
64
+ begin
65
+ @load_balancing_policy.teardown(self)
66
+ rescue
67
+ nil
68
+ end
48
69
  end
49
70
  end
50
71
 
@@ -95,7 +116,7 @@ module Cassandra
95
116
  return self if r == @registry
96
117
  r
97
118
  end
98
- alias :hosts :each_host
119
+ alias hosts each_host
99
120
 
100
121
  # @!method host(address)
101
122
  # Find a host by its address
@@ -119,7 +140,7 @@ module Cassandra
119
140
  return self if r == @schema
120
141
  r
121
142
  end
122
- alias :keyspaces :each_keyspace
143
+ alias keyspaces each_keyspace
123
144
 
124
145
  # @!method keyspace(name)
125
146
  # Find a keyspace by name
@@ -175,7 +196,18 @@ module Cassandra
175
196
  return @futures.error(::ArgumentError.new("keyspace must be a string, #{keyspace.inspect} given"))
176
197
  end
177
198
 
178
- client = Client.new(@logger, @registry, @schema, @io_reactor, @connector, @load_balancing_policy, @reconnection_policy, @retry_policy, @address_resolver, @connection_options, @futures)
199
+ client = Client.new(@logger,
200
+ @registry,
201
+ @schema,
202
+ @io_reactor,
203
+ @connector,
204
+ @load_balancing_policy,
205
+ @reconnection_policy,
206
+ @retry_policy,
207
+ @address_resolver,
208
+ @connection_options,
209
+ @futures,
210
+ @timestamp_generator)
179
211
  session = Session.new(client, @execution_options, @futures)
180
212
  promise = @futures.promise
181
213
 
@@ -246,7 +278,15 @@ module Cassandra
246
278
 
247
279
  # @private
248
280
  def inspect
249
- "#<#{self.class.name}:0x#{self.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}>"
250
290
  end
251
291
  end
252
292
  end
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  #--
4
- # Copyright 2013-2015 DataStax, Inc.
4
+ # Copyright 2013-2016 DataStax, Inc.
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
@@ -24,7 +24,18 @@ module Cassandra
24
24
 
25
25
  attr_reader :keyspace
26
26
 
27
- def initialize(logger, cluster_registry, cluster_schema, io_reactor, connector, load_balancing_policy, reconnection_policy, retry_policy, address_resolution_policy, connection_options, futures_factory)
27
+ def initialize(logger,
28
+ cluster_registry,
29
+ cluster_schema,
30
+ io_reactor,
31
+ connector,
32
+ load_balancing_policy,
33
+ reconnection_policy,
34
+ retry_policy,
35
+ address_resolution_policy,
36
+ connection_options,
37
+ futures_factory,
38
+ timestamp_generator)
28
39
  @logger = logger
29
40
  @registry = cluster_registry
30
41
  @schema = cluster_schema
@@ -42,6 +53,7 @@ module Cassandra
42
53
  @pending_connections = ::Hash.new
43
54
  @keyspace = nil
44
55
  @state = :idle
56
+ @timestamp_generator = timestamp_generator
45
57
 
46
58
  mon_initialize
47
59
  end
@@ -65,7 +77,9 @@ module Cassandra
65
77
  when :remote
66
78
  pool_size = @connection_options.connections_per_remote_node
67
79
  else
68
- @logger.error("Not connecting to #{host.ip} - invalid load balancing distance. Distance must be one of #{LoadBalancing::DISTANCES.inspect}, #{distance.inspect} given")
80
+ @logger.error("Not connecting to #{host.ip} - invalid load balancing " \
81
+ 'distance. Distance must be one of ' \
82
+ "#{LoadBalancing::DISTANCES.inspect}, #{distance.inspect} given")
69
83
  next
70
84
  end
71
85
 
@@ -101,7 +115,9 @@ module Cassandra
101
115
  raise Errors::NoHostsAvailable.new(errors)
102
116
  else
103
117
  failed_connections.each do |f|
104
- connect_to_host_with_retry(f.host, connecting_hosts[f.host], @reconnection_policy.schedule)
118
+ connect_to_host_with_retry(f.host,
119
+ connecting_hosts[f.host],
120
+ @reconnection_policy.schedule)
105
121
  end
106
122
  end
107
123
 
@@ -119,18 +135,19 @@ module Cassandra
119
135
  return CLIENT_NOT_CONNECTED if @state == :idle
120
136
  return @closed_future if @state == :closed || @state == :closing
121
137
 
122
- state, @state = @state, :closing
138
+ state = @state
139
+ @state = :closing
123
140
  end
124
141
 
125
142
  @closed_future = begin
126
143
  @registry.remove_listener(self)
127
144
  @schema.remove_listener(self)
128
145
 
129
- if state == :connecting
130
- f = @connected_future.recover.flat_map { close_connections }
131
- else
132
- f = close_connections
133
- end
146
+ f = if state == :connecting
147
+ @connected_future.recover.flat_map { close_connections }
148
+ else
149
+ close_connections
150
+ end
134
151
 
135
152
  f.map(self)
136
153
  end
@@ -160,7 +177,9 @@ module Cassandra
160
177
  when :remote
161
178
  pool_size = @connection_options.connections_per_remote_node
162
179
  else
163
- @logger.error("Not connecting to #{host.ip} - invalid load balancing distance. Distance must be one of #{LoadBalancing::DISTANCES.inspect}, #{distance.inspect} given")
180
+ @logger.error("Not connecting to #{host.ip} - " \
181
+ 'invalid load balancing distance. Distance must be one of ' \
182
+ "#{LoadBalancing::DISTANCES.inspect}, #{distance.inspect} given")
164
183
  return Ione::Future.resolved
165
184
  end
166
185
 
@@ -177,7 +196,7 @@ module Cassandra
177
196
  pool = nil
178
197
 
179
198
  synchronize do
180
- return Ione::Future.resolved unless @connections.has_key?(host)
199
+ return Ione::Future.resolved unless @connections.key?(host)
181
200
 
182
201
  @pending_connections.delete(host) unless @pending_connections[host] > 0
183
202
  @prepared_statements.delete(host)
@@ -186,7 +205,7 @@ module Cassandra
186
205
  end
187
206
 
188
207
  if pool
189
- Ione::Future.all(*pool.snapshot.map! {|c| c.close}).map(nil)
208
+ Ione::Future.all(*pool.snapshot.map!(&:close)).map(nil)
190
209
  else
191
210
  Ione::Future.resolved
192
211
  end
@@ -203,29 +222,48 @@ module Cassandra
203
222
  nil
204
223
  end
205
224
 
206
-
207
225
  def query(statement, options)
208
- return @futures.error(Errors::ClientError.new("Positional arguments are not supported by the current version of Apache Cassandra")) if !statement.params.empty? && @connection_options.protocol_version == 1
226
+ if !statement.params.empty? && @connection_options.protocol_version == 1
227
+ return @futures.error(
228
+ Errors::ClientError.new(
229
+ 'Positional arguments are not supported by the current version of ' \
230
+ 'Apache Cassandra'))
231
+ end
209
232
 
210
- timestamp = nil
211
- timestamp = ::Time.now if @connection_options.client_timestamps? && @connection_options.protocol_version > 2
233
+ timestamp = @timestamp_generator.next if @timestamp_generator && @connection_options.protocol_version > 2
212
234
  payload = nil
213
- payload = options.payload if @connection_options.protocol_version >= 4
214
- request = Protocol::QueryRequest.new(statement.cql, statement.params, statement.params_types, options.consistency, options.serial_consistency, options.page_size, options.paging_state, options.trace?, statement.params_names, timestamp, payload)
235
+ payload = options.payload if @connection_options.protocol_version >= 4
236
+ request = Protocol::QueryRequest.new(statement.cql,
237
+ statement.params,
238
+ statement.params_types,
239
+ options.consistency,
240
+ options.serial_consistency,
241
+ options.page_size,
242
+ options.paging_state,
243
+ options.trace?,
244
+ statement.params_names,
245
+ timestamp,
246
+ payload)
215
247
  timeout = options.timeout
216
248
  promise = @futures.promise
217
249
 
218
250
  keyspace = @keyspace
219
251
  plan = @load_balancing_policy.plan(keyspace, statement, options)
220
252
 
221
- send_request_by_plan(promise, keyspace, statement, options, request, plan, timeout)
253
+ send_request_by_plan(promise,
254
+ keyspace,
255
+ statement,
256
+ options,
257
+ request,
258
+ plan,
259
+ timeout)
222
260
 
223
261
  promise.future
224
262
  end
225
263
 
226
264
  def prepare(cql, options)
227
265
  payload = nil
228
- payload = options.payload if @connection_options.protocol_version >= 4
266
+ payload = options.payload if @connection_options.protocol_version >= 4
229
267
  request = Protocol::PrepareRequest.new(cql, options.trace?, payload)
230
268
  timeout = options.timeout
231
269
  promise = @futures.promise
@@ -234,19 +272,34 @@ module Cassandra
234
272
  statement = VOID_STATEMENT
235
273
  plan = @load_balancing_policy.plan(keyspace, statement, options)
236
274
 
237
- send_request_by_plan(promise, keyspace, statement, options, request, plan, timeout)
275
+ send_request_by_plan(promise,
276
+ keyspace,
277
+ statement,
278
+ options,
279
+ request,
280
+ plan,
281
+ timeout)
238
282
 
239
283
  promise.future
240
284
  end
241
285
 
242
286
  def execute(statement, options)
243
- timestamp = nil
244
- timestamp = ::Time.now if @connection_options.client_timestamps? && @connection_options.protocol_version > 2
287
+ timestamp = @timestamp_generator.next if @timestamp_generator && @connection_options.protocol_version > 2
245
288
  payload = nil
246
- payload = options.payload if @connection_options.protocol_version >= 4
289
+ payload = options.payload if @connection_options.protocol_version >= 4
247
290
  timeout = options.timeout
248
291
  result_metadata = statement.result_metadata
249
- request = Protocol::ExecuteRequest.new(nil, statement.params_types, statement.params, result_metadata.nil?, options.consistency, options.serial_consistency, options.page_size, options.paging_state, options.trace?, timestamp, payload)
292
+ request = Protocol::ExecuteRequest.new(nil,
293
+ statement.params_types,
294
+ statement.params,
295
+ result_metadata.nil?,
296
+ options.consistency,
297
+ options.serial_consistency,
298
+ options.page_size,
299
+ options.paging_state,
300
+ options.trace?,
301
+ timestamp,
302
+ payload)
250
303
  promise = @futures.promise
251
304
 
252
305
  keyspace = @keyspace
@@ -258,14 +311,23 @@ module Cassandra
258
311
  end
259
312
 
260
313
  def batch(statement, options)
261
- return @futures.error(Errors::ClientError.new("Batch statements are not supported by the current version of Apache Cassandra")) if @connection_options.protocol_version < 2
314
+ if @connection_options.protocol_version < 2
315
+ return @futures.error(
316
+ Errors::ClientError.new(
317
+ 'Batch statements are not supported by the current version of ' \
318
+ 'Apache Cassandra'))
319
+ end
262
320
 
263
- timestamp = nil
264
- timestamp = ::Time.now if @connection_options.client_timestamps? && @connection_options.protocol_version > 2
321
+ timestamp = @timestamp_generator.next if @timestamp_generator && @connection_options.protocol_version > 2
265
322
  payload = nil
266
- payload = options.payload if @connection_options.protocol_version >= 4
323
+ payload = options.payload if @connection_options.protocol_version >= 4
267
324
  timeout = options.timeout
268
- request = Protocol::BatchRequest.new(BATCH_TYPES[statement.type], options.consistency, options.trace?, options.serial_consistency, timestamp, payload)
325
+ request = Protocol::BatchRequest.new(BATCH_TYPES[statement.type],
326
+ options.consistency,
327
+ options.trace?,
328
+ options.serial_consistency,
329
+ timestamp,
330
+ payload)
269
331
  keyspace = @keyspace
270
332
  plan = @load_balancing_policy.plan(keyspace, statement, options)
271
333
  promise = @futures.promise
@@ -276,16 +338,16 @@ module Cassandra
276
338
  end
277
339
 
278
340
  def inspect
279
- "#<#{self.class.name}:0x#{self.object_id.to_s(16)}>"
341
+ "#<#{self.class.name}:0x#{object_id.to_s(16)}>"
280
342
  end
281
343
 
282
344
  private
283
345
 
284
346
  NO_CONNECTIONS = Ione::Future.resolved([])
285
347
  BATCH_TYPES = {
286
- :logged => Protocol::BatchRequest::LOGGED_TYPE,
287
- :unlogged => Protocol::BatchRequest::UNLOGGED_TYPE,
288
- :counter => Protocol::BatchRequest::COUNTER_TYPE,
348
+ logged: Protocol::BatchRequest::LOGGED_TYPE,
349
+ unlogged: Protocol::BatchRequest::UNLOGGED_TYPE,
350
+ counter: Protocol::BatchRequest::COUNTER_TYPE
289
351
  }.freeze
290
352
  CLIENT_CLOSED = Ione::Future.failed(Errors::ClientError.new('Client closed'))
291
353
  NOT_CONNECTED = Errors::ClientError.new('Client not connected')
@@ -299,8 +361,18 @@ module Cassandra
299
361
  BOOTSTRAPPING_ERROR_CODE = 0x1002
300
362
  UNPREPARED_ERROR_CODE = 0x2500
301
363
 
302
- SELECT_SCHEMA_PEERS = Protocol::QueryRequest.new("SELECT peer, rpc_address, schema_version FROM system.peers", EMPTY_LIST, EMPTY_LIST, :one)
303
- SELECT_SCHEMA_LOCAL = Protocol::QueryRequest.new("SELECT schema_version FROM system.local WHERE key='local'", EMPTY_LIST, EMPTY_LIST, :one)
364
+ SELECT_SCHEMA_PEERS =
365
+ Protocol::QueryRequest.new(
366
+ 'SELECT peer, rpc_address, schema_version FROM system.peers',
367
+ EMPTY_LIST,
368
+ EMPTY_LIST,
369
+ :one)
370
+ SELECT_SCHEMA_LOCAL =
371
+ Protocol::QueryRequest.new(
372
+ "SELECT schema_version FROM system.local WHERE key='local'",
373
+ EMPTY_LIST,
374
+ EMPTY_LIST,
375
+ :one)
304
376
 
305
377
  def connected(f)
306
378
  if f.resolved?
@@ -339,7 +411,7 @@ module Cassandra
339
411
  def close_connections
340
412
  futures = []
341
413
  synchronize do
342
- @connections.each do |host, connections|
414
+ @connections.each do |_host, connections|
343
415
  connections.snapshot.each do |c|
344
416
  futures << c.close
345
417
  end
@@ -351,7 +423,8 @@ module Cassandra
351
423
 
352
424
  def connect_to_host_maybe_retry(host, pool_size)
353
425
  connect_to_host(host, pool_size).fallback do |e|
354
- @logger.error("Scheduling initial connection retry to #{host.ip} (#{e.class.name}: #{e.message})")
426
+ @logger.error('Scheduling initial connection retry to ' \
427
+ "#{host.ip} (#{e.class.name}: #{e.message})")
355
428
  connect_to_host_with_retry(host, pool_size, @reconnection_policy.schedule)
356
429
  end.map(nil)
357
430
  end
@@ -364,7 +437,8 @@ module Cassandra
364
437
  f = @reactor.schedule_timer(interval)
365
438
  f.flat_map do
366
439
  connect_to_host(host, pool_size).fallback do |e|
367
- @logger.error("Scheduling connection retry to #{host.ip} (#{e.class.name}: #{e.message})")
440
+ @logger.error('Scheduling connection retry to ' \
441
+ "#{host.ip} (#{e.class.name}: #{e.message})")
368
442
  connect_to_host_with_retry(host, pool_size, schedule)
369
443
  end
370
444
  end
@@ -390,7 +464,8 @@ module Cassandra
390
464
  size -= @pending_connections[host]
391
465
 
392
466
  if size <= 0
393
- @logger.info("Not connecting to #{host.ip} - host is already pending connections")
467
+ @logger.info("Not connecting to #{host.ip} - " \
468
+ 'host is already pending connections')
394
469
  return NO_CONNECTIONS
395
470
  end
396
471
 
@@ -439,7 +514,7 @@ module Cassandra
439
514
  end
440
515
  end
441
516
  else
442
- connections.each {|c| c.close}
517
+ connections.each(&:close)
443
518
  end
444
519
 
445
520
  if error
@@ -450,7 +525,15 @@ module Cassandra
450
525
  end
451
526
  end
452
527
 
453
- def execute_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors = nil, hosts = [])
528
+ def execute_by_plan(promise,
529
+ keyspace,
530
+ statement,
531
+ options,
532
+ request,
533
+ plan,
534
+ timeout,
535
+ errors = nil,
536
+ hosts = [])
454
537
  unless plan.has_next?
455
538
  promise.break(Errors::NoHostsAvailable.new(errors))
456
539
  return
@@ -463,7 +546,15 @@ module Cassandra
463
546
  unless pool
464
547
  errors ||= {}
465
548
  errors[host] = NOT_CONNECTED
466
- return execute_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
549
+ return execute_by_plan(promise,
550
+ keyspace,
551
+ statement,
552
+ options,
553
+ request,
554
+ plan,
555
+ timeout,
556
+ errors,
557
+ hosts)
467
558
  end
468
559
 
469
560
  connection = pool.random_connection
@@ -472,13 +563,32 @@ module Cassandra
472
563
  switch = switch_keyspace(connection, keyspace, timeout)
473
564
  switch.on_complete do |s|
474
565
  if s.resolved?
475
- prepare_and_send_request_by_plan(host, connection, promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
566
+ prepare_and_send_request_by_plan(host,
567
+ connection,
568
+ promise,
569
+ keyspace,
570
+ statement,
571
+ options,
572
+ request,
573
+ plan,
574
+ timeout,
575
+ errors,
576
+ hosts)
476
577
  else
477
578
  s.on_failure do |e|
478
- if e.is_a?(Errors::HostError) || (e.is_a?(Errors::TimeoutError) && statement.idempotent?)
579
+ if e.is_a?(Errors::HostError) ||
580
+ (e.is_a?(Errors::TimeoutError) && statement.idempotent?)
479
581
  errors ||= {}
480
582
  errors[host] = e
481
- execute_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
583
+ execute_by_plan(promise,
584
+ keyspace,
585
+ statement,
586
+ options,
587
+ request,
588
+ plan,
589
+ timeout,
590
+ errors,
591
+ hosts)
482
592
  else
483
593
  promise.break(e)
484
594
  end
@@ -486,33 +596,111 @@ module Cassandra
486
596
  end
487
597
  end
488
598
  else
489
- prepare_and_send_request_by_plan(host, connection, promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
599
+ prepare_and_send_request_by_plan(host,
600
+ connection,
601
+ promise,
602
+ keyspace,
603
+ statement,
604
+ options,
605
+ request,
606
+ plan,
607
+ timeout,
608
+ errors,
609
+ hosts)
490
610
  end
491
611
  rescue => e
492
612
  errors ||= {}
493
613
  errors[host] = e
494
- execute_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
614
+ execute_by_plan(promise,
615
+ keyspace,
616
+ statement,
617
+ options,
618
+ request,
619
+ plan,
620
+ timeout,
621
+ errors,
622
+ hosts)
495
623
  end
496
624
 
497
- def prepare_and_send_request_by_plan(host, connection, promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
625
+ def prepare_and_send_request_by_plan(host,
626
+ connection,
627
+ promise,
628
+ keyspace,
629
+ statement,
630
+ options,
631
+ request,
632
+ plan,
633
+ timeout,
634
+ errors,
635
+ hosts)
498
636
  cql = statement.cql
499
- id = synchronize { @prepared_statements[host][cql] }
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
500
646
 
501
647
  if id
502
648
  request.id = id
503
- do_send_request_by_plan(host, connection, promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
649
+ do_send_request_by_plan(host,
650
+ connection,
651
+ promise,
652
+ keyspace,
653
+ statement,
654
+ options,
655
+ request,
656
+ plan,
657
+ timeout,
658
+ errors,
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)
504
673
  else
505
674
  prepare = prepare_statement(host, connection, cql, timeout)
506
675
  prepare.on_complete do |_|
507
676
  if prepare.resolved?
508
677
  request.id = prepare.value
509
- do_send_request_by_plan(host, connection, promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
678
+ do_send_request_by_plan(host,
679
+ connection,
680
+ promise,
681
+ keyspace,
682
+ statement,
683
+ options,
684
+ request,
685
+ plan,
686
+ timeout,
687
+ errors,
688
+ hosts)
510
689
  else
511
690
  prepare.on_failure do |e|
512
- if e.is_a?(Errors::HostError) || (e.is_a?(Errors::TimeoutError) && statement.idempotent?)
691
+ if e.is_a?(Errors::HostError) ||
692
+ (e.is_a?(Errors::TimeoutError) && statement.idempotent?)
513
693
  errors ||= {}
514
694
  errors[host] = e
515
- execute_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
695
+ execute_by_plan(promise,
696
+ keyspace,
697
+ statement,
698
+ options,
699
+ request,
700
+ plan,
701
+ timeout,
702
+ errors,
703
+ hosts)
516
704
  else
517
705
  promise.break(e)
518
706
  end
@@ -524,7 +712,15 @@ module Cassandra
524
712
  promise.break(e)
525
713
  end
526
714
 
527
- def batch_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors = nil, hosts = [])
715
+ def batch_by_plan(promise,
716
+ keyspace,
717
+ statement,
718
+ options,
719
+ request,
720
+ plan,
721
+ timeout,
722
+ errors = nil,
723
+ hosts = [])
528
724
  unless plan.has_next?
529
725
  promise.break(Errors::NoHostsAvailable.new(errors))
530
726
  return
@@ -537,7 +733,15 @@ module Cassandra
537
733
  unless pool
538
734
  errors ||= {}
539
735
  errors[host] = NOT_CONNECTED
540
- return batch_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
736
+ return batch_by_plan(promise,
737
+ keyspace,
738
+ statement,
739
+ options,
740
+ request,
741
+ plan,
742
+ timeout,
743
+ errors,
744
+ hosts)
541
745
  end
542
746
 
543
747
  connection = pool.random_connection
@@ -546,13 +750,32 @@ module Cassandra
546
750
  switch = switch_keyspace(connection, keyspace, timeout)
547
751
  switch.on_complete do |s|
548
752
  if s.resolved?
549
- batch_and_send_request_by_plan(host, connection, promise, keyspace, statement, request, options, plan, timeout, errors, hosts)
753
+ batch_and_send_request_by_plan(host,
754
+ connection,
755
+ promise,
756
+ keyspace,
757
+ statement,
758
+ request,
759
+ options,
760
+ plan,
761
+ timeout,
762
+ errors,
763
+ hosts)
550
764
  else
551
765
  s.on_failure do |e|
552
- if e.is_a?(Errors::HostError) || (e.is_a?(Errors::TimeoutError) && statement.idempotent?)
766
+ if e.is_a?(Errors::HostError) ||
767
+ (e.is_a?(Errors::TimeoutError) && statement.idempotent?)
553
768
  errors ||= {}
554
769
  errors[host] = e
555
- batch_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
770
+ batch_by_plan(promise,
771
+ keyspace,
772
+ statement,
773
+ options,
774
+ request,
775
+ plan,
776
+ timeout,
777
+ errors,
778
+ hosts)
556
779
  else
557
780
  promise.break(e)
558
781
  end
@@ -560,26 +783,73 @@ module Cassandra
560
783
  end
561
784
  end
562
785
  else
563
- batch_and_send_request_by_plan(host, connection, promise, keyspace, statement, request, options, plan, timeout, errors, hosts)
786
+ batch_and_send_request_by_plan(host,
787
+ connection,
788
+ promise,
789
+ keyspace,
790
+ statement,
791
+ request,
792
+ options,
793
+ plan,
794
+ timeout,
795
+ errors,
796
+ hosts)
564
797
  end
565
798
  rescue => e
566
799
  errors ||= {}
567
800
  errors[host] = e
568
- batch_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
801
+ batch_by_plan(promise,
802
+ keyspace,
803
+ statement,
804
+ options,
805
+ request,
806
+ plan,
807
+ timeout,
808
+ errors,
809
+ hosts)
569
810
  end
570
811
 
571
- def batch_and_send_request_by_plan(host, connection, promise, keyspace, statement, request, options, plan, timeout, errors, hosts)
812
+ def batch_and_send_request_by_plan(host,
813
+ connection,
814
+ promise,
815
+ keyspace,
816
+ batch_statement,
817
+ request,
818
+ options,
819
+ plan,
820
+ timeout,
821
+ errors,
822
+ hosts)
572
823
  request.clear
573
824
  unprepared = Hash.new {|hash, cql| hash[cql] = []}
574
825
 
575
- statement.statements.each do |statement|
826
+ batch_statement.statements.each do |statement|
576
827
  cql = statement.cql
577
828
 
578
829
  if statement.is_a?(Statements::Bound)
579
- id = synchronize { @prepared_statements[host][cql] }
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
580
839
 
581
840
  if id
582
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)
583
853
  else
584
854
  unprepared[cql] << statement
585
855
  end
@@ -589,7 +859,17 @@ module Cassandra
589
859
  end
590
860
 
591
861
  if unprepared.empty?
592
- do_send_request_by_plan(host, connection, promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
862
+ do_send_request_by_plan(host,
863
+ connection,
864
+ promise,
865
+ keyspace,
866
+ batch_statement,
867
+ options,
868
+ request,
869
+ plan,
870
+ timeout,
871
+ errors,
872
+ hosts)
593
873
  else
594
874
  to_prepare = unprepared.to_a
595
875
  futures = to_prepare.map do |cql, _|
@@ -601,17 +881,38 @@ module Cassandra
601
881
  prepared_ids = f.value
602
882
  to_prepare.each_with_index do |(_, statements), i|
603
883
  statements.each do |statement|
604
- request.add_prepared(prepared_ids[i], statement.params, statement.params_types)
884
+ request.add_prepared(prepared_ids[i],
885
+ statement.params,
886
+ statement.params_types)
605
887
  end
606
888
  end
607
889
 
608
- do_send_request_by_plan(host, connection, promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
890
+ do_send_request_by_plan(host,
891
+ connection,
892
+ promise,
893
+ keyspace,
894
+ batch_statement,
895
+ options,
896
+ request,
897
+ plan,
898
+ timeout,
899
+ errors,
900
+ hosts)
609
901
  else
610
902
  f.on_failure do |e|
611
- if e.is_a?(Errors::HostError) || (e.is_a?(Errors::TimeoutError) && statement.idempotent?)
903
+ if e.is_a?(Errors::HostError) ||
904
+ (e.is_a?(Errors::TimeoutError) && batch_statement.idempotent?)
612
905
  errors ||= {}
613
906
  errors[host] = e
614
- batch_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
907
+ batch_by_plan(promise,
908
+ keyspace,
909
+ batch_statement,
910
+ options,
911
+ request,
912
+ plan,
913
+ timeout,
914
+ errors,
915
+ hosts)
615
916
  else
616
917
  promise.break(e)
617
918
  end
@@ -621,7 +922,15 @@ module Cassandra
621
922
  end
622
923
  end
623
924
 
624
- def send_request_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors = nil, hosts = [])
925
+ def send_request_by_plan(promise,
926
+ keyspace,
927
+ statement,
928
+ options,
929
+ request,
930
+ plan,
931
+ timeout,
932
+ errors = nil,
933
+ hosts = [])
625
934
  unless plan.has_next?
626
935
  promise.break(Errors::NoHostsAvailable.new(errors))
627
936
  return
@@ -634,7 +943,15 @@ module Cassandra
634
943
  unless pool
635
944
  errors ||= {}
636
945
  errors[host] = NOT_CONNECTED
637
- return send_request_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
946
+ return send_request_by_plan(promise,
947
+ keyspace,
948
+ statement,
949
+ options,
950
+ request,
951
+ plan,
952
+ timeout,
953
+ errors,
954
+ hosts)
638
955
  end
639
956
 
640
957
  connection = pool.random_connection
@@ -643,13 +960,32 @@ module Cassandra
643
960
  switch = switch_keyspace(connection, keyspace, timeout)
644
961
  switch.on_complete do |s|
645
962
  if s.resolved?
646
- do_send_request_by_plan(host, connection, promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
963
+ do_send_request_by_plan(host,
964
+ connection,
965
+ promise,
966
+ keyspace,
967
+ statement,
968
+ options,
969
+ request,
970
+ plan,
971
+ timeout,
972
+ errors,
973
+ hosts)
647
974
  else
648
975
  s.on_failure do |e|
649
- if e.is_a?(Errors::HostError) || (e.is_a?(Errors::TimeoutError) && statement.idempotent?)
976
+ if e.is_a?(Errors::HostError) ||
977
+ (e.is_a?(Errors::TimeoutError) && statement.idempotent?)
650
978
  errors ||= {}
651
979
  errors[host] = e
652
- send_request_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
980
+ send_request_by_plan(promise,
981
+ keyspace,
982
+ statement,
983
+ options,
984
+ request,
985
+ plan,
986
+ timeout,
987
+ errors,
988
+ hosts)
653
989
  else
654
990
  promise.break(e)
655
991
  end
@@ -657,166 +993,447 @@ module Cassandra
657
993
  end
658
994
  end
659
995
  else
660
- do_send_request_by_plan(host, connection, promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
996
+ do_send_request_by_plan(host,
997
+ connection,
998
+ promise,
999
+ keyspace,
1000
+ statement,
1001
+ options,
1002
+ request,
1003
+ plan,
1004
+ timeout,
1005
+ errors,
1006
+ hosts)
661
1007
  end
662
1008
  rescue => e
663
1009
  errors ||= {}
664
1010
  errors[host] = e
665
- send_request_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
1011
+ send_request_by_plan(promise,
1012
+ keyspace,
1013
+ statement,
1014
+ options,
1015
+ request,
1016
+ plan,
1017
+ timeout,
1018
+ errors,
1019
+ hosts)
666
1020
  end
667
1021
 
668
- def do_send_request_by_plan(host, connection, promise, keyspace, statement, options, request, plan, timeout, errors, hosts, retries = 0)
1022
+ def do_send_request_by_plan(host,
1023
+ connection,
1024
+ promise,
1025
+ keyspace,
1026
+ statement,
1027
+ options,
1028
+ request,
1029
+ plan,
1030
+ timeout,
1031
+ errors,
1032
+ hosts,
1033
+ retries = 0)
669
1034
  request.retries = retries
670
1035
 
671
1036
  f = connection.send_request(request, timeout)
672
- f.on_complete do |f|
673
- if f.resolved?
674
- r = f.value
675
-
676
- begin
677
- decision = nil
678
-
679
- case r
680
- when Protocol::UnavailableErrorResponse
681
- decision = @retry_policy.unavailable(statement, r.consistency, r.required, r.alive, retries)
682
- when Protocol::WriteTimeoutErrorResponse
683
- decision = @retry_policy.write_timeout(statement, r.consistency, r.write_type, r.blockfor, r.received, retries)
684
- when Protocol::ReadTimeoutErrorResponse
685
- decision = @retry_policy.read_timeout(statement, r.consistency, r.blockfor, r.received, r.data_present, retries)
686
- when Protocol::UnpreparedErrorResponse
687
- cql = statement.cql
688
-
689
- synchronize do
690
- @preparing_statements[host].delete(cql)
691
- @prepared_statements[host].delete(cql)
692
- end
1037
+ f.on_complete do |response_future|
1038
+ errors ||= {}
1039
+ handle_response(response_future,
1040
+ host,
1041
+ connection,
1042
+ promise,
1043
+ keyspace,
1044
+ statement,
1045
+ options,
1046
+ request,
1047
+ plan,
1048
+ timeout,
1049
+ errors,
1050
+ hosts,
1051
+ retries)
1052
+ end
1053
+ rescue => e
1054
+ promise.break(e)
1055
+ end
693
1056
 
694
- prepare = prepare_statement(host, connection, cql, timeout)
695
- prepare.on_complete do |_|
696
- if prepare.resolved?
697
- request.id = prepare.value
698
- do_send_request_by_plan(host, connection, promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
699
- else
700
- prepare.on_failure do |e|
701
- if e.is_a?(Errors::HostError) || (e.is_a?(Errors::TimeoutError) && statement.idempotent?)
702
- errors ||= {}
703
- errors[host] = e
704
- execute_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
705
- else
706
- promise.break(e)
707
- end
708
- end
709
- end
710
- end
711
- when Protocol::ErrorResponse
712
- error = r.to_error(keyspace, statement, options, hosts, request.consistency, retries)
1057
+ def handle_response(response_future,
1058
+ host,
1059
+ connection,
1060
+ promise,
1061
+ keyspace,
1062
+ statement,
1063
+ options,
1064
+ request,
1065
+ plan,
1066
+ timeout,
1067
+ errors,
1068
+ hosts,
1069
+ retries)
1070
+ if response_future.resolved?
1071
+ r = response_future.value
1072
+
1073
+ begin
1074
+ decision = nil
1075
+
1076
+ case r
1077
+ when Protocol::UnavailableErrorResponse
1078
+ decision = @retry_policy.unavailable(statement,
1079
+ r.consistency,
1080
+ r.required,
1081
+ r.alive,
1082
+ retries)
1083
+ when Protocol::WriteTimeoutErrorResponse
1084
+ decision = @retry_policy.write_timeout(statement,
1085
+ r.consistency,
1086
+ r.write_type,
1087
+ r.blockfor,
1088
+ r.received,
1089
+ retries)
1090
+ when Protocol::ReadTimeoutErrorResponse
1091
+ decision = @retry_policy.read_timeout(statement,
1092
+ r.consistency,
1093
+ r.blockfor,
1094
+ r.received,
1095
+ r.data_present,
1096
+ retries)
1097
+ when Protocol::UnpreparedErrorResponse
1098
+ cql = statement.cql
1099
+
1100
+ synchronize do
1101
+ @preparing_statements[host].delete(cql)
1102
+ @prepared_statements[host].delete(cql)
1103
+ end
713
1104
 
714
- if error.is_a?(Errors::HostError) || (error.is_a?(Errors::TimeoutError) && statement.idempotent?)
715
- errors ||= {}
716
- errors[host] = error
717
-
718
- case request
719
- when Protocol::QueryRequest, Protocol::PrepareRequest
720
- send_request_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
721
- when Protocol::ExecuteRequest
722
- execute_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
723
- when Protocol::BatchRequest
724
- batch_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
725
- end
1105
+ prepare = prepare_statement(host, connection, cql, timeout)
1106
+ prepare.on_complete do |_|
1107
+ if prepare.resolved?
1108
+ request.id = prepare.value
1109
+ do_send_request_by_plan(host,
1110
+ connection,
1111
+ promise,
1112
+ keyspace,
1113
+ statement,
1114
+ options,
1115
+ request,
1116
+ plan,
1117
+ timeout,
1118
+ errors,
1119
+ hosts)
726
1120
  else
727
- promise.break(error)
728
- end
729
- when Protocol::SetKeyspaceResultResponse
730
- @keyspace = r.keyspace
731
- promise.fulfill(Results::Void.new(r.custom_payload, r.warnings, r.trace_id, keyspace, statement, options, hosts, request.consistency, retries, self, @futures))
732
- when Protocol::PreparedResultResponse
733
- cql = request.cql
734
- synchronize do
735
- @prepared_statements[host][cql] = r.id
736
- @preparing_statements[host].delete(cql)
737
- end
738
-
739
- metadata = r.metadata
740
- pk_idx = r.pk_idx
741
- pk_idx ||= @schema.get_pk_idx(metadata)
742
-
743
- promise.fulfill(Statements::Prepared.new(r.custom_payload, r.warnings, cql, metadata, r.result_metadata, pk_idx, r.trace_id, keyspace, statement, options, hosts, request.consistency, retries, self, @connection_options))
744
- when Protocol::RawRowsResultResponse
745
- r.materialize(statement.result_metadata)
746
- promise.fulfill(Results::Paged.new(r.custom_payload, r.warnings, r.rows, r.paging_state, r.trace_id, keyspace, statement, options, hosts, request.consistency, retries, self, @futures))
747
- when Protocol::RowsResultResponse
748
- promise.fulfill(Results::Paged.new(r.custom_payload, r.warnings, r.rows, r.paging_state, r.trace_id, keyspace, statement, options, hosts, request.consistency, retries, self, @futures))
749
- when Protocol::SchemaChangeResultResponse
750
- @schema.delete_keyspace(r.keyspace) if r.change == 'DROPPED' && r.target == Protocol::Constants::SCHEMA_CHANGE_TARGET_KEYSPACE
751
-
752
- @logger.debug('Waiting for schema to propagate to all hosts after a change')
753
- wait_for_schema_agreement(connection, @reconnection_policy.schedule).on_complete do |f|
754
- unless f.resolved?
755
- f.on_failure do |e|
756
- @logger.error("Schema agreement failure (#{e.class.name}: #{e.message})")
1121
+ prepare.on_failure do |e|
1122
+ if e.is_a?(Errors::HostError) ||
1123
+ (e.is_a?(Errors::TimeoutError) && statement.idempotent?)
1124
+ errors[host] = e
1125
+ execute_by_plan(promise,
1126
+ keyspace,
1127
+ statement,
1128
+ options,
1129
+ request,
1130
+ plan,
1131
+ timeout,
1132
+ errors,
1133
+ hosts)
1134
+ else
1135
+ promise.break(e)
757
1136
  end
758
1137
  end
759
- promise.fulfill(Results::Void.new(r.custom_payload, r.warnings, r.trace_id, keyspace, statement, options, hosts, request.consistency, retries, self, @futures))
1138
+ end
1139
+ end
1140
+ when Protocol::ErrorResponse
1141
+ error = r.to_error(keyspace,
1142
+ statement,
1143
+ options,
1144
+ hosts,
1145
+ request.consistency,
1146
+ retries)
1147
+
1148
+ if error.is_a?(Errors::HostError) ||
1149
+ (error.is_a?(Errors::TimeoutError) && statement.idempotent?)
1150
+ errors[host] = error
1151
+
1152
+ case request
1153
+ when Protocol::QueryRequest, Protocol::PrepareRequest
1154
+ send_request_by_plan(promise,
1155
+ keyspace,
1156
+ statement,
1157
+ options,
1158
+ request,
1159
+ plan,
1160
+ timeout,
1161
+ errors,
1162
+ hosts)
1163
+ when Protocol::ExecuteRequest
1164
+ execute_by_plan(promise,
1165
+ keyspace,
1166
+ statement,
1167
+ options,
1168
+ request,
1169
+ plan,
1170
+ timeout,
1171
+ errors,
1172
+ hosts)
1173
+ when Protocol::BatchRequest
1174
+ batch_by_plan(promise,
1175
+ keyspace,
1176
+ statement,
1177
+ options,
1178
+ request,
1179
+ plan,
1180
+ timeout,
1181
+ errors,
1182
+ hosts)
760
1183
  end
761
1184
  else
762
- promise.fulfill(Results::Void.new(r.custom_payload, r.warnings, r.trace_id, keyspace, statement, options, hosts, request.consistency, retries, self, @futures))
1185
+ promise.break(error)
1186
+ end
1187
+ when Protocol::SetKeyspaceResultResponse
1188
+ @keyspace = r.keyspace
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))
1200
+ when Protocol::PreparedResultResponse
1201
+ cql = request.cql
1202
+ synchronize do
1203
+ @prepared_statements[host][cql] = r.id
1204
+ @preparing_statements[host].delete(cql)
763
1205
  end
764
1206
 
765
- if decision
766
- case decision
767
- when Retry::Decisions::Retry
768
- request.consistency = decision.consistency
769
- do_send_request_by_plan(host, connection, promise, keyspace, statement, options, request, plan, timeout, errors, hosts, retries + 1)
770
- when Retry::Decisions::TryNextHost
771
- errors ||= {}
772
- errors[host] = r.to_error(keyspace, statement, options, hosts, request.consistency, retries)
773
- case request
774
- when Protocol::QueryRequest, Protocol::PrepareRequest
775
- send_request_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
776
- when Protocol::ExecuteRequest
777
- execute_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
778
- when Protocol::BatchRequest
779
- batch_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
780
- else
781
- promise.break(e)
1207
+ metadata = r.metadata
1208
+ pk_idx = r.pk_idx
1209
+ pk_idx ||= @schema.get_pk_idx(metadata)
1210
+
1211
+ promise.fulfill(
1212
+ Statements::Prepared.new(r.custom_payload,
1213
+ r.warnings,
1214
+ cql,
1215
+ metadata,
1216
+ r.result_metadata,
1217
+ pk_idx,
1218
+ r.trace_id,
1219
+ keyspace,
1220
+ statement,
1221
+ options,
1222
+ hosts,
1223
+ request.consistency,
1224
+ retries,
1225
+ self,
1226
+ @connection_options))
1227
+ when Protocol::RawRowsResultResponse
1228
+ r.materialize(statement.result_metadata)
1229
+ promise.fulfill(
1230
+ Results::Paged.new(r.custom_payload,
1231
+ r.warnings,
1232
+ r.rows,
1233
+ r.paging_state,
1234
+ r.trace_id,
1235
+ keyspace,
1236
+ statement,
1237
+ options,
1238
+ hosts,
1239
+ request.consistency,
1240
+ retries,
1241
+ self,
1242
+ @futures))
1243
+ when Protocol::RowsResultResponse
1244
+ promise.fulfill(
1245
+ Results::Paged.new(r.custom_payload,
1246
+ r.warnings,
1247
+ r.rows,
1248
+ r.paging_state,
1249
+ r.trace_id,
1250
+ keyspace,
1251
+ statement,
1252
+ options,
1253
+ hosts,
1254
+ request.consistency,
1255
+ retries,
1256
+ self,
1257
+ @futures))
1258
+ when Protocol::SchemaChangeResultResponse
1259
+ if r.change == 'DROPPED' &&
1260
+ r.target == Protocol::Constants::SCHEMA_CHANGE_TARGET_KEYSPACE
1261
+ @schema.delete_keyspace(r.keyspace)
1262
+ end
1263
+
1264
+ @logger.debug('Waiting for schema to propagate to all hosts after a change')
1265
+ wait_for_schema_agreement(connection,
1266
+ @reconnection_policy.schedule).on_complete do |f|
1267
+ unless f.resolved?
1268
+ f.on_failure do |e|
1269
+ @logger.error(
1270
+ "Schema agreement failure (#{e.class.name}: #{e.message})")
782
1271
  end
783
- when Retry::Decisions::Ignore
784
- promise.fulfill(Results::Void.new(r.custom_payload, r.warnings, r.trace_id, keyspace, statement, options, hosts, request.consistency, retries, self, @futures))
785
- when Retry::Decisions::Reraise
786
- promise.break(r.to_error(keyspace, statement, options, hosts, request.consistency, retries))
787
- else
788
- promise.break(r.to_error(keyspace, statement, options, hosts, request.consistency, retries))
789
1272
  end
1273
+ promise.fulfill(
1274
+ Results::Void.new(r.custom_payload,
1275
+ r.warnings,
1276
+ r.trace_id,
1277
+ keyspace,
1278
+ statement,
1279
+ options,
1280
+ hosts,
1281
+ request.consistency,
1282
+ retries,
1283
+ self,
1284
+ @futures))
790
1285
  end
791
- rescue => e
792
- promise.break(e)
1286
+ else
1287
+ promise.fulfill(Results::Void.new(r.custom_payload,
1288
+ r.warnings,
1289
+ r.trace_id,
1290
+ keyspace,
1291
+ statement,
1292
+ options,
1293
+ hosts,
1294
+ request.consistency,
1295
+ retries,
1296
+ self,
1297
+ @futures))
793
1298
  end
794
- else
795
- f.on_failure do |e|
796
- errors ||= {}
797
- errors[host] = e
798
- case request
799
- when Protocol::QueryRequest, Protocol::PrepareRequest
800
- send_request_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
801
- when Protocol::ExecuteRequest
802
- execute_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
803
- when Protocol::BatchRequest
804
- batch_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
1299
+
1300
+ if decision
1301
+ case decision
1302
+ when Retry::Decisions::Retry
1303
+ request.consistency = decision.consistency
1304
+ do_send_request_by_plan(host,
1305
+ connection,
1306
+ promise,
1307
+ keyspace,
1308
+ statement,
1309
+ options,
1310
+ request,
1311
+ plan,
1312
+ timeout,
1313
+ errors,
1314
+ hosts,
1315
+ retries + 1)
1316
+ when Retry::Decisions::TryNextHost
1317
+ errors[host] = r.to_error(keyspace,
1318
+ statement,
1319
+ options,
1320
+ hosts,
1321
+ request.consistency,
1322
+ retries)
1323
+ case request
1324
+ when Protocol::QueryRequest, Protocol::PrepareRequest
1325
+ send_request_by_plan(promise,
1326
+ keyspace,
1327
+ statement,
1328
+ options,
1329
+ request,
1330
+ plan,
1331
+ timeout,
1332
+ errors,
1333
+ hosts)
1334
+ when Protocol::ExecuteRequest
1335
+ execute_by_plan(promise,
1336
+ keyspace,
1337
+ statement,
1338
+ options,
1339
+ request,
1340
+ plan,
1341
+ timeout,
1342
+ errors,
1343
+ hosts)
1344
+ when Protocol::BatchRequest
1345
+ batch_by_plan(promise,
1346
+ keyspace,
1347
+ statement,
1348
+ options,
1349
+ request,
1350
+ plan,
1351
+ timeout,
1352
+ errors,
1353
+ hosts)
1354
+ else
1355
+ promise.break(e)
1356
+ end
1357
+ when Retry::Decisions::Ignore
1358
+ promise.fulfill(
1359
+ Results::Void.new(r.custom_payload,
1360
+ r.warnings,
1361
+ nil,
1362
+ keyspace,
1363
+ statement,
1364
+ options,
1365
+ hosts,
1366
+ request.consistency,
1367
+ retries,
1368
+ self,
1369
+ @futures))
1370
+ when Retry::Decisions::Reraise
1371
+ promise.break(
1372
+ r.to_error(keyspace,
1373
+ statement,
1374
+ options,
1375
+ hosts,
1376
+ request.consistency,
1377
+ retries))
805
1378
  else
806
- promise.break(e)
1379
+ promise.break(
1380
+ r.to_error(keyspace,
1381
+ statement,
1382
+ options,
1383
+ hosts,
1384
+ request.consistency,
1385
+ retries))
807
1386
  end
808
1387
  end
1388
+ rescue => e
1389
+ promise.break(e)
1390
+ end
1391
+ else
1392
+ response_future.on_failure do |ex|
1393
+ errors[host] = ex
1394
+ case request
1395
+ when Protocol::QueryRequest, Protocol::PrepareRequest
1396
+ send_request_by_plan(promise,
1397
+ keyspace,
1398
+ statement,
1399
+ options,
1400
+ request,
1401
+ plan,
1402
+ timeout,
1403
+ errors,
1404
+ hosts)
1405
+ when Protocol::ExecuteRequest
1406
+ execute_by_plan(promise,
1407
+ keyspace,
1408
+ statement,
1409
+ options,
1410
+ request,
1411
+ plan,
1412
+ timeout,
1413
+ errors,
1414
+ hosts)
1415
+ when Protocol::BatchRequest
1416
+ batch_by_plan(promise,
1417
+ keyspace,
1418
+ statement,
1419
+ options,
1420
+ request,
1421
+ plan,
1422
+ timeout,
1423
+ errors,
1424
+ hosts)
1425
+ else
1426
+ promise.break(ex)
1427
+ end
809
1428
  end
810
1429
  end
811
- rescue => e
812
- promise.break(e)
813
1430
  end
814
1431
 
815
1432
  def wait_for_schema_agreement(connection, schedule)
816
- peers = send_select_request(connection, SELECT_SCHEMA_PEERS)
817
- local = send_select_request(connection, SELECT_SCHEMA_LOCAL)
1433
+ peers_future = send_select_request(connection, SELECT_SCHEMA_PEERS)
1434
+ local_future = send_select_request(connection, SELECT_SCHEMA_LOCAL)
818
1435
 
819
- Ione::Future.all(peers, local).flat_map do |(peers, local)|
1436
+ Ione::Future.all(peers_future, local_future).flat_map do |(peers, local)|
820
1437
  versions = ::Set.new
821
1438
 
822
1439
  unless local.empty?
@@ -841,7 +1458,8 @@ module Cassandra
841
1458
  Ione::Future.resolved
842
1459
  else
843
1460
  interval = schedule.next
844
- @logger.info("Hosts have different schema versions: #{versions.to_a.inspect}, retrying in #{interval} seconds")
1461
+ @logger.info('Hosts have different schema versions: ' \
1462
+ "#{versions.to_a.inspect}, retrying in #{interval} seconds")
845
1463
  @reactor.schedule_timer(interval).flat_map do
846
1464
  wait_for_schema_agreement(connection, schedule)
847
1465
  end
@@ -862,7 +1480,10 @@ module Cassandra
862
1480
 
863
1481
  return pending_switch || Ione::Future.resolved if pending_keyspace == keyspace
864
1482
 
865
- request = Protocol::QueryRequest.new("USE #{Util.escape_name(keyspace)}", EMPTY_LIST, EMPTY_LIST, :one)
1483
+ request = Protocol::QueryRequest.new("USE #{Util.escape_name(keyspace)}",
1484
+ EMPTY_LIST,
1485
+ EMPTY_LIST,
1486
+ :one)
866
1487
 
867
1488
  f = connection.send_request(request, timeout).map do |r|
868
1489
  case r
@@ -870,7 +1491,12 @@ module Cassandra
870
1491
  @keyspace = r.keyspace
871
1492
  nil
872
1493
  when Protocol::ErrorResponse
873
- raise r.to_error(nil, Statements::Simple.new("USE #{Util.escape_name(keyspace)}"), VOID_OPTIONS, EMPTY_LIST, :one, 0)
1494
+ raise r.to_error(nil,
1495
+ Statements::Simple.new("USE #{Util.escape_name(keyspace)}"),
1496
+ VOID_OPTIONS,
1497
+ EMPTY_LIST,
1498
+ :one,
1499
+ 0)
874
1500
  else
875
1501
  raise Errors::InternalError, "Unexpected response #{r.inspect}"
876
1502
  end
@@ -879,7 +1505,7 @@ module Cassandra
879
1505
  connection[:pending_keyspace] = keyspace
880
1506
  connection[:pending_switch] = f
881
1507
 
882
- f.on_complete do |f|
1508
+ f.on_complete do |_f|
883
1509
  connection[:pending_switch] = nil
884
1510
  connection[:pending_keyspace] = nil
885
1511
  end
@@ -891,7 +1517,7 @@ module Cassandra
891
1517
  synchronize do
892
1518
  pending = @preparing_statements[host]
893
1519
 
894
- return pending[cql] if pending.has_key?(cql)
1520
+ return pending[cql] if pending.key?(cql)
895
1521
  end
896
1522
 
897
1523
  request = Protocol::PrepareRequest.new(cql, false)