cassandra-driver 1.0.0.beta.3 → 1.0.0.rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. checksums.yaml +13 -5
  2. data/README.md +8 -6
  3. data/lib/cassandra.rb +99 -13
  4. data/lib/cassandra/address_resolution.rb +36 -0
  5. data/lib/cassandra/address_resolution/policies.rb +2 -0
  6. data/lib/cassandra/address_resolution/policies/ec2_multi_region.rb +56 -0
  7. data/lib/cassandra/address_resolution/policies/none.rb +35 -0
  8. data/lib/cassandra/auth.rb +1 -1
  9. data/lib/cassandra/auth/providers/password.rb +1 -1
  10. data/lib/cassandra/client.rb +2 -2
  11. data/lib/cassandra/client/batch.rb +3 -3
  12. data/lib/cassandra/client/client.rb +12 -12
  13. data/lib/cassandra/client/connection_manager.rb +2 -2
  14. data/lib/cassandra/client/connector.rb +6 -10
  15. data/lib/cassandra/client/prepared_statement.rb +4 -4
  16. data/lib/cassandra/client/request_runner.rb +1 -2
  17. data/lib/cassandra/cluster.rb +15 -5
  18. data/lib/cassandra/cluster/client.rb +158 -96
  19. data/lib/cassandra/cluster/connector.rb +42 -27
  20. data/lib/cassandra/cluster/control_connection.rb +384 -132
  21. data/lib/cassandra/cluster/options.rb +5 -2
  22. data/lib/cassandra/cluster/registry.rb +19 -9
  23. data/lib/cassandra/compression.rb +1 -1
  24. data/lib/cassandra/compression/compressors/lz4.rb +1 -1
  25. data/lib/cassandra/compression/compressors/snappy.rb +1 -1
  26. data/lib/cassandra/driver.rb +28 -20
  27. data/lib/cassandra/errors.rb +325 -35
  28. data/lib/cassandra/future.rb +3 -3
  29. data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +7 -3
  30. data/lib/cassandra/load_balancing/policies/token_aware.rb +1 -1
  31. data/lib/cassandra/protocol.rb +0 -16
  32. data/lib/cassandra/protocol/cql_byte_buffer.rb +18 -18
  33. data/lib/cassandra/protocol/cql_protocol_handler.rb +74 -8
  34. data/lib/cassandra/protocol/frame_decoder.rb +2 -2
  35. data/lib/cassandra/protocol/frame_encoder.rb +1 -1
  36. data/lib/cassandra/protocol/response.rb +1 -1
  37. data/lib/cassandra/protocol/responses/detailed_error_response.rb +16 -1
  38. data/lib/cassandra/protocol/responses/error_response.rb +17 -0
  39. data/lib/cassandra/protocol/responses/event_response.rb +1 -1
  40. data/lib/cassandra/protocol/responses/raw_rows_result_response.rb +1 -1
  41. data/lib/cassandra/protocol/responses/result_response.rb +1 -1
  42. data/lib/cassandra/protocol/responses/rows_result_response.rb +1 -1
  43. data/lib/cassandra/protocol/type_converter.rb +4 -3
  44. data/lib/cassandra/reconnection.rb +1 -1
  45. data/lib/cassandra/retry.rb +3 -5
  46. data/lib/cassandra/session.rb +11 -5
  47. data/lib/cassandra/table.rb +1 -1
  48. data/lib/cassandra/time_uuid.rb +21 -83
  49. data/lib/cassandra/util.rb +1 -1
  50. data/lib/cassandra/uuid.rb +6 -4
  51. data/lib/cassandra/uuid/generator.rb +207 -0
  52. data/lib/cassandra/version.rb +1 -1
  53. metadata +24 -19
@@ -22,10 +22,11 @@ module Cassandra
22
22
  class Options
23
23
  attr_reader :credentials, :auth_provider, :compressor, :port,
24
24
  :connect_timeout, :ssl, :connections_per_local_node,
25
- :connections_per_remote_node
25
+ :connections_per_remote_node, :heartbeat_interval,
26
+ :idle_timeout
26
27
  attr_accessor :protocol_version
27
28
 
28
- def initialize(protocol_version, credentials, auth_provider, compressor, port, connect_timeout, ssl, connections_per_local_node, connections_per_remote_node)
29
+ def initialize(protocol_version, credentials, auth_provider, compressor, port, connect_timeout, ssl, connections_per_local_node, connections_per_remote_node, heartbeat_interval, idle_timeout)
29
30
  @protocol_version = protocol_version
30
31
  @credentials = credentials
31
32
  @auth_provider = auth_provider
@@ -33,6 +34,8 @@ module Cassandra
33
34
  @port = port
34
35
  @connect_timeout = connect_timeout
35
36
  @ssl = ssl
37
+ @heartbeat_interval = heartbeat_interval
38
+ @idle_timeout = idle_timeout
36
39
 
37
40
  @connections_per_local_node = connections_per_local_node
38
41
  @connections_per_remote_node = connections_per_remote_node
@@ -22,24 +22,30 @@ module Cassandra
22
22
  class Registry
23
23
  include MonitorMixin
24
24
 
25
- LISTENER_METHODS = [:host_found, :host_lost, :host_up, :host_down].freeze
26
-
27
25
  def initialize(logger)
28
26
  @logger = logger
29
27
  @hosts = ::Hash.new
30
- @listeners = ::Set.new
28
+ @listeners = ::Array.new
31
29
 
32
30
  mon_initialize
33
31
  end
34
32
 
35
33
  def add_listener(listener)
36
- synchronize { @listeners = @listeners.dup.add(listener) }
34
+ synchronize do
35
+ listeners = @listeners.dup
36
+ listeners.push(listener)
37
+ @listeners = listeners
38
+ end
37
39
 
38
40
  self
39
41
  end
40
42
 
41
43
  def remove_listener(listener)
42
- synchronize { @listeners = @listeners.dup.delete(listener) }
44
+ synchronize do
45
+ listeners = @listeners.dup
46
+ listeners.delete(listener)
47
+ @listeners = listeners
48
+ end
43
49
 
44
50
  self
45
51
  end
@@ -72,8 +78,12 @@ module Cassandra
72
78
  host.rack == data['rack'] &&
73
79
  host.datacenter == data['data_center']
74
80
 
75
- return self
81
+ return self if host.up?
82
+
83
+ host = toggle_up(host)
76
84
  else
85
+ @logger.debug("Host #{host.ip} metadata has been updated, it will be considered lost and found")
86
+
77
87
  notify_lost(host)
78
88
 
79
89
  host = create_host(address, data)
@@ -164,7 +174,7 @@ module Cassandra
164
174
  def toggle_down(host)
165
175
  host = Host.new(host.ip, host.id, host.rack, host.datacenter, host.release_version, host.tokens, :down)
166
176
  @logger.debug("Host #{host.ip} is down")
167
- @listeners.each do |listener|
177
+ @listeners.reverse_each do |listener|
168
178
  listener.host_down(host) rescue nil
169
179
  end
170
180
  host
@@ -174,13 +184,13 @@ module Cassandra
174
184
  if host.up?
175
185
  @logger.debug("Host #{host.ip} is down and lost")
176
186
  host = Host.new(host.ip, host.id, host.rack, host.datacenter, host.release_version, host.tokens, :down)
177
- @listeners.each do |listener|
187
+ @listeners.reverse_each do |listener|
178
188
  listener.host_down(host) rescue nil
179
189
  listener.host_lost(host) rescue nil
180
190
  end
181
191
  else
182
192
  @logger.debug("Host #{host.ip} is lost")
183
- @listeners.each do |listener|
193
+ @listeners.reverse_each do |listener|
184
194
  listener.host_lost(host) rescue nil
185
195
  end
186
196
  end
@@ -18,7 +18,7 @@
18
18
 
19
19
  module Cassandra
20
20
  module Compression
21
- # @abstract Compressors given to {Cassandra.connect} as the `:compressor`
21
+ # @abstract Compressors given to {Cassandra.cluster} as the `:compressor`
22
22
  # option don't need to be subclasses of this class, but need to implement
23
23
  # the same methods. This class exists only for documentation purposes.
24
24
  class Compressor
@@ -31,7 +31,7 @@ module Cassandra
31
31
  # [lz4-ruby](http://rubygems.org/gems/lz4-ruby) gem (v0.3.2 or later
32
32
  # required).
33
33
  # @note No need to instantiate this class manually, use `compression:
34
- # :lz4` option when calling {Cassandra.connect} and one will be created
34
+ # :lz4` option when calling {Cassandra.cluster} and one will be created
35
35
  # automatically for you.
36
36
  class Lz4 < Compressor
37
37
  # @return [String] `'lz4'`
@@ -31,7 +31,7 @@ module Cassandra
31
31
  # [snappy](http://rubygems.org/gems/snappy) gem (v0.0.10 or later for
32
32
  # JRuby support).
33
33
  # @note No need to instantiate this class manually, use `compression:
34
- # :snappy` option when calling {Cassandra.connect} and one will be
34
+ # :snappy` option when calling {Cassandra.cluster} and one will be
35
35
  # created automatically for you.
36
36
  class Snappy < Compressor
37
37
  # @return [String] `'snappy'`
@@ -24,7 +24,7 @@ module Cassandra
24
24
  define_method(:"#{name}=") { |object| @instances[name] = object }
25
25
  end
26
26
 
27
- let(:io_reactor) { Io::IoReactor.new }
27
+ let(:io_reactor) { Ione::Io::IoReactor.new }
28
28
  let(:cluster_registry) { Cluster::Registry.new(logger) }
29
29
  let(:cluster_schema) { Cluster::Schema.new(schema_type_parser) }
30
30
  let(:cluster_metadata) { Cluster::Metadata.new(
@@ -56,34 +56,40 @@ module Cassandra
56
56
 
57
57
  let(:connector) { Cluster::Connector.new(logger, io_reactor, cluster_registry, connection_options) }
58
58
 
59
- let(:control_connection) { Cluster::ControlConnection.new(logger, io_reactor, cluster_registry, cluster_schema, cluster_metadata, load_balancing_policy, reconnection_policy, connector) }
59
+ let(:control_connection) { Cluster::ControlConnection.new(logger, io_reactor, cluster_registry, cluster_schema, cluster_metadata, load_balancing_policy, reconnection_policy, address_resolution_policy, connector) }
60
60
 
61
- let(:cluster) { Cluster.new(logger, io_reactor, control_connection, cluster_registry, cluster_schema, cluster_metadata, execution_options, connection_options, load_balancing_policy, reconnection_policy, retry_policy, connector, futures_factory) }
61
+ let(:cluster) { Cluster.new(logger, io_reactor, 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) }
62
62
 
63
63
  let(:execution_options) do
64
64
  Execution::Options.new({
65
65
  :consistency => consistency,
66
66
  :trace => trace,
67
- :page_size => page_size
67
+ :page_size => page_size,
68
+ :timeout => timeout
68
69
  })
69
70
  end
70
71
 
71
- let(:connection_options) { Cluster::Options.new(protocol_version, credentials, auth_provider, compressor, port, connect_timeout, ssl, connections_per_local_node, connections_per_remote_node) }
72
-
73
- let(:port) { 9042 }
74
- let(:protocol_version) { 2 }
75
- let(:connect_timeout) { 10 }
76
- let(:ssl) { false }
77
- let(:logger) { Client::NullLogger.new }
78
- let(:compressor) { nil }
79
- let(:credentials) { nil }
80
- let(:auth_provider) { nil }
81
- let(:load_balancing_policy) { LoadBalancing::Policies::RoundRobin.new }
82
- let(:reconnection_policy) { Reconnection::Policies::Exponential.new(0.5, 30, 2) }
83
- let(:retry_policy) { Retry::Policies::Default.new }
84
- let(:consistency) { :quorum }
85
- let(:trace) { false }
86
- let(:page_size) { nil }
72
+ let(:connection_options) { Cluster::Options.new(protocol_version, credentials, auth_provider, compressor, port, connect_timeout, ssl, connections_per_local_node, connections_per_remote_node, heartbeat_interval, idle_timeout) }
73
+
74
+ let(:port) { 9042 }
75
+ let(:protocol_version) { 2 }
76
+ let(:connect_timeout) { 10 }
77
+ let(:ssl) { false }
78
+ let(:logger) { Client::NullLogger.new }
79
+ let(:compressor) { nil }
80
+ let(:credentials) { nil }
81
+ let(:auth_provider) { nil }
82
+ let(:datacenter) { nil }
83
+ let(:load_balancing_policy) { LoadBalancing::Policies::TokenAware.new(LoadBalancing::Policies::DCAwareRoundRobin.new(datacenter, 0)) }
84
+ let(:reconnection_policy) { Reconnection::Policies::Exponential.new(0.5, 30, 2) }
85
+ let(:retry_policy) { Retry::Policies::Default.new }
86
+ let(:address_resolution_policy) { AddressResolution::Policies::None.new }
87
+ let(:consistency) { :one }
88
+ let(:trace) { false }
89
+ let(:page_size) { nil }
90
+ let(:heartbeat_interval) { 30 }
91
+ let(:idle_timeout) { 60 }
92
+ let(:timeout) { 10 }
87
93
 
88
94
  let(:connections_per_local_node) { 2 }
89
95
  let(:connections_per_remote_node) { 1 }
@@ -103,8 +109,10 @@ module Cassandra
103
109
  cluster.register(listener)
104
110
  end
105
111
 
112
+ logger.debug('Populating policies and listeners with initial endpoints')
106
113
  addresses.each {|address| cluster_registry.host_found(address)}
107
114
 
115
+ logger.info('Establishing control connection')
108
116
  control_connection.connect_async.map(cluster)
109
117
  end
110
118
  end
@@ -17,63 +17,353 @@
17
17
  #++
18
18
 
19
19
  module Cassandra
20
- # Base class for all Errors raised by the driver
20
+ # Included in all Errors raised by the driver to allow rescuing from any
21
+ # driver-specific error.
22
+ # @example Catching all driver errors
23
+ # begin
24
+ # cluster = Cassandra.cluster
25
+ # session = cluster.connect
26
+ # rescue Cassandra::Error => e
27
+ # puts "#{e.class.name}: #{e.message}"
28
+ # end
21
29
  # @see Cassandra::Errors
22
- class Error < StandardError
30
+ module Error
23
31
  end
24
32
 
25
33
  module Errors
26
- # @!parse class IoError < StandardError; end
27
- # @private
28
- IoError = Ione::IoError
29
-
30
- # This error type represents errors sent by the server, the `code` attribute
31
- # can be used to find the exact type, and `cql` contains the request's CQL,
32
- # if any. `message` contains the human readable error message sent by the
33
- # server.
34
- class QueryError < Error
35
- # @return [Integer] error code
36
- attr_reader :code
37
- # @return [String] original CQL used
38
- attr_reader :cql
39
- # @return [Hash{Symbol => String, Integer}] various error details
40
- attr_reader :details
34
+ # Mixed into any host-specific errors. Requests resulting in these errors
35
+ # are attempted on other hosts. Once all hosts failed with this type of
36
+ # error, a {Cassandra::Errors::NoHostsAvailable} error is raised with
37
+ # details of failures.
38
+ #
39
+ # @see Errors::NoHostsAvailable
40
+ module HostError
41
+ end
42
+
43
+ # Raised when something unexpected happened. This indicates a server-side
44
+ # bug.
45
+ #
46
+ # @see https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v1.spec#L554-L555 Description of Server Error in Apache Cassandra native protocol spec v1
47
+ class ServerError < ::StandardError
48
+ include Error, HostError
49
+ end
50
+
51
+ # Mixed into all internal driver errors.
52
+ module InternalError
53
+ include Error, HostError
54
+ end
55
+
56
+ # Raised when data decoding fails.
57
+ class DecodingError < ::RuntimeError
58
+ include InternalError
59
+ end
60
+
61
+ # Raised when data encoding fails.
62
+ class EncodingError < ::RuntimeError
63
+ include InternalError
64
+ end
65
+
66
+ # Raised when a connection level error occured.
67
+ class IOError < ::IOError
68
+ include InternalError
69
+ end
70
+
71
+ # Raised when a timeout has occured.
72
+ class TimeoutError < ::Timeout::Error
73
+ include InternalError
74
+ end
75
+
76
+ # Mixed into all request execution errors.
77
+ module ExecutionError
78
+ include Error
79
+
80
+ # @return [Cassandra::Statement] statement that triggered the error.
81
+ attr_reader :statement
41
82
 
42
83
  # @private
43
- def initialize(code, message, cql=nil, details=nil)
84
+ def initialize(message, statement)
44
85
  super(message)
45
- @code = code
46
- @cql = cql
47
- @details = details
86
+
87
+ @statement = statement
48
88
  end
49
89
  end
50
90
 
51
- # This error is thrown when not hosts could be reached during connection or query execution.
52
- class NoHostsAvailable < Error
53
- # @return [Hash{Cassandra::Host => Exception}] a map of hosts to underlying exceptions
54
- attr_reader :errors
91
+ # Raised when coordinator determines that a request cannot be executed
92
+ # because there are not enough replicas. In this scenario, the request is
93
+ # not sent to the nodes at all.
94
+ #
95
+ # @note This error can be handled by a {Cassandra::Retry::Policy} to
96
+ # determine the desired outcome.
97
+ #
98
+ # @see https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v1.spec#L562-L572 Description of Unavailable Error in Apache Cassandra native protocol spec v1
99
+ class UnavailableError < ::StandardError
100
+ include ExecutionError
101
+ # Consistency level that triggered the error.
102
+ #
103
+ # @return [Symbol] the original consistency level for the request, one of
104
+ # {Cassandra::CONSISTENCIES}
105
+ attr_reader :consistency
106
+
107
+ # @return [Integer] the number of replicas required to achieve requested
108
+ # consistency level
109
+ attr_reader :required
110
+
111
+ # @return [Integer] the number of replicas available for the request
112
+ attr_reader :alive
55
113
 
56
114
  # @private
57
- def initialize(errors = {})
58
- super("no hosts available, check #errors property for details")
115
+ def initialize(message, statement, consistency, required, alive)
116
+ super(message, statement)
59
117
 
60
- @errors = errors
118
+ @consistency = consistency
119
+ @required = required
120
+ @alive = alive
61
121
  end
62
122
  end
63
123
 
64
- # Client error represents bad driver state or configuration
124
+ # Raised when the request cannot be processed because the coordinator node
125
+ # is overloaded
126
+ #
127
+ # @see https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v1.spec#L573-L574 Description of Overloaded Error in Apache Cassandra native protocol spec v1
128
+ class OverloadedError < ::StandardError
129
+ include ExecutionError, HostError
130
+ end
131
+
132
+ # Raise when the request was a read request but the coordinator node is
133
+ # bootstrapping
134
+ #
135
+ # @see https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v1.spec#L575-L576 Description of Is Bootstrapping Error in Apache Cassandra native protocol spec v1
136
+ class IsBootstrappingError < ::StandardError
137
+ include ExecutionError, HostError
138
+ end
139
+
140
+ # Raised when truncation failed.
141
+ #
142
+ # @see https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v1.spec#L577 Description of Truncate Error in Apache Cassandra native protocol spec v1
143
+ class TruncateError < ::StandardError
144
+ include ExecutionError
145
+ end
146
+
147
+ # Raised when a write request timed out.
148
+ #
149
+ # @see https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v1.spec#L578-L603 Description of Write Timeout Error in Apache Cassandra native protocol spec v1
150
+ class WriteTimeoutError < ::StandardError
151
+ include ExecutionError
152
+
153
+ # @return [Symbol] the type of write request that timed out, one of
154
+ # {Cassandra::WRITE_TYPES}
155
+ attr_reader :type
156
+ # @return [Symbol] the original consistency level for the request, one of
157
+ # {Cassandra::CONSISTENCIES}
158
+ attr_reader :consistency
159
+ # @return [Integer] the number of acks required to achieve requested
160
+ # consistency level
161
+ attr_reader :required
162
+ # @return [Integer] the number of acks received by the time the query
163
+ # timed out
164
+ attr_reader :received
165
+
166
+ # @private
167
+ def initialize(message, statement, type, consistency, required, received)
168
+ super(message, statement)
169
+
170
+ @type = type
171
+ @consistency = consistency
172
+ @required = required
173
+ @received = received
174
+ end
175
+ end
176
+
177
+ # Raised when a read request timed out.
178
+ #
179
+ # @see https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v1.spec#L604-L622 Description of Read Timeout Error in Apache Cassandra native protocol spec v1
180
+ class ReadTimeoutError < ::StandardError
181
+ include ExecutionError
182
+
183
+ # @return [Boolean] whether actual data (as opposed to data checksum) was
184
+ # present in the received responses.
185
+ attr_reader :retrieved
186
+ # @return [Symbol] the original consistency level for the request, one of
187
+ # {Cassandra::CONSISTENCIES}
188
+ attr_reader :consistency
189
+ # @return [Integer] the number of responses required to achieve requested
190
+ # consistency level
191
+ attr_reader :required
192
+ # @return [Integer] the number of responses received by the time the
193
+ # query timed out
194
+ attr_reader :received
195
+
196
+ # @private
197
+ def initialize(message, statement, retrieved, consistency, required, received)
198
+ super(message, statement)
199
+
200
+ @retrieved = retrieved
201
+ @consistency = consistency
202
+ @required = required
203
+ @received = received
204
+ end
205
+
206
+ def retrieved?
207
+ @retrieved
208
+ end
209
+ end
210
+
211
+ # Client error represents bad driver state or mis-configuration
212
+ class ClientError < ::StandardError
213
+ include Error
214
+ end
215
+
216
+ # Raised when some client message triggered a protocol violation (for
217
+ # instance a QUERY message is sent before a STARTUP one has been sent)
65
218
  #
66
- # @see Cassandra::Errors::AuthenticationError
67
- class ClientError < Error
219
+ # @see https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v1.spec#L556-L558 Description of Protocol Error in Apache Cassandra native protocol spec v1
220
+ class ProtocolError < ClientError
68
221
  end
69
222
 
70
223
  # Raised when cannot authenticate to Cassandra
224
+ #
225
+ # @see https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v1.spec#L559-L561 Description of Bad Credentials Error in Apache Cassandra native protocol spec v1
71
226
  class AuthenticationError < ClientError
72
227
  end
73
228
 
74
- # @private
75
- NotConnectedError = Class.new(Error)
76
- # @private
77
- NotPreparedError = Class.new(Error)
229
+ # Mixed into all request validation errors.
230
+ module ValidationError
231
+ include Error
232
+
233
+ # @return [Cassandra::Statement] statement that triggered the error.
234
+ attr_reader :statement
235
+
236
+ # @private
237
+ def initialize(message, statement)
238
+ super(message)
239
+
240
+ @statement = statement
241
+ end
242
+ end
243
+
244
+ # Raised when a prepared statement tries to be executed and the provided
245
+ # prepared statement ID is not known by this host
246
+ #
247
+ # @note Seeing this error can be considered a Ruby Driver bug as it should
248
+ # handle automatic re-preparing internally.
249
+ #
250
+ # @see https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v1.spec#L638-L641 Description of Unprepared Error in Apache Cassandra native protocol spec v1
251
+ class UnpreparedError < ::StandardError
252
+ include ValidationError
253
+ # @return [String] prepared statement id that triggered the error
254
+ attr_reader :id
255
+
256
+ # @private
257
+ def initialize(message, statement, id)
258
+ super(message, statement)
259
+
260
+ @id = id
261
+ end
262
+ end
263
+
264
+ # Raised when the submitted query has a syntax error.
265
+ #
266
+ # @see https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v1.spec#L623 Description of Syntax Error in Apache Cassandra native protocol spec v1
267
+ class SyntaxError < ::StandardError
268
+ include ValidationError
269
+ end
270
+
271
+ # Raised when the logged user doesn't have the right to perform the query.
272
+ #
273
+ # @see https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v1.spec#L624-L625 Description of Unauthorized Error in Apache Cassandra native protocol spec v1
274
+ class UnauthorizedError < ::StandardError
275
+ include ValidationError
276
+ end
277
+
278
+ # Raised when the query is syntactically correct but invalid.
279
+ #
280
+ # @example Creating a table without selecting a keyspace
281
+ # begin
282
+ # session.execute("CREATE TABLE users (user_id INT PRIMARY KEY)")
283
+ # rescue Cassandra::Errors::InvalidError
284
+ # end
285
+ #
286
+ # @see https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v1.spec#L626 Description of Invalid Error in Apache Cassandra native protocol spec v1
287
+ class InvalidError < ::StandardError
288
+ include ValidationError
289
+ end
290
+
291
+ # Raised when the query is invalid because of some configuration issue.
292
+ #
293
+ # @example Dropping non-existent keyspace
294
+ # begin
295
+ # client.execute("DROP KEYSPACE unknown_keyspace")
296
+ # rescue Cassandra::Errors::ConfigurationError
297
+ # end
298
+ #
299
+ # @see https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v1.spec#L627 Description of Config Error in Apache Cassandra native protocol spec v1
300
+ class ConfigurationError < ::StandardError
301
+ include ValidationError
302
+ end
303
+
304
+ # Raised when the query attempted to create a keyspace or a table that was
305
+ # already existing.
306
+ #
307
+ # @example Creating a table twice
308
+ # session.execute("USE my_keyspace")
309
+ # session.execute("CREATE TABLE users (user_id INT PRIMARY KEY)")
310
+ # begin
311
+ # session.execute("CREATE TABLE users (user_id INT PRIMARY KEY)")
312
+ # rescue Cassandra::Errors::AlreadyExistsError => e
313
+ # p ['already exists', e.keyspace, e.table]
314
+ # end
315
+ #
316
+ # @see https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v1.spec#L628-L637 Description of Already Exists Error in Apache Cassandra native protocol spec v1
317
+ class AlreadyExistsError < ConfigurationError
318
+ # @return [String] keyspace
319
+ attr_reader :keyspace
320
+
321
+ # @return [String, nil] table or `nil`
322
+ attr_reader :table
323
+
324
+ # @private
325
+ def initialize(message, statement, keyspace, table)
326
+ super(message, statement)
327
+
328
+ @keyspace = keyspace
329
+ @table = table
330
+ end
331
+ end
332
+
333
+ # This error is thrown when all attempted hosts raised a
334
+ # {Cassandra::Errors::HostError} during connection or query execution.
335
+ #
336
+ # @see Cassandra::Cluster#connect
337
+ # @see Cassandra::Session#execute
338
+ class NoHostsAvailable < ::StandardError
339
+ include Error
340
+
341
+ # @return [Hash{Cassandra::Host => Cassandra::Errors::HostError}] a map
342
+ # of hosts to underlying exceptions
343
+ attr_reader :errors
344
+
345
+ # @private
346
+ def initialize(errors = nil)
347
+ if errors
348
+ first = true
349
+ message = "All attempted hosts failed"
350
+ details = errors.each do |(host, error)|
351
+ if first
352
+ first = false
353
+ message << ': '
354
+ else
355
+ message << ', '
356
+ end
357
+ message << "#{host.ip} (#{error.class.name}: #{error.message})"
358
+ end
359
+ else
360
+ message = "All hosts down"
361
+ end
362
+
363
+ super(message)
364
+
365
+ @errors = errors || {}
366
+ end
367
+ end
78
368
  end
79
369
  end