cassandra-driver 3.0.3 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +8 -8
  2. data/README.md +46 -31
  3. data/lib/cassandra.rb +35 -44
  4. data/lib/cassandra/cluster.rb +40 -11
  5. data/lib/cassandra/cluster/client.rb +193 -159
  6. data/lib/cassandra/cluster/connector.rb +12 -10
  7. data/lib/cassandra/cluster/control_connection.rb +38 -10
  8. data/lib/cassandra/cluster/options.rb +8 -4
  9. data/lib/cassandra/cluster/registry.rb +1 -2
  10. data/lib/cassandra/cluster/schema/fetchers.rb +122 -26
  11. data/lib/cassandra/column_container.rb +9 -4
  12. data/lib/cassandra/custom_data.rb +24 -22
  13. data/lib/cassandra/driver.rb +30 -13
  14. data/lib/cassandra/errors.rb +12 -2
  15. data/lib/cassandra/execution/options.rb +52 -16
  16. data/lib/cassandra/execution/profile.rb +150 -0
  17. data/lib/cassandra/execution/profile_manager.rb +71 -0
  18. data/lib/cassandra/execution/trace.rb +5 -4
  19. data/lib/cassandra/executors.rb +1 -1
  20. data/lib/cassandra/index.rb +1 -1
  21. data/lib/cassandra/keyspace.rb +36 -1
  22. data/lib/cassandra/protocol.rb +5 -0
  23. data/lib/cassandra/protocol/coder.rb +2 -1
  24. data/lib/cassandra/protocol/cql_byte_buffer.rb +21 -0
  25. data/lib/cassandra/protocol/responses/read_failure_error_response.rb +10 -4
  26. data/lib/cassandra/protocol/responses/write_failure_error_response.rb +14 -8
  27. data/lib/cassandra/protocol/v3.rb +2 -1
  28. data/lib/cassandra/protocol/v4.rb +58 -20
  29. data/lib/cassandra/result.rb +1 -1
  30. data/lib/cassandra/session.rb +43 -16
  31. data/lib/cassandra/statements/bound.rb +5 -1
  32. data/lib/cassandra/statements/prepared.rb +8 -3
  33. data/lib/cassandra/table.rb +72 -0
  34. data/lib/cassandra/trigger.rb +67 -0
  35. data/lib/cassandra/types.rb +12 -24
  36. data/lib/cassandra/udt.rb +3 -6
  37. data/lib/cassandra/uuid/generator.rb +6 -3
  38. data/lib/cassandra/version.rb +1 -1
  39. metadata +5 -2
@@ -60,8 +60,10 @@ module Cassandra
60
60
  # @return [ColumnContainer::Compaction] the compaction strategy of this column-container.
61
61
  attr_reader :compaction_strategy
62
62
 
63
+ # @return whether or not change data capture is enabled on this table.
64
+ attr_reader :cdc
65
+
63
66
  # @private
64
- # rubocop:disable Metrics/ParameterLists
65
67
  def initialize(comment,
66
68
  read_repair_chance,
67
69
  local_read_repair_chance,
@@ -80,7 +82,8 @@ module Cassandra
80
82
  compression,
81
83
  compact_storage,
82
84
  crc_check_chance,
83
- extensions)
85
+ extensions,
86
+ cdc)
84
87
  @comment = comment
85
88
  @read_repair_chance = read_repair_chance
86
89
  @local_read_repair_chance = local_read_repair_chance
@@ -100,6 +103,7 @@ module Cassandra
100
103
  @compact_storage = compact_storage
101
104
  @crc_check_chance = crc_check_chance
102
105
  @extensions = extensions
106
+ @cdc = cdc
103
107
  end
104
108
 
105
109
  # Return whether to replicate counter updates to other replicas. It is *strongly* recommended
@@ -130,6 +134,7 @@ module Cassandra
130
134
  options << "bloom_filter_fp_chance = #{Util.encode_object(@bloom_filter_fp_chance)}"
131
135
  end
132
136
  options << "caching = #{Util.encode_object(@caching)}" unless @caching.nil?
137
+ options << 'cdc = true' if @cdc
133
138
  options << "comment = #{Util.encode_object(@comment)}" unless @comment.nil?
134
139
  options << "compaction = #{@compaction_strategy.to_cql}" unless @compaction_strategy.nil?
135
140
  options << "compression = #{Util.encode_object(@compression)}" unless @compression.nil?
@@ -153,7 +158,6 @@ module Cassandra
153
158
  options << "read_repair_chance = #{Util.encode_object(@read_repair_chance)}" unless @read_repair_chance.nil?
154
159
  options << "replicate_on_write = '#{@replicate_on_write}'" unless @replicate_on_write.nil?
155
160
  options << "speculative_retry = #{Util.encode_object(@speculative_retry)}" unless @speculative_retry.nil?
156
-
157
161
  options.join("\nAND ")
158
162
  end
159
163
 
@@ -176,7 +180,8 @@ module Cassandra
176
180
  @compression == other.compression &&
177
181
  @compact_storage == other.compact_storage? &&
178
182
  @crc_check_chance == other.crc_check_chance &&
179
- @extensions == other.extensions
183
+ @extensions == other.extensions &&
184
+ @cdc == other.cdc
180
185
  end
181
186
  alias == eql?
182
187
  end
@@ -20,32 +20,34 @@
20
20
  # columns in C*. This module has no logic of its own, but indicates that the marked class has
21
21
  # certain methods.
22
22
  # @private
23
- module Cassandra::CustomData
24
- def self.included base
25
- base.send :include, InstanceMethods
26
- base.extend ClassMethods
27
- end
28
-
29
- module ClassMethods
30
- # @return [Cassandra::Types::Custom] the custom type that this class represents.
31
- def type
32
- raise NotImplementedError, "#{self.class} must implement the :type class method"
23
+ module Cassandra
24
+ module CustomData
25
+ def self.included(base)
26
+ base.send :include, InstanceMethods
27
+ base.extend ClassMethods
33
28
  end
34
29
 
35
- # Deserialize the given data into an instance of this domain object class.
36
- # @param data [String] byte-array representation of a column value of this custom type.
37
- # @return An instance of the domain object class.
38
- # @raise [Cassandra::Errors::DecodingError] upon failure.
39
- def deserialize(data)
40
- raise NotImplementedError, "#{self.class} must implement the :deserialize class method"
30
+ module ClassMethods
31
+ # @return [Cassandra::Types::Custom] the custom type that this class represents.
32
+ def type
33
+ raise NotImplementedError, "#{self.class} must implement the :type class method"
34
+ end
35
+
36
+ # Deserialize the given data into an instance of this domain object class.
37
+ # @param data [String] byte-array representation of a column value of this custom type.
38
+ # @return An instance of the domain object class.
39
+ # @raise [Cassandra::Errors::DecodingError] upon failure.
40
+ def deserialize(data)
41
+ raise NotImplementedError, "#{self.class} must implement the :deserialize class method"
42
+ end
41
43
  end
42
- end
43
44
 
44
- module InstanceMethods
45
- # Serialize this domain object into a byte array to send to C*.
46
- # @return [String] byte-array representation of this domain object.
47
- def serialize
48
- raise NotImplementedError, "#{self.class} must implement the :serialize instance method"
45
+ module InstanceMethods
46
+ # Serialize this domain object into a byte array to send to C*.
47
+ # @return [String] byte-array representation of this domain object.
48
+ def serialize
49
+ raise NotImplementedError, "#{self.class} must implement the :serialize instance method"
50
+ end
49
51
  end
50
52
  end
51
53
  end
@@ -84,7 +84,7 @@ module Cassandra
84
84
  cluster_registry,
85
85
  cluster_schema,
86
86
  cluster_metadata,
87
- load_balancing_policy,
87
+ profile_manager.default_profile.load_balancing_policy,
88
88
  reconnection_policy,
89
89
  address_resolution_policy,
90
90
  connector,
@@ -104,21 +104,22 @@ module Cassandra
104
104
  cluster_metadata,
105
105
  execution_options,
106
106
  connection_options,
107
- load_balancing_policy,
107
+ profile_manager,
108
108
  reconnection_policy,
109
- retry_policy,
110
109
  address_resolution_policy,
111
110
  connector,
112
111
  futures_factory,
113
- timestamp_generator)
112
+ timestamp_generator)
114
113
  end
115
114
 
116
115
  let(:execution_options) do
117
- Execution::Options.new(consistency: consistency,
116
+ Execution::Options.new(consistency: profile_manager.default_profile.consistency,
118
117
  trace: trace,
119
118
  page_size: page_size,
120
- timeout: timeout,
121
- idempotent: false)
119
+ timeout: profile_manager.default_profile.timeout,
120
+ idempotent: false,
121
+ load_balancing_policy: profile_manager.default_profile.load_balancing_policy,
122
+ retry_policy: profile_manager.default_profile.retry_policy)
122
123
  end
123
124
 
124
125
  let(:connection_options) do
@@ -140,13 +141,15 @@ module Cassandra
140
141
  schema_refresh_timeout,
141
142
  nodelay,
142
143
  requests_per_connection,
143
- custom_types
144
+ custom_types,
145
+ allow_beta_protocol
144
146
  )
145
147
  end
146
148
 
147
- let(:custom_types) { [] }
149
+ let(:custom_types) { [] }
148
150
  let(:port) { 9042 }
149
151
  let(:protocol_version) { nil }
152
+ let(:allow_beta_protocol) { false }
150
153
  let(:connect_timeout) { 10 }
151
154
  let(:ssl) { false }
152
155
  let(:logger) { NullLogger.new }
@@ -157,7 +160,8 @@ module Cassandra
157
160
  let(:load_balancing_policy) do
158
161
  LoadBalancing::Policies::TokenAware.new(
159
162
  LoadBalancing::Policies::DCAwareRoundRobin.new(datacenter, 0),
160
- shuffle_replicas)
163
+ shuffle_replicas
164
+ )
161
165
  end
162
166
  let(:reconnection_policy) do
163
167
  Reconnection::Policies::Exponential.new(0.5, 30, 2)
@@ -180,7 +184,14 @@ module Cassandra
180
184
  let(:connections_per_local_node) { nil }
181
185
  let(:connections_per_remote_node) { nil }
182
186
  let(:requests_per_connection) { nil }
183
-
187
+ let(:default_execution_profile) {
188
+ Cassandra::Execution::Profile.new(load_balancing_policy: load_balancing_policy,
189
+ retry_policy: retry_policy,
190
+ consistency: consistency,
191
+ timeout: timeout)
192
+ }
193
+ let(:execution_profiles) { {} }
194
+ let(:profile_manager) { Cassandra::Execution::ProfileManager.new(default_execution_profile, execution_profiles) }
184
195
  let(:listeners) { [] }
185
196
 
186
197
  def initialize(defaults = {})
@@ -188,8 +199,11 @@ module Cassandra
188
199
  end
189
200
 
190
201
  def connect(addresses)
191
- load_balancing_policy.setup(cluster)
192
- cluster_registry.add_listener(load_balancing_policy)
202
+ profile_manager.load_balancing_policies.each do |lbp|
203
+ lbp.setup(cluster)
204
+ cluster_registry.add_listener(lbp)
205
+ end
206
+
193
207
  cluster_registry.add_listener(control_connection)
194
208
  listeners.each do |listener|
195
209
  cluster.register(listener)
@@ -236,6 +250,9 @@ module Cassandra
236
250
  picker.when('3.') do
237
251
  Cluster::Schema::Fetchers::V3_0_x.new(schema_cql_type_parser, cluster_schema)
238
252
  end
253
+ picker.when('4.') do
254
+ Cluster::Schema::Fetchers::V3_0_x.new(schema_cql_type_parser, cluster_schema)
255
+ end
239
256
 
240
257
  picker
241
258
  end
@@ -348,6 +348,9 @@ module Cassandra
348
348
  attr_reader :received
349
349
  # @return [Integer] the number of writes failed
350
350
  attr_reader :failed
351
+ # @return [Hash<IPAddr, Integer>] map of <ip, error-code>. This is new in v5 and is nil in previous versions
352
+ # of the Casssandra protocol.
353
+ attr_reader :failures_by_node
351
354
 
352
355
  # @private
353
356
  def initialize(message,
@@ -363,7 +366,8 @@ module Cassandra
363
366
  consistency,
364
367
  required,
365
368
  failed,
366
- received)
369
+ received,
370
+ failures_by_node)
367
371
  super(message,
368
372
  payload,
369
373
  warnings,
@@ -378,6 +382,7 @@ module Cassandra
378
382
  @required = required
379
383
  @failed = failed
380
384
  @received = received
385
+ @failures_by_node = failures_by_node
381
386
  end
382
387
  end
383
388
 
@@ -400,6 +405,9 @@ module Cassandra
400
405
  attr_reader :received
401
406
  # @return [Integer] the number of reads failed
402
407
  attr_reader :failed
408
+ # @return [Hash<IPaddr, Integer>] map of <ip, error-code>. This is new in v5 and is nil in previous versions
409
+ # of the Casssandra protocol.
410
+ attr_reader :failures_by_node
403
411
 
404
412
  # @private
405
413
  def initialize(message,
@@ -415,7 +423,8 @@ module Cassandra
415
423
  consistency,
416
424
  required,
417
425
  failed,
418
- received)
426
+ received,
427
+ failures_by_node)
419
428
  super(message,
420
429
  payload,
421
430
  warnings,
@@ -430,6 +439,7 @@ module Cassandra
430
439
  @required = required
431
440
  @failed = failed
432
441
  @received = received
442
+ @failures_by_node = failures_by_node
433
443
  end
434
444
 
435
445
  def retrieved?
@@ -50,11 +50,11 @@ module Cassandra
50
50
  attr_reader :paging_state
51
51
 
52
52
  # @return [nil, Hash<String, String>] custom outgoing payload, a map of
53
- # string and byte buffers.
53
+ # string and byte buffers.
54
54
  #
55
55
  # @see https://github.com/apache/cassandra/blob/cassandra-3.4/doc/native_protocol_v4.spec#L125-L131 Description
56
56
  # of custom payload in Cassandra native protocol v4.
57
- # @see http://docs.datastax.com/en/developer/java-driver/3.0/supplemental/manual/custom_payloads/?local=true&nav=toc#enabling-custom-payloads-on-c-nodes
57
+ # @see http://dsdocs30_java/manual/custom_payloads/#enabling-custom-payloads-on-c-nodes
58
58
  # Enabling custom payloads on Cassandra nodes.
59
59
  #
60
60
  # @example Sending a custom payload
@@ -64,21 +64,31 @@ module Cassandra
64
64
  # })
65
65
  attr_reader :payload
66
66
 
67
+ # @return [Cassandra::LoadBalancing::Policy] load-balancing policy that determines which node will run the
68
+ # next statement.
69
+ attr_reader :load_balancing_policy
70
+
71
+ # @return [Cassandra::Retry::Policy] retry policy that determines how request retries should be handled for
72
+ # different failure modes.
73
+ attr_reader :retry_policy
74
+
67
75
  # @private
68
76
  # @param options [Hash] execution options to validate and encapsulate
69
77
  # @param trusted_options [Options] (optional) base Execution::Options from which
70
78
  # to create this new Options object.
71
79
  def initialize(options, trusted_options = nil)
72
- consistency = options[:consistency]
73
- page_size = options[:page_size]
74
- trace = options[:trace]
75
- timeout = options[:timeout]
76
- serial_consistency = options[:serial_consistency]
77
- paging_state = options[:paging_state]
78
- arguments = options[:arguments]
79
- type_hints = options[:type_hints]
80
- idempotent = options[:idempotent]
81
- payload = options[:payload]
80
+ consistency = options[:consistency]
81
+ page_size = options[:page_size]
82
+ trace = options[:trace]
83
+ timeout = options[:timeout]
84
+ serial_consistency = options[:serial_consistency]
85
+ paging_state = options[:paging_state]
86
+ arguments = options[:arguments]
87
+ type_hints = options[:type_hints]
88
+ idempotent = options[:idempotent]
89
+ payload = options[:payload]
90
+ load_balancing_policy = options[:load_balancing_policy]
91
+ retry_policy = options[:retry_policy]
82
92
 
83
93
  # consistency is a required attribute of an Options object. If we are creating
84
94
  # an Options object from scratch (e.g. no trusted_options as base) validate the
@@ -91,6 +101,22 @@ module Cassandra
91
101
  end
92
102
  end
93
103
 
104
+ # load_balancing_policy and retry_policy are required, but can fallback to trusted_options, just like
105
+ # consistency.
106
+ if trusted_options.nil? || !load_balancing_policy.nil?
107
+ methods = [:host_up, :host_down, :host_found, :host_lost, :setup, :teardown,
108
+ :distance, :plan]
109
+ Util.assert_responds_to_all(methods, load_balancing_policy,
110
+ ":load_balancing_policy #{load_balancing_policy.inspect} must respond " \
111
+ "to #{methods.inspect}, but doesn't")
112
+ end
113
+ if trusted_options.nil? || !retry_policy.nil?
114
+ methods = [:read_timeout, :write_timeout, :unavailable]
115
+ Util.assert_responds_to_all(methods, retry_policy,
116
+ ":retry_policy #{retry_policy.inspect} must respond to #{methods.inspect}, " \
117
+ "but doesn't")
118
+ end
119
+
94
120
  unless serial_consistency.nil?
95
121
  Util.assert_one_of(SERIAL_CONSISTENCIES, serial_consistency) do
96
122
  ":serial_consistency must be one of #{SERIAL_CONSISTENCIES.inspect}, " \
@@ -173,6 +199,8 @@ module Cassandra
173
199
  @serial_consistency = serial_consistency
174
200
  @arguments = arguments
175
201
  @type_hints = type_hints
202
+ @load_balancing_policy = load_balancing_policy
203
+ @retry_policy = retry_policy
176
204
  else
177
205
  @consistency = consistency || trusted_options.consistency
178
206
  @page_size = page_size || trusted_options.page_size
@@ -181,6 +209,8 @@ module Cassandra
181
209
  @serial_consistency = serial_consistency || trusted_options.serial_consistency
182
210
  @arguments = arguments || trusted_options.arguments
183
211
  @type_hints = type_hints || trusted_options.type_hints
212
+ @load_balancing_policy = load_balancing_policy || trusted_options.load_balancing_policy
213
+ @retry_policy = retry_policy || trusted_options.retry_policy
184
214
  end
185
215
 
186
216
  # The following fields are *not* inherited from trusted_options, so we always
@@ -210,18 +240,24 @@ module Cassandra
210
240
  other.serial_consistency == @serial_consistency &&
211
241
  other.paging_state == @paging_state &&
212
242
  other.arguments == @arguments &&
213
- other.type_hints == @type_hints
243
+ other.type_hints == @type_hints &&
244
+ other.load_balancing_policy == @load_balancing_policy &&
245
+ other.retry_policy == @retry_policy
214
246
  end
215
247
  alias == eql?
216
248
 
217
249
  # @private
218
250
  def override(*options)
219
251
  merged = options.unshift({}).inject do |base, opts|
252
+ # Skip nil args
220
253
  next base unless opts
221
- Util.assert_instance_of(::Hash, opts) do
222
- "options must be a Hash, #{options.inspect} given"
254
+
255
+ if opts.is_a?(Cassandra::Execution::Profile)
256
+ base.merge!(opts.to_h)
257
+ else
258
+ Util.assert_instance_of(::Hash, opts, "options must be a Hash, #{opts.inspect} given")
259
+ base.merge!(opts)
223
260
  end
224
- base.merge!(opts)
225
261
  end
226
262
 
227
263
  Options.new(merged, self)
@@ -0,0 +1,150 @@
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
+ module Cassandra
20
+ module Execution
21
+ # A profile is a collection of settings to use when executing and preparing statements. Register different
22
+ # profiles when creating the {Cassandra::Cluster} and execute/prepare statements with a particular profile
23
+ # by providing its name to the relevant method in {Session}.
24
+ #
25
+ # @see Cassandra.cluster
26
+ # @see Session#execute_async
27
+ # @see Session#execute
28
+ # @see Session#prepare_async
29
+ # @see Session#prepare
30
+ class Profile
31
+ # @return [Cassandra::LoadBalancing::Policy] load-balancing policy that determines which node will run the
32
+ # next statement.
33
+ attr_reader :load_balancing_policy
34
+
35
+ # @return [Cassandra::Retry::Policy] retry policy that determines how request retries should be handled for
36
+ # different failure modes.
37
+ attr_reader :retry_policy
38
+
39
+ # @return [Symbol] consistency level with which to run statements.
40
+ attr_reader :consistency
41
+
42
+ # @return [Numeric] request execution timeout in seconds. `nil` means there is no timeout.
43
+ attr_reader :timeout
44
+
45
+ # @private
46
+ DEFAULT_OPTIONS = { consistency: :local_one, timeout: 12 }.freeze
47
+
48
+ # @param options [Hash] hash of attributes. Unspecified attributes fall back to system defaults.
49
+ # @option options [Numeric] :timeout (12) Request execution timeout in
50
+ # seconds. Setting value to `nil` will remove request timeout.
51
+ # @option options [Cassandra::LoadBalancing::Policy] :load_balancing_policy (
52
+ # LoadBalancing::Policies::TokenAware(LoadBalancing::Policies::DCAwareRoundRobin)) Load-balancing policy
53
+ # that determines which node will run the next statement.
54
+ # @option options [Cassandra::Retry::Policy] :retry_policy (Retry::Policies::Default) Retry policy that
55
+ # determines how request retries should be handled for different failure modes.
56
+ # @option options [Symbol] :consistency (:local_one) Consistency level with which to run statements. Must be one
57
+ # of {Cassandra::CONSISTENCIES}.
58
+ def initialize(options = {})
59
+ validate(options)
60
+ options = DEFAULT_OPTIONS.merge(options)
61
+ @load_balancing_policy = options[:load_balancing_policy] ||
62
+ LoadBalancing::Policies::TokenAware.new(
63
+ LoadBalancing::Policies::DCAwareRoundRobin.new,
64
+ true)
65
+ @retry_policy = options[:retry_policy] || Retry::Policies::Default.new
66
+ @consistency = options[:consistency]
67
+ @timeout = options[:timeout]
68
+ end
69
+
70
+ # @private
71
+ def to_h
72
+ {
73
+ load_balancing_policy: @load_balancing_policy,
74
+ retry_policy: @retry_policy,
75
+ consistency: @consistency,
76
+ timeout: @timeout
77
+ }
78
+ end
79
+
80
+ # @private
81
+ def eql?(other)
82
+ other.is_a?(Profile) && \
83
+ @load_balancing_policy == other.load_balancing_policy && \
84
+ @retry_policy == other.retry_policy && \
85
+ @consistency == other.consistency && \
86
+ @timeout == other.timeout
87
+ end
88
+ alias == eql?
89
+
90
+ # @private
91
+ def hash
92
+ @hash ||= begin
93
+ h = 17
94
+ h = 31 * h + @load_balancing_policy.hash
95
+ h = 31 * h + @retry_policy.hash
96
+ h = 31 * h + @consistency.hash
97
+ h = 31 * h + @timeout.hash
98
+ h
99
+ end
100
+ end
101
+
102
+ # @private
103
+ def inspect
104
+ "#<#{self.class.name}:0x#{object_id.to_s(16)} " \
105
+ "load_balancing_policy=#{@load_balancing_policy.inspect}, " \
106
+ "retry_policy=#{@retry_policy.inspect}, " \
107
+ "consistency=#{@consistency.inspect}, " \
108
+ "timeout=#{@timeout.inspect}>"
109
+ end
110
+
111
+ # @private
112
+ def validate(options)
113
+ if options.key?(:timeout)
114
+ timeout = options[:timeout]
115
+
116
+ unless timeout.nil?
117
+ Util.assert_instance_of(::Numeric, timeout, ":timeout must be a number of seconds, #{timeout.inspect} given")
118
+ Util.assert(timeout > 0, ":timeout must be greater than 0, #{timeout} given")
119
+ end
120
+ end
121
+
122
+ if options.key?(:load_balancing_policy)
123
+ load_balancing_policy = options[:load_balancing_policy]
124
+ methods = [:host_up, :host_down, :host_found, :host_lost, :setup, :teardown,
125
+ :distance, :plan]
126
+ Util.assert_responds_to_all(methods, load_balancing_policy) do
127
+ ":load_balancing_policy #{load_balancing_policy.inspect} must respond " \
128
+ "to #{methods.inspect}, but doesn't"
129
+ end
130
+ end
131
+
132
+ if options.key?(:retry_policy)
133
+ retry_policy = options[:retry_policy]
134
+ methods = [:read_timeout, :write_timeout, :unavailable]
135
+ Util.assert_responds_to_all(methods, retry_policy) do
136
+ ":retry_policy #{retry_policy.inspect} must respond to #{methods.inspect}, " \
137
+ "but doesn't"
138
+ end
139
+ end
140
+
141
+ if options.key?(:consistency)
142
+ consistency = options[:consistency]
143
+ Util.assert_one_of(CONSISTENCIES, consistency,
144
+ ":consistency must be one of #{CONSISTENCIES.inspect}, " \
145
+ "#{consistency.inspect} given")
146
+ end
147
+ end
148
+ end
149
+ end
150
+ end