cassandra-driver 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- OTcyZDFmZGEzMGZhODU2MTRkYmRlMjhiNWIyYWI0OWVkODZmYmY3Mg==
4
+ ODg3NTI1OTYyMmViMzc5OWU4YjQyYTViYmQyMDFmZmNjOTIzMGExNg==
5
5
  data.tar.gz: !binary |-
6
- MzQ5Y2M4YmI1YzQ3Yjk3MDU4YzI1YWJjYmZjYTc2YTE4NjA4ZTRmMQ==
6
+ NjI3OWQyZDc0NTM1MmE4M2VlMWVhM2EwMTRlMGVjYzdjODQyOGIzNw==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NmFiNzc1M2E0NTk0YmIyY2VjNTcxZjI2ZDcwMGE5NmUzZDhhZGU5NmYyMTRj
10
- M2NiZjgwNzdmMzJjOTA4YzBjNjVlYjRlNmJmZjE3MjZhOWY1ODRlOTQwM2Qy
11
- YzYyNzc2MTFmYzNjOWNiZmI4NjY3Yjg4ZjBjYjJkMWRmMTY2Mzg=
9
+ ZGFhMWZjYWUyMTdlYzllODBmNGVjMTkzZjU5YWYyN2M3MjQwZmVhNTI3NzIz
10
+ ZGFiYTA3NzAyNWU0MWQ4Njg1OWFhNTViNTQ0NDFmMDU4NmQwMWQ3OTFkNjBj
11
+ NTdlM2ZjOTAwYTA5Njk4ZWQ2Nzk3ZjQ1OWM1MWU5YzcyODcwZmY=
12
12
  data.tar.gz: !binary |-
13
- M2EzNzFhZDM5MTNkMTlhNzVhZTE1YzdmZGMyMWEyY2ZmZTc4N2YwMGIwMjll
14
- ODhkNzFjODE3NmMxYTE5Y2U4MzA0ZjViMTQ3MzYyMjcwZDJkNjgyZjg1Y2Q2
15
- NWY3MjRjM2QwY2VhMTU4MGIzOWM0YmY2MjI4ZmYyOTdhMDU0NDE=
13
+ YTQ0MDg5ZjI3Yzg5MGRiOGI1YTdlMjgwZGIxZjI1Y2ZkZDVhZWYwOGFkYTJi
14
+ MzIyOTY1OTY1ODgzMjhkYWY2ODYxYTIzZTRiYzI5OWRjODIwN2FmM2FlYTVk
15
+ YWFjOGNkMjY3OGJhYjhjZmE5ODMzMzgzMGNjNGU5ZmMyZTllYWI=
data/README.md CHANGED
@@ -16,22 +16,29 @@ the Cassandra Query Language version 3 (CQL3) and Cassandra's native protocol.
16
16
 
17
17
  This driver is based on [the cql-rb gem](https://github.com/iconara/cql-rb) by [Theo Hultberg](https://github.com/iconara) and we added support for:
18
18
 
19
- * [asynchronous execution](http://datastax.github.io/ruby-driver/features/asynchronous_io/)
20
- * 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/)
21
- * automatic peer discovery and cluster metadata
22
- * 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/)
19
+ * [Asynchronous execution](http://datastax.github.io/ruby-driver/features/asynchronous_io/)
20
+ * 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/)
21
+ * Automatic peer discovery and cluster metadata with [support for change notifications](http://datastax.github.io/ruby-driver/features/state_listeners/)
22
+ * Various [load-balancing](http://datastax.github.io/ruby-driver/features/load_balancing/), [retry](http://datastax.github.io/ruby-driver/features/retry_policies/) and [reconnection](http://datastax.github.io/ruby-driver/features/reconnection/) policies with [ability to write your own](http://datastax.github.io/ruby-driver/features/load_balancing/implementing_a_policy/)
23
23
  * [SSL encryption](http://datastax.github.io/ruby-driver/features/security/ssl_encryption/)
24
+ * [Flexible and robust error handling](http://datastax.github.io/ruby-driver/features/error_handling/)
25
+ * [Per-request execution information and tracing](http://datastax.github.io/ruby-driver/features/debugging/)
26
+ * [Configurable address resolution](http://datastax.github.io/ruby-driver/features/address_resolution/)
27
+
28
+ [Check out the slides from Ruby Driver Explained](https://speakerdeck.com/avalanche123/ruby-driver-explained) for a detailed overview of the Ruby Driver architecture.
24
29
 
25
30
  ## Compability
26
31
 
27
32
  This driver works exclusively with the Cassandra Query Language v3 (CQL3) and Cassandra's native protocol. The current version works with:
28
33
 
29
- * Apache Cassandra versions 1.2 and 2.0
34
+ * Apache Cassandra versions 1.2, 2.0 and partially 2.1
30
35
  * DataStax Enterprise 3.1, 3.2, 4.0 and 4.5
31
36
  * Ruby (MRI) 1.9.3, 2.0 and 2.1
32
37
  * JRuby 1.7
33
38
  * Rubinius 2.2
34
39
 
40
+ __Note__: Apache Cassandra 2.1 support is limited to the Cassandra 2.0 API, e.g. no user-defined types.
41
+
35
42
  __Note__: JRuby 1.6 is not officially supported, although 1.6.8 should work.
36
43
 
37
44
  ## Quick start
@@ -57,7 +64,7 @@ end
57
64
  future.join
58
65
  ```
59
66
 
60
- The host you specify is just a seed node, the driver will automatically discover all peers in the cluster.
67
+ __Note__: The host you specify is just a seed node, the driver will automatically discover all peers in the cluster.
61
68
 
62
69
  Read more:
63
70
 
@@ -70,34 +77,32 @@ Read more:
70
77
  Install via rubygems
71
78
 
72
79
  ```bash
73
- gem install cassandra-driver --pre
80
+ gem install cassandra-driver
74
81
  ```
75
82
 
76
83
  Install via Gemfile
77
84
 
78
85
  ```ruby
79
- gem 'cassandra-driver', '~> 1.0.0.rc'
86
+ gem 'cassandra-driver', '~> 1.0.0'
80
87
  ```
81
88
 
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)
89
+ __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)
83
90
 
84
91
 
85
92
  ## Upgrading from cql-rb
86
93
 
87
94
  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.
88
95
 
89
- ## What's new in v1.0.0
96
+ ## What's new in v1.1.0
90
97
 
91
98
  Current release introduces the following new features:
92
99
 
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/)
97
- * [SSL encryption](http://datastax.github.io/ruby-driver/features/security/ssl_encryption/)
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/)
100
+ * Ability to disable automatic schema synchronization
101
+ * Schema change event storm protection using a sliding delay
102
+ * [`Cassandra::LoadBalancing::Policy#teardown`](http://datastax.github.io/ruby-driver/api/load_balancing/policy/#teardown-instance_method) for cleaning up resources
103
+ * [`Cassandra::Cluster#refresh_schema`](http://datastax.github.io/ruby-driver/api/cluster/#refresh_schema-instance_method) for manually refreshing schema metadata
104
+ * Host list randomization to prevent hotspots between multiple clients
105
+ * Future listeners run in a dedicated threadpool to not block the reactor
101
106
 
102
107
  ## Code examples
103
108
 
data/lib/cassandra.rb CHANGED
@@ -25,7 +25,6 @@ require 'ipaddr'
25
25
  require 'set'
26
26
  require 'bigdecimal'
27
27
  require 'forwardable'
28
- require 'timeout'
29
28
  require 'digest'
30
29
  require 'stringio'
31
30
  require 'resolv'
@@ -51,7 +50,7 @@ module Cassandra
51
50
  # @see https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v1.spec#L591-L603 Description of possible types of writes in Apache Cassandra native protocol spec v1
52
51
  WRITE_TYPES = [:simple, :batch, :unlogged_batch, :counter, :batch_log].freeze
53
52
 
54
- # Creates a {Cassandra::Cluster} instance
53
+ # Creates a {Cassandra::Cluster Cluster instance}.
55
54
  #
56
55
  # @option options [Array<String, IPAddr>] :hosts (['127.0.0.1']) a list of
57
56
  # initial addresses. Note that the entire list of cluster members will be
@@ -65,6 +64,10 @@ module Cassandra
65
64
  # can skip this option if you specify only hosts from the local datacenter
66
65
  # in `:hosts` option.
67
66
  #
67
+ # @option options [Boolean] :shuffle_replicas (true) whether replicas list
68
+ # found by the default Token-Aware Load Balancing Policy should be
69
+ # shuffled. See {Cassandra::LoadBalancing::Policies::TokenAware#initialize Token-Aware Load Balancing Policy}.
70
+ #
68
71
  # @option options [Numeric] :connect_timeout (10) connection timeout in
69
72
  # seconds. Setting value to `nil` will reset it to 5 seconds.
70
73
  #
@@ -119,12 +122,33 @@ module Cassandra
119
122
  # address resolver to use. Must be one of `:none` or
120
123
  # `:ec2_multi_region`.
121
124
  #
125
+ # @option options [Boolean] :synchronize_schema (true) whether the driver
126
+ # should automatically keep schema metadata synchronized. When enabled, the
127
+ # driver updates schema metadata after receiving schema change
128
+ # notifications from Cassandra. Setting this setting to `false` disables
129
+ # automatic schema updates. Schema metadata is used by the driver to
130
+ # determine cluster partitioners as well as to find partition keys and
131
+ # replicas of prepared statements, this information makes token aware load
132
+ # balancing possible. One can still {Cassandra::Cluster#refresh_schema refresh schema manually}.
133
+ #
134
+ # @option options [Numeric] :schema_refresh_delay (1) the driver will wait
135
+ # for `:schema_refresh_delay` before fetching metadata after receiving a
136
+ # schema change event. This timer is restarted every time a new schema
137
+ # change event is received. Finally, when the timer expires or a maximum
138
+ # wait time of `:schema_refresh_timeout` has been reached, a schema refresh
139
+ # attempt will be made and the timeout is reset.
140
+ #
141
+ # @option options [Numeric] :schema_refresh_timeout (10) the maximum delay
142
+ # before automatically refreshing schema. Such delay can occur whenever
143
+ # multiple schema change events are continuously arriving within
144
+ # `:schema_refresh_delay` interval.
145
+ #
122
146
  # @option options [Cassandra::Reconnection::Policy] :reconnection_policy
123
- # default: {Cassandra::Reconnection::Policies::Exponential}. Note that the
124
- # default policy is configured with `(0.5, 30, 2)`.
147
+ # default: {Cassandra::Reconnection::Policies::Exponential Exponential}.
148
+ # Note that the default policy is configured with `(0.5, 30, 2)`.
125
149
  #
126
150
  # @option options [Cassandra::Retry::Policy] :retry_policy default:
127
- # {Cassandra::Retry::Policies::Default}.
151
+ # {Cassandra::Retry::Policies::Default Default Retry Policy}.
128
152
  #
129
153
  # @option options [Logger] :logger (none) logger. a {Logger} instance from the
130
154
  # standard library or any object responding to standard log methods
@@ -145,7 +169,7 @@ module Cassandra
145
169
  #
146
170
  # @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.
147
171
  #
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.
172
+ # @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 Password Provider} will be used automatically.
149
173
  #
150
174
  # @option options [Cassandra::Compression::Compressor] :compressor (none) a
151
175
  # custom compressor. Note that if you have specified `:compression`, an
@@ -153,7 +177,7 @@ module Cassandra
153
177
  #
154
178
  # @option options [Cassandra::AddressResolution::Policy]
155
179
  # :address_resolution_policy default:
156
- # {Cassandra::AddressResolution::Policies::None} a custom address resolution
180
+ # {Cassandra::AddressResolution::Policies::None No Resolution Policy} a custom address resolution
157
181
  # policy. Note that if you have specified `:address_resolution`, an
158
182
  # appropriate address resolution policy will be provided automatically.
159
183
  #
@@ -178,7 +202,7 @@ module Cassandra
178
202
  cluster_async(options).get
179
203
  end
180
204
 
181
- # Creates a {Cassandra::Cluster} instance
205
+ # Creates a {Cassandra::Cluster Cluster instance}.
182
206
  #
183
207
  # @see Cassandra.cluster
184
208
  #
@@ -191,12 +215,12 @@ module Cassandra
191
215
  :consistency, :trace, :page_size, :compressor, :username, :password,
192
216
  :ssl, :server_cert, :client_cert, :private_key, :passphrase,
193
217
  :connect_timeout, :futures_factory, :datacenter, :address_resolution,
194
- :address_resolution_policy, :idle_timeout, :heartbeat_interval, :timeout
218
+ :address_resolution_policy, :idle_timeout, :heartbeat_interval, :timeout,
219
+ :synchronize_schema, :schema_refresh_delay, :schema_refresh_timeout,
220
+ :shuffle_replicas
195
221
  ].include?(key)
196
222
  end
197
223
 
198
- futures = options.fetch(:futures_factory, Future)
199
-
200
224
  has_username = options.has_key?(:username)
201
225
  has_password = options.has_key?(:password)
202
226
  if has_username || has_password
@@ -361,9 +385,23 @@ module Cassandra
361
385
  end
362
386
  end
363
387
 
388
+ if options.has_key?(:schema_refresh_delay)
389
+ timeout = options[:schema_refresh_delay]
390
+
391
+ Util.assert_instance_of(::Numeric, timeout) { ":schema_refresh_delay must be a number of seconds, #{timeout} given" }
392
+ Util.assert(timeout > 0) { ":schema_refresh_delay must be greater than 0, #{timeout} given" }
393
+ end
394
+
395
+ if options.has_key?(:schema_refresh_timeout)
396
+ timeout = options[:schema_refresh_timeout]
397
+
398
+ Util.assert_instance_of(::Numeric, timeout) { ":schema_refresh_timeout must be a number of seconds, #{timeout} given" }
399
+ Util.assert(timeout > 0) { ":schema_refresh_timeout must be greater than 0, #{timeout} given" }
400
+ end
401
+
364
402
  if options.has_key?(:load_balancing_policy)
365
403
  load_balancing_policy = options[:load_balancing_policy]
366
- methods = [:host_up, :host_down, :host_found, :host_lost, :setup, :distance, :plan]
404
+ methods = [:host_up, :host_down, :host_found, :host_lost, :setup, :teardown, :distance, :plan]
367
405
 
368
406
  Util.assert_responds_to_all(methods, load_balancing_policy) { ":load_balancing_policy #{load_balancing_policy.inspect} must respond to #{methods.inspect}, but doesn't" }
369
407
  end
@@ -382,9 +420,7 @@ module Cassandra
382
420
  end
383
421
 
384
422
  if options.has_key?(:listeners)
385
- listeners = options[:listeners]
386
-
387
- Util.assert_instance_of(::Enumerable, listeners) { ":listeners must be an Enumerable, #{listeners.inspect} given" }
423
+ options[:listeners] = Array(options[:listeners])
388
424
  end
389
425
 
390
426
  if options.has_key?(:consistency)
@@ -397,6 +433,10 @@ module Cassandra
397
433
  options[:trace] = !!options[:trace]
398
434
  end
399
435
 
436
+ if options.has_key?(:shuffle_replicas)
437
+ options[:shuffle_replicas] = !!options[:shuffle_replicas]
438
+ end
439
+
400
440
  if options.has_key?(:page_size)
401
441
  page_size = options[:page_size]
402
442
 
@@ -432,6 +472,10 @@ module Cassandra
432
472
  Util.assert_responds_to(:resolve, address_resolver) { ":address_resolution_policy must respond to :resolve, #{address_resolver.inspect} but doesn't" }
433
473
  end
434
474
 
475
+ if options.has_key?(:synchronize_schema)
476
+ options[:synchronize_schema] = !!options[:synchronize_schema]
477
+ end
478
+
435
479
  hosts = []
436
480
 
437
481
  Array(options.fetch(:hosts, '127.0.0.1')).each do |host|
@@ -450,20 +494,14 @@ module Cassandra
450
494
  if hosts.empty?
451
495
  raise ::ArgumentError, ":hosts #{options[:hosts].inspect} could not be resolved to any ip address"
452
496
  end
497
+
498
+ hosts.shuffle!
453
499
  rescue => e
500
+ futures = options.fetch(:futures_factory) { Driver.new.futures_factory }
454
501
  futures.error(e)
455
502
  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
-
466
- promise.future
503
+ driver = Driver.new(options)
504
+ driver.connect(hosts)
467
505
  end
468
506
  end
469
507
 
@@ -475,6 +513,7 @@ require 'cassandra/protocol'
475
513
  require 'cassandra/auth'
476
514
  require 'cassandra/null_logger'
477
515
 
516
+ require 'cassandra/executors'
478
517
  require 'cassandra/future'
479
518
  require 'cassandra/cluster'
480
519
  require 'cassandra/driver'
@@ -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} instances
22
- # (or objects matching that interface). Its {#create_authenticator} will be
23
- # called once for each connection that requires authentication.
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.
24
24
  #
25
25
  # If the authentication requires keeping state, keep that in the
26
26
  # authenticator instances, not in the auth provider.
@@ -17,8 +17,7 @@
17
17
  #++
18
18
 
19
19
  module Cassandra
20
- # Cluster represents a cassandra cluster. It serves as a {Cassandra::Session}
21
- # factory and a collection of metadata.
20
+ # Cluster represents a cassandra cluster. It serves as a {Cassandra::Session session factory} factory and a collection of metadata.
22
21
  #
23
22
  # @see Cassandra::Cluster#connect Creating a new session
24
23
  # @see Cassandra::Cluster#each_host Getting all peers in the cluster
@@ -26,46 +25,11 @@ module Cassandra
26
25
  class Cluster
27
26
  extend Forwardable
28
27
 
29
- # @!method host(address)
30
- # Find a host by its address
31
- # @param address [IPAddr, String] ip address
32
- # @return [Cassandra::Host, nil] host or nil
33
- #
34
- # @!method has_host?(address)
35
- # Determine if a host by a given address exists
36
- # @param address [IPAddr, String] ip address
37
- # @return [Boolean] true or false
38
- def_delegators :@registry, :host, :has_host?
39
-
40
- # @!method keyspace(name)
41
- # Find a keyspace by name
42
- # @param name [String] keyspace name
43
- # @return [Cassandra::Keyspace, nil] keyspace or nil
44
- #
45
- # @!method has_keyspace?(name)
46
- # Determine if a keyspace by a given name exists
47
- # @param name [String] keyspace name
48
- # @return [Boolean] true or false
49
- def_delegators :@schema, :keyspace, :has_keyspace?
50
-
51
- # @!method name
52
- # Return cluster's name
53
- # @return [String] cluster's name
54
- #
55
- # @!method find_replicas(keyspace, statement)
56
- # Return replicas for a given statement and keyspace
57
- # @note an empty list is returned when statement/keyspace information is
58
- # not enough to determine replica list.
59
- # @param keyspace [String] keyspace name
60
- # @param statement [Cassandra::Statement] statement for which to find
61
- # replicas
62
- # @return [Array<Cassandra::Host>] a list of replicas
63
- def_delegators :@metadata, :name, :find_replicas
64
-
65
28
  # @private
66
- def initialize(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)
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)
67
30
  @logger = logger
68
31
  @io_reactor = io_reactor
32
+ @executor = executor
69
33
  @control_connection = control_connection
70
34
  @registry = cluster_registry
71
35
  @schema = cluster_schema
@@ -78,8 +42,26 @@ module Cassandra
78
42
  @address_resolver = address_resolution_policy
79
43
  @connector = connector
80
44
  @futures = futures_factory
45
+
46
+ @control_connection.on_close do |cause|
47
+ @load_balancing_policy.teardown(self) rescue nil
48
+ end
81
49
  end
82
50
 
51
+ # @!method name
52
+ # Return cluster's name
53
+ # @return [String] cluster's name
54
+ #
55
+ # @!method find_replicas(keyspace, statement)
56
+ # Return replicas for a given statement and keyspace
57
+ # @note an empty list is returned when statement/keyspace information is
58
+ # not enough to determine replica list.
59
+ # @param keyspace [String] keyspace name
60
+ # @param statement [Cassandra::Statement] statement for which to find
61
+ # replicas
62
+ # @return [Array<Cassandra::Host>] a list of replicas
63
+ def_delegators :@metadata, :name, :find_replicas
64
+
83
65
  # Register a cluster state listener. State listener will start receiving
84
66
  # notifications about topology and schema changes
85
67
  #
@@ -115,6 +97,17 @@ module Cassandra
115
97
  end
116
98
  alias :hosts :each_host
117
99
 
100
+ # @!method host(address)
101
+ # Find a host by its address
102
+ # @param address [IPAddr, String] ip address
103
+ # @return [Cassandra::Host, nil] host or nil
104
+ #
105
+ # @!method has_host?(address)
106
+ # Determine if a host by a given address exists
107
+ # @param address [IPAddr, String] ip address
108
+ # @return [Boolean] true or false
109
+ def_delegators :@registry, :host, :has_host?
110
+
118
111
  # Yield or enumerate each keyspace defined in this cluster
119
112
  # @overload each_keyspace
120
113
  # @yieldparam keyspace [Cassandra::Keyspace] current keyspace
@@ -128,6 +121,35 @@ module Cassandra
128
121
  end
129
122
  alias :keyspaces :each_keyspace
130
123
 
124
+ # @!method keyspace(name)
125
+ # Find a keyspace by name
126
+ # @param name [String] keyspace name
127
+ # @return [Cassandra::Keyspace, nil] keyspace or nil
128
+ #
129
+ # @!method has_keyspace?(name)
130
+ # Determine if a keyspace by a given name exists
131
+ # @param name [String] keyspace name
132
+ # @return [Boolean] true or false
133
+ def_delegators :@schema, :keyspace, :has_keyspace?
134
+
135
+ # @!method refresh_schema_async
136
+ # Trigger an asynchronous schema metadata refresh
137
+ # @return [Cassandra::Future<nil>] a future that will be fulfilled when
138
+ # schema metadata has been refreshed
139
+ def_delegator :@control_connection, :refresh_schema_async_maybe_retry, \
140
+ :refresh_schema_async
141
+
142
+ # Synchronously refresh schema metadata
143
+ #
144
+ # @return [nil] nothing
145
+ # @raise [Cassandra::Errors::ClientError] when cluster is disconnected
146
+ # @raise [Cassandra::Error] other unexpected errors
147
+ #
148
+ # @see Cassandra::Cluster#refresh_schema_async
149
+ def refresh_schema
150
+ refresh_schema_async.get
151
+ end
152
+
131
153
  # Asynchronously create a new session, optionally scoped to a keyspace
132
154
  #
133
155
  # @param keyspace [String] optional keyspace to scope session to
@@ -191,11 +213,12 @@ module Cassandra
191
213
 
192
214
  @control_connection.close_async.on_complete do |f|
193
215
  if f.resolved?
194
- @load_balancing_policy.teardown(self) rescue nil
195
216
  promise.fulfill(self)
196
217
  else
197
218
  f.on_failure {|e| promise.break(e)}
198
219
  end
220
+
221
+ @executor.shutdown
199
222
  end
200
223
 
201
224
  promise.future