cassandra-driver 1.0.0.rc.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +8 -8
  2. data/README.md +45 -10
  3. data/lib/cassandra.rb +82 -82
  4. data/lib/cassandra/cluster.rb +3 -0
  5. data/lib/cassandra/cluster/client.rb +17 -5
  6. data/lib/cassandra/{client/connection_manager.rb → cluster/connection_pool.rb} +3 -3
  7. data/lib/cassandra/cluster/connector.rb +101 -30
  8. data/lib/cassandra/cluster/control_connection.rb +6 -7
  9. data/lib/cassandra/{client/null_logger.rb → cluster/failed_connection.rb} +12 -14
  10. data/lib/cassandra/cluster/options.rb +8 -0
  11. data/lib/cassandra/column.rb +5 -0
  12. data/lib/cassandra/driver.rb +3 -3
  13. data/lib/cassandra/errors.rb +5 -5
  14. data/lib/cassandra/execution/options.rb +13 -6
  15. data/lib/cassandra/execution/trace.rb +4 -4
  16. data/lib/cassandra/future.rb +4 -0
  17. data/lib/cassandra/keyspace.rb +5 -0
  18. data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +7 -2
  19. data/lib/cassandra/load_balancing/policies/token_aware.rb +1 -3
  20. data/lib/cassandra/load_balancing/policies/white_list.rb +3 -6
  21. data/lib/cassandra/null_logger.rb +35 -0
  22. data/lib/cassandra/protocol/cql_protocol_handler.rb +4 -0
  23. data/lib/cassandra/protocol/requests/query_request.rb +1 -11
  24. data/lib/cassandra/result.rb +4 -6
  25. data/lib/cassandra/session.rb +3 -0
  26. data/lib/cassandra/statements/prepared.rb +5 -1
  27. data/lib/cassandra/table.rb +5 -0
  28. data/lib/cassandra/util.rb +130 -0
  29. data/lib/cassandra/version.rb +1 -1
  30. metadata +9 -20
  31. data/lib/cassandra/client.rb +0 -144
  32. data/lib/cassandra/client/batch.rb +0 -212
  33. data/lib/cassandra/client/client.rb +0 -591
  34. data/lib/cassandra/client/column_metadata.rb +0 -54
  35. data/lib/cassandra/client/connector.rb +0 -273
  36. data/lib/cassandra/client/execute_options_decoder.rb +0 -59
  37. data/lib/cassandra/client/peer_discovery.rb +0 -50
  38. data/lib/cassandra/client/prepared_statement.rb +0 -314
  39. data/lib/cassandra/client/query_result.rb +0 -230
  40. data/lib/cassandra/client/request_runner.rb +0 -70
  41. data/lib/cassandra/client/result_metadata.rb +0 -48
  42. data/lib/cassandra/client/void_result.rb +0 -78
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NTA3NTE1Y2M2Y2U5MmJmNGVlODZlZmI4YjI1NWE3OGNhOTY4OTgzOA==
4
+ OTcyZDFmZGEzMGZhODU2MTRkYmRlMjhiNWIyYWI0OWVkODZmYmY3Mg==
5
5
  data.tar.gz: !binary |-
6
- ZDg0NTUxZTFmNDBjYmVjZDFlYjE1MzUwODc3MGFkODkwNTBjZmZjOQ==
6
+ MzQ5Y2M4YmI1YzQ3Yjk3MDU4YzI1YWJjYmZjYTc2YTE4NjA4ZTRmMQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- OGI2NTA0NDQ2ZTk2ODlmNDFkNTkyMTYxZDBmY2I3OTNhNjQ3Y2ExNGQzZDlh
10
- YzkzZDA0MGIwM2MzODRkMmJjYjI1OTRjNzYzYzg1MTNiNzFjMmJmOGUyZWEz
11
- MjczMzZmNzg1OTZjN2NjY2JhMjc3YjYxMTJhOTc2MTVjOTI1MTQ=
9
+ NmFiNzc1M2E0NTk0YmIyY2VjNTcxZjI2ZDcwMGE5NmUzZDhhZGU5NmYyMTRj
10
+ M2NiZjgwNzdmMzJjOTA4YzBjNjVlYjRlNmJmZjE3MjZhOWY1ODRlOTQwM2Qy
11
+ YzYyNzc2MTFmYzNjOWNiZmI4NjY3Yjg4ZjBjYjJkMWRmMTY2Mzg=
12
12
  data.tar.gz: !binary |-
13
- MTc1ZDhiYmMyZDYzMDhjZDQzZmUxM2MzMzQ0NDNjNWFhOTIxZGY4ZjNiZDRm
14
- Y2I2YmYzYmNkZmY0NGIyNzNkOGU3YWM4MTg3MDhjYTZhOTYyNWY2YWQ4ODI2
15
- YmU3OTQ4ZjQ4NGU4NWY0MTkzOTQ4MWFiM2U0YzRiYTI4MzVjZmE=
13
+ M2EzNzFhZDM5MTNkMTlhNzVhZTE1YzdmZGMyMWEyY2ZmZTc4N2YwMGIwMjll
14
+ ODhkNzFjODE3NmMxYTE5Y2U4MzA0ZjViMTQ3MzYyMjcwZDJkNjgyZjg1Y2Q2
15
+ NWY3MjRjM2QwY2VhMTU4MGIzOWM0YmY2MjI4ZmYyOTdhMDU0NDE=
data/README.md CHANGED
@@ -9,10 +9,10 @@ the Cassandra Query Language version 3 (CQL3) and Cassandra's native protocol.
9
9
 
10
10
  - Code: https://github.com/datastax/ruby-driver
11
11
  - Docs: http://datastax.github.io/ruby-driver/
12
- - JIRA: https://datastax-oss.atlassian.net/browse/RUBY
13
- - MAILING LIST: https://groups.google.com/a/lists.datastax.com/forum/#!forum/ruby-driver-user
12
+ - Jira: https://datastax-oss.atlassian.net/browse/RUBY
13
+ - Mailing List: https://groups.google.com/a/lists.datastax.com/forum/#!forum/ruby-driver-user
14
14
  - IRC: #datastax-drivers on [irc.freenode.net](http://freenode.net>)
15
- - TWITTER: Follow the latest news about DataStax Drivers - [@avalanche123](http://twitter.com/avalanche123), [@mfiguiere](http://twitter.com/mfiguiere), [@al3xandru](https://twitter.com/al3xandru)
15
+ - Twitter: Follow the latest news about DataStax Drivers - [@avalanche123](http://twitter.com/avalanche123), [@mfiguiere](http://twitter.com/mfiguiere), [@al3xandru](https://twitter.com/al3xandru)
16
16
 
17
17
  This driver is based on [the cql-rb gem](https://github.com/iconara/cql-rb) by [Theo Hultberg](https://github.com/iconara) and we added support for:
18
18
 
@@ -26,10 +26,11 @@ This driver is based on [the cql-rb gem](https://github.com/iconara/cql-rb) by [
26
26
 
27
27
  This driver works exclusively with the Cassandra Query Language v3 (CQL3) and Cassandra's native protocol. The current version works with:
28
28
 
29
- * Cassandra versions 1.2 and 2.0
30
- * Ruby 1.9.3 and 2.0
29
+ * Apache Cassandra versions 1.2 and 2.0
30
+ * DataStax Enterprise 3.1, 3.2, 4.0 and 4.5
31
+ * Ruby (MRI) 1.9.3, 2.0 and 2.1
31
32
  * JRuby 1.7
32
- * Rubinius 2.1
33
+ * Rubinius 2.2
33
34
 
34
35
  __Note__: JRuby 1.6 is not officially supported, although 1.6.8 should work.
35
36
 
@@ -75,7 +76,7 @@ gem install cassandra-driver --pre
75
76
  Install via Gemfile
76
77
 
77
78
  ```ruby
78
- gem 'cassandra-driver', '~> 1.0.0.beta'
79
+ gem 'cassandra-driver', '~> 1.0.0.rc'
79
80
  ```
80
81
 
81
82
  Note: if you want to use compression you should also install [snappy](http://rubygems.org/gems/snappy) or [lz4-ruby](http://rubygems.org/gems/lz4-ruby). [Read more about compression.](http://datastax.github.io/ruby-driver/features/#compression)
@@ -85,13 +86,45 @@ Note: if you want to use compression you should also install [snappy](http://rub
85
86
 
86
87
  Some of the new features added to the driver have unfortunately led to changes in the original cql-rb API. In the examples directory, you can find [an example of how to wrap the ruby driver to achieve almost complete interface parity with cql-rb](https://github.com/datastax/ruby-driver/blob/master/examples/cql-rb-wrapper.rb) to assist you with gradual upgrade.
87
88
 
88
- ## What's new in v1.0.0.beta.3
89
+ ## What's new in v1.0.0
89
90
 
90
91
  Current release introduces the following new features:
91
92
 
92
- * [Token-aware load balancing policy](http://datastax.github.io/ruby-driver/features/load_balancing/token_aware/)
93
+ * [Asynchronous execution](http://datastax.github.io/ruby-driver/features/asynchronous_io/)
94
+ * One-off, [prepared](http://datastax.github.io/ruby-driver/features/basics/prepared_statements/) and [batch statements](http://datastax.github.io/ruby-driver/features/basics/batch_statements/)
95
+ * Automatic peer discovery and cluster metadata with [support for change notifications](http://datastax.github.io/ruby-driver/features/state_listeners/)
96
+ * Various [load-balancing](http://datastax.github.io/ruby-driver/features/load_balancing/), [retry](http://datastax.github.io/ruby-driver/features/retry_policies/) and reconnection policies, [with ability to write your own](http://datastax.github.io/ruby-driver/features/load_balancing/implementing_a_policy/)
93
97
  * [SSL encryption](http://datastax.github.io/ruby-driver/features/security/ssl_encryption/)
94
- * Domain names
98
+ * [Flexible and robust error handling](http://datastax.github.io/ruby-driver/features/error_handling/)
99
+ * [Per-request execution information and tracing](http://datastax.github.io/ruby-driver/features/debugging/)
100
+ * [Configurable address resolution](http://datastax.github.io/ruby-driver/features/address_resolution/)
101
+
102
+ ## Code examples
103
+
104
+ The DataStax Ruby Driver uses the awesome [Cucumber Framework](http://cukes.info/) for both end-to-end, or acceptance, testing and constructing documentation. All of the features supported by the driver have appropriate acceptance tests with easy-to-copy code examples in the `features/` directory.
105
+
106
+ ## Running tests
107
+
108
+ If you don't feel like reading through the following instructions on how to run ruby-driver tests, feel free to [check out .travis.yml for the entire build code](https://github.com/datastax/ruby-driver/blob/master/.travis.yml).
109
+
110
+ * Check out the driver codebase and install test dependencies:
111
+
112
+ ```bash
113
+ git clone https://github.com/datastax/ruby-driver.git
114
+ cd ruby-driver
115
+ bundle install --without docs
116
+ ```
117
+
118
+ * [Install ccm](http://www.datastax.com/dev/blog/ccm-a-development-tool-for-creating-local-cassandra-clusters)
119
+
120
+ * Run tests:
121
+
122
+ ```bash
123
+ bundle exec cucumber # runs end-to-end tests (or bundle exec rake cucumber)
124
+ bundle exec rspec # runs unit tests (or bundle exec rake rspec)
125
+ bundle exec rake integration # run integration tests
126
+ bundle exec rake test # run both as well as integration tests
127
+ ```
95
128
 
96
129
  ## Changelog & versioning
97
130
 
@@ -105,7 +138,9 @@ Prereleases will be stable, in the sense that they will have finished and proper
105
138
 
106
139
  * JRuby 1.6 is not officially supported, although 1.6.8 should work, if you're stuck in JRuby 1.6.8 try and see if it works for you.
107
140
  * Because the driver reactor is using `IO.select`, the maximum number of tcp connections allowed is 1024.
141
+ * Because the driver uses `IO#write_nonblock`, Windows is not supported.
108
142
 
143
+ Please [refer to the usage documentation for more information on common pitfalls](http://datastax.github.io/ruby-driver/features/)
109
144
 
110
145
  ## Credits
111
146
 
@@ -66,21 +66,22 @@ module Cassandra
66
66
  # in `:hosts` option.
67
67
  #
68
68
  # @option options [Numeric] :connect_timeout (10) connection timeout in
69
- # seconds.
69
+ # seconds. Setting value to `nil` will reset it to 5 seconds.
70
70
  #
71
71
  # @option options [Numeric] :timeout (10) request execution timeout in
72
- # seconds.
72
+ # seconds. Setting value to `nil` will remove request timeout.
73
73
  #
74
74
  # @option options [Numeric] :heartbeat_interval (30) how often should a
75
75
  # heartbeat be sent to determine if a connection is alive. Several things to
76
76
  # note about this option. Only one heartbeat request will ever be
77
77
  # outstanding on a given connection. Each heatbeat will be sent in at least
78
78
  # `:heartbeat_interval` seconds after the last request has been sent on a
79
- # given connection.
79
+ # given connection. Setting value to `nil` will remove connection timeout.
80
80
  #
81
81
  # @option options [Numeric] :idle_timeout (60) period of inactivity after
82
82
  # which a connection is considered dead. Note that this value should be at
83
- # least a few times larger than `:heartbeat_interval`.
83
+ # least a few times larger than `:heartbeat_interval`. Setting value to
84
+ # `nil` will remove automatic connection termination.
84
85
  #
85
86
  # @option options [String] :username (none) username to use for
86
87
  # authentication to cassandra. Note that you must also specify `:password`.
@@ -139,15 +140,15 @@ module Cassandra
139
140
  # @option options [Boolean] :trace (false) whether or not to trace all
140
141
  # requests by default.
141
142
  #
142
- # @option options [Integer] :page_size (nil) default page size for all select
143
- # queries.
143
+ # @option options [Integer] :page_size (10000) default page size for all
144
+ # select queries. Set this value to `nil` to disable paging.
144
145
  #
145
146
  # @option options [Hash{String => String}] :credentials (none) a hash of credentials - to be used with [credentials authentication in cassandra 1.2](https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v1.spec#L238-L250). Note that if you specified `:username` and `:password` options, those credentials are configured automatically.
146
147
  #
147
148
  # @option options [Cassandra::Auth::Provider] :auth_provider (none) a custom auth provider to be used with [SASL authentication in cassandra 2.0](https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v2.spec#L257-L273). Note that if you have specified `:username` and `:password`, then a {Cassandra::Auth::Providers::Password} will be used automatically.
148
149
  #
149
- # @option options [Cassandra::Compressor] :compressor (none) a custom
150
- # compressor. Note that if you have specified `:compression`, an
150
+ # @option options [Cassandra::Compression::Compressor] :compressor (none) a
151
+ # custom compressor. Note that if you have specified `:compression`, an
151
152
  # appropriate compressor will be provided automatically.
152
153
  #
153
154
  # @option options [Cassandra::AddressResolution::Policy]
@@ -157,10 +158,10 @@ module Cassandra
157
158
  # appropriate address resolution policy will be provided automatically.
158
159
  #
159
160
  # @option options [Object<#all, #error, #value, #promise>] :futures_factory
160
- # (none) a custom futures factory to assist with integration into existing
161
- # futures library. Note that promises returned by this object must conform
162
- # to {Cassandra::Promise} api, which is not yet public. Things may change,
163
- # use at your own risk.
161
+ # default: {Cassandra::Future} a futures factory to assist with integration
162
+ # into existing futures library. Note that promises returned by this object
163
+ # must conform to {Cassandra::Promise} api, which is not yet public. Things
164
+ # may change, use at your own risk.
164
165
  #
165
166
  # @example Connecting to localhost
166
167
  # cluster = Cassandra.cluster
@@ -174,6 +175,16 @@ module Cassandra
174
175
  #
175
176
  # @return [Cassandra::Cluster] a cluster instance
176
177
  def self.cluster(options = {})
178
+ cluster_async(options).get
179
+ end
180
+
181
+ # Creates a {Cassandra::Cluster} instance
182
+ #
183
+ # @see Cassandra.cluster
184
+ #
185
+ # @return [Cassandra::Future<Cassandra::Cluster>] a future resolving to the
186
+ # cluster instance.
187
+ def self.cluster_async(options = {})
177
188
  options = options.select do |key, value|
178
189
  [ :credentials, :auth_provider, :compression, :hosts, :logger, :port,
179
190
  :load_balancing_policy, :reconnection_policy, :retry_policy, :listeners,
@@ -184,6 +195,8 @@ module Cassandra
184
195
  ].include?(key)
185
196
  end
186
197
 
198
+ futures = options.fetch(:futures_factory, Future)
199
+
187
200
  has_username = options.has_key?(:username)
188
201
  has_password = options.has_key?(:password)
189
202
  if has_username || has_password
@@ -195,11 +208,13 @@ module Cassandra
195
208
  raise ::ArgumentError, "both :username and :password options must be specified, but only :password given"
196
209
  end
197
210
 
198
- username = String(options.delete(:username))
199
- password = String(options.delete(:password))
211
+ username = options.delete(:username)
212
+ password = options.delete(:password)
200
213
 
201
- raise ::ArgumentError, ":username cannot be empty" if username.empty?
202
- raise ::ArgumentError, ":password cannot be empty" if password.empty?
214
+ Util.assert_instance_of(::String, username) { ":username must be a String, #{username.inspect} given" }
215
+ Util.assert_instance_of(::String, password) { ":password must be a String, #{password.inspect} given" }
216
+ Util.assert_not_empty(username) { ":username cannot be empty" }
217
+ Util.assert_not_empty(password) { ":password cannot be empty" }
203
218
 
204
219
  options[:credentials] = {:username => username, :password => password}
205
220
  options[:auth_provider] = Auth::Providers::Password.new(username, password)
@@ -208,17 +223,13 @@ module Cassandra
208
223
  if options.has_key?(:credentials)
209
224
  credentials = options[:credentials]
210
225
 
211
- unless credentials.is_a?(Hash)
212
- raise ::ArgumentError, ":credentials must be a hash, #{credentials.inspect} given"
213
- end
226
+ Util.assert_instance_of(::Hash, credentials) { ":credentials must be a hash, #{credentials.inspect} given" }
214
227
  end
215
228
 
216
229
  if options.has_key?(:auth_provider)
217
230
  auth_provider = options[:auth_provider]
218
231
 
219
- unless auth_provider.respond_to?(:create_authenticator)
220
- raise ::ArgumentError, ":auth_provider #{auth_provider.inspect} must respond to :create_authenticator, but doesn't"
221
- end
232
+ Util.assert_responds_to(:create_authenticator, auth_provider) { ":auth_provider #{auth_provider.inspect} must respond to :create_authenticator, but doesn't" }
222
233
  end
223
234
 
224
235
  has_client_cert = options.has_key?(:client_cert)
@@ -236,13 +247,8 @@ module Cassandra
236
247
  client_cert = ::File.expand_path(options[:client_cert])
237
248
  private_key = ::File.expand_path(options[:private_key])
238
249
 
239
- unless ::File.exists?(client_cert)
240
- raise ::ArgumentError, ":client_cert #{client_cert.inspect} doesn't exist"
241
- end
242
-
243
- unless ::File.exists?(private_key)
244
- raise ::ArgumentError, ":private_key #{private_key.inspect} doesn't exist"
245
- end
250
+ Util.assert_file_exists(client_cert) { ":client_cert #{client_cert.inspect} doesn't exist" }
251
+ Util.assert_file_exists(private_key) { ":private_key #{private_key.inspect} doesn't exist" }
246
252
  end
247
253
 
248
254
  has_server_cert = options.has_key?(:server_cert)
@@ -250,9 +256,7 @@ module Cassandra
250
256
  if has_server_cert
251
257
  server_cert = ::File.expand_path(options[:server_cert])
252
258
 
253
- unless ::File.exists?(server_cert)
254
- raise ::ArgumentError, ":server_cert #{server_cert.inspect} doesn't exist"
255
- end
259
+ Util.assert_file_exists(server_cert) { ":server_cert #{server_cert.inspect} doesn't exist" }
256
260
  end
257
261
 
258
262
  if has_client_cert || has_server_cert
@@ -279,9 +283,7 @@ module Cassandra
279
283
  if options.has_key?(:ssl)
280
284
  ssl = options[:ssl]
281
285
 
282
- unless ssl.is_a?(::TrueClass) || ssl.is_a?(::FalseClass) || ssl.is_a?(::OpenSSL::SSL::SSLContext)
283
- raise ::ArgumentError, ":ssl must be a boolean or an OpenSSL::SSL::SSLContext, #{ssl.inspect} given"
284
- end
286
+ Util.assert_instance_of_one_of([::TrueClass, ::FalseClass, ::OpenSSL::SSL::SSLContext], ssl) { ":ssl must be a boolean or an OpenSSL::SSL::SSLContext, #{ssl.inspect} given" }
285
287
  end
286
288
 
287
289
  if options.has_key?(:compression)
@@ -303,26 +305,20 @@ module Cassandra
303
305
  compressor = options[:compressor]
304
306
  methods = [:algorithm, :compress?, :compress, :decompress]
305
307
 
306
- unless methods.all? {|method| compressor.respond_to?(method)}
307
- raise ::ArgumentError, ":compressor #{compressor.inspect} must respond to #{methods.inspect}, but doesn't"
308
- end
308
+ Util.assert_responds_to_all(methods, compressor) { ":compressor #{compressor.inspect} must respond to #{methods.inspect}, but doesn't" }
309
309
  end
310
310
 
311
311
  if options.has_key?(:logger)
312
312
  logger = options[:logger]
313
313
  methods = [:debug, :info, :warn, :error, :fatal]
314
314
 
315
- unless methods.all? {|method| logger.respond_to?(method)}
316
- raise ::ArgumentError, ":logger #{logger.inspect} must respond to #{methods.inspect}, but doesn't"
317
- end
315
+ Util.assert_responds_to_all(methods, logger) { ":logger #{logger.inspect} must respond to #{methods.inspect}, but doesn't" }
318
316
  end
319
317
 
320
318
  if options.has_key?(:port)
321
319
  port = options[:port] = Integer(options[:port])
322
320
 
323
- if port < 0 || port > 65536
324
- raise ::ArgumentError, ":port must be a valid ip port, #{port.given}"
325
- end
321
+ Util.assert_one_of(0..65536, port) { ":port must be a valid ip port, #{port} given" }
326
322
  end
327
323
 
328
324
  if options.has_key?(:datacenter)
@@ -330,34 +326,38 @@ module Cassandra
330
326
  end
331
327
 
332
328
  if options.has_key?(:connect_timeout)
333
- timeout = options[:connect_timeout] = Integer(options[:connect_timeout])
329
+ timeout = options[:connect_timeout]
334
330
 
335
- if timeout < 0
336
- raise ::ArgumentError, ":connect_timeout must be a positive value, #{timeout.given}"
331
+ unless timeout.nil?
332
+ Util.assert_instance_of(::Numeric, timeout) { ":connect_timeout must be a number of seconds, #{timeout} given" }
333
+ Util.assert(timeout > 0) { ":connect_timeout must be greater than 0, #{timeout} given" }
337
334
  end
338
335
  end
339
336
 
340
337
  if options.has_key?(:timeout)
341
- timeout = options[:timeout] = Integer(options[:timeout])
338
+ timeout = options[:timeout]
342
339
 
343
- if timeout < 0
344
- raise ::ArgumentError, ":timeout must be a positive value, #{timeout.given}"
340
+ unless timeout.nil?
341
+ Util.assert_instance_of(::Numeric, timeout) { ":timeout must be a number of seconds, #{timeout} given" }
342
+ Util.assert(timeout > 0) { ":timeout must be greater than 0, #{timeout} given" }
345
343
  end
346
344
  end
347
345
 
348
346
  if options.has_key?(:heartbeat_interval)
349
- timeout = options[:heartbeat_interval] = Integer(options[:heartbeat_interval])
347
+ timeout = options[:heartbeat_interval]
350
348
 
351
- if timeout < 0
352
- raise ::ArgumentError, ":heartbeat_interval must be a positive value, #{timeout.given}"
349
+ unless timeout.nil?
350
+ Util.assert_instance_of(::Numeric, timeout) { ":heartbeat_interval must be a number of seconds, #{timeout} given" }
351
+ Util.assert(timeout > 0) { ":heartbeat_interval must be greater than 0, #{timeout} given" }
353
352
  end
354
353
  end
355
354
 
356
355
  if options.has_key?(:idle_timeout)
357
- timeout = options[:idle_timeout] = Integer(options[:idle_timeout])
356
+ timeout = options[:idle_timeout]
358
357
 
359
- if timeout < 0
360
- raise ::ArgumentError, ":idle_timeout must be a positive value, #{timeout.given}"
358
+ unless timeout.nil?
359
+ Util.assert_instance_of(::Numeric, timeout) { ":idle_timeout must be a number of seconds, #{timeout} given" }
360
+ Util.assert(timeout > 0) { ":idle_timeout must be greater than 0, #{timeout} given" }
361
361
  end
362
362
  end
363
363
 
@@ -365,42 +365,32 @@ module Cassandra
365
365
  load_balancing_policy = options[:load_balancing_policy]
366
366
  methods = [:host_up, :host_down, :host_found, :host_lost, :setup, :distance, :plan]
367
367
 
368
- unless methods.all? {|method| load_balancing_policy.respond_to?(method)}
369
- raise ::ArgumentError, ":load_balancing_policy #{load_balancing_policy.inspect} must respond to #{methods.inspect}, but doesn't"
370
- end
368
+ Util.assert_responds_to_all(methods, load_balancing_policy) { ":load_balancing_policy #{load_balancing_policy.inspect} must respond to #{methods.inspect}, but doesn't" }
371
369
  end
372
370
 
373
371
  if options.has_key?(:reconnection_policy)
374
372
  reconnection_policy = options[:reconnection_policy]
375
373
 
376
- unless reconnection_policy.respond_to?(:schedule)
377
- raise ::ArgumentError, ":reconnection_policy #{reconnection_policy.inspect} must respond to :schedule, but doesn't"
378
- end
374
+ Util.assert_responds_to(:schedule, reconnection_policy) { ":reconnection_policy #{reconnection_policy.inspect} must respond to :schedule, but doesn't" }
379
375
  end
380
376
 
381
377
  if options.has_key?(:retry_policy)
382
378
  retry_policy = options[:retry_policy]
383
379
  methods = [:read_timeout, :write_timeout, :unavailable]
384
380
 
385
- unless methods.all? {|method| retry_policy.respond_to?(method)}
386
- raise ::ArgumentError, ":retry_policy #{retry_policy.inspect} must respond to #{methods.inspect}, but doesn't"
387
- end
381
+ Util.assert_responds_to_all(methods, retry_policy) { ":retry_policy #{retry_policy.inspect} must respond to #{methods.inspect}, but doesn't" }
388
382
  end
389
383
 
390
384
  if options.has_key?(:listeners)
391
385
  listeners = options[:listeners]
392
386
 
393
- unless listeners.respond_to?(:each)
394
- raise ::ArgumentError, ":listeners must be an Enumerable, #{listeners.inspect} given"
395
- end
387
+ Util.assert_instance_of(::Enumerable, listeners) { ":listeners must be an Enumerable, #{listeners.inspect} given" }
396
388
  end
397
389
 
398
390
  if options.has_key?(:consistency)
399
391
  consistency = options[:consistency]
400
392
 
401
- unless CONSISTENCIES.include?(consistency)
402
- raise ::ArgumentError, ":consistency must be one of #{CONSISTENCIES.inspect}, #{consistency.inspect} given"
403
- end
393
+ Util.assert_one_of(CONSISTENCIES, consistency) { ":consistency must be one of #{CONSISTENCIES.inspect}, #{consistency.inspect} given" }
404
394
  end
405
395
 
406
396
  if options.has_key?(:trace)
@@ -408,10 +398,11 @@ module Cassandra
408
398
  end
409
399
 
410
400
  if options.has_key?(:page_size)
411
- page_size = options[:page_size] = Integer(options[:page_size])
401
+ page_size = options[:page_size]
412
402
 
413
- if page_size <= 0
414
- raise ::ArgumentError, ":page_size must be a positive integer, #{page_size.inspect} given"
403
+ unless page_size.nil?
404
+ page_size = options[:page_size] = Integer(page_size)
405
+ Util.assert(page_size > 0) { ":page_size must be a positive integer, #{page_size.inspect} given" }
415
406
  end
416
407
  end
417
408
 
@@ -419,9 +410,7 @@ module Cassandra
419
410
  futures_factory = options[:futures_factory]
420
411
  methods = [:error, :value, :promise, :all]
421
412
 
422
- unless methods.all? {|method| futures_factory.respond_to?(method)}
423
- raise ::ArgumentError, ":futures_factory #{futures_factory.inspect} must respond to #{methods.inspect}, but doesn't"
424
- end
413
+ Util.assert_responds_to_all(methods, futures_factory) { ":futures_factory #{futures_factory.inspect} must respond to #{methods.inspect}, but doesn't" }
425
414
  end
426
415
 
427
416
  if options.has_key?(:address_resolution)
@@ -429,6 +418,7 @@ module Cassandra
429
418
 
430
419
  case address_resolution
431
420
  when :none
421
+ # do nothing
432
422
  when :ec2_multi_region
433
423
  options[:address_resolution_policy] = AddressResolution::Policies::EC2MultiRegion.new
434
424
  else
@@ -439,9 +429,7 @@ module Cassandra
439
429
  if options.has_key?(:address_resolution_policy)
440
430
  address_resolver = options[:address_resolution_policy]
441
431
 
442
- unless address_resolver.respond_to?(:resolve)
443
- raise ::ArgumentError, ":address_resolution_policy must respond to :resolve, #{address_resolver.inspect} but doesn't"
444
- end
432
+ Util.assert_responds_to(:resolve, address_resolver) { ":address_resolution_policy must respond to :resolve, #{address_resolver.inspect} but doesn't" }
445
433
  end
446
434
 
447
435
  hosts = []
@@ -462,8 +450,20 @@ module Cassandra
462
450
  if hosts.empty?
463
451
  raise ::ArgumentError, ":hosts #{options[:hosts].inspect} could not be resolved to any ip address"
464
452
  end
453
+ rescue => e
454
+ futures.error(e)
455
+ else
456
+ promise = futures.promise
457
+
458
+ Driver.new(options).connect(hosts).on_complete do |f|
459
+ if f.resolved?
460
+ promise.fulfill(f.value)
461
+ else
462
+ f.on_failure {|e| promise.break(e)}
463
+ end
464
+ end
465
465
 
466
- Driver.new(options).connect(hosts).value
466
+ promise.future
467
467
  end
468
468
  end
469
469
 
@@ -473,7 +473,7 @@ require 'cassandra/time_uuid'
473
473
  require 'cassandra/compression'
474
474
  require 'cassandra/protocol'
475
475
  require 'cassandra/auth'
476
- require 'cassandra/client'
476
+ require 'cassandra/null_logger'
477
477
 
478
478
  require 'cassandra/future'
479
479
  require 'cassandra/cluster'