cassandra-driver 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/README.md +23 -18
- data/lib/cassandra.rb +65 -26
- data/lib/cassandra/auth.rb +3 -3
- data/lib/cassandra/cluster.rb +63 -40
- data/lib/cassandra/cluster/client.rb +51 -24
- data/lib/cassandra/cluster/connection_pool.rb +6 -0
- data/lib/cassandra/cluster/control_connection.rb +155 -90
- data/lib/cassandra/cluster/options.rb +18 -11
- data/lib/cassandra/cluster/schema.rb +22 -1
- data/lib/cassandra/driver.rb +43 -9
- data/lib/cassandra/execution/options.rb +30 -3
- data/lib/cassandra/executors.rb +111 -0
- data/lib/cassandra/future.rb +88 -68
- data/lib/cassandra/keyspace.rb +7 -0
- data/lib/cassandra/load_balancing.rb +10 -0
- data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +3 -3
- data/lib/cassandra/load_balancing/policies/round_robin.rb +7 -5
- data/lib/cassandra/load_balancing/policies/token_aware.rb +28 -5
- data/lib/cassandra/load_balancing/policies/white_list.rb +1 -1
- data/lib/cassandra/protocol/cql_protocol_handler.rb +4 -1
- data/lib/cassandra/result.rb +30 -3
- data/lib/cassandra/session.rb +3 -0
- data/lib/cassandra/version.rb +1 -1
- metadata +3 -2
@@ -23,24 +23,31 @@ module Cassandra
|
|
23
23
|
attr_reader :credentials, :auth_provider, :compressor, :port,
|
24
24
|
:connect_timeout, :ssl, :connections_per_local_node,
|
25
25
|
:connections_per_remote_node, :heartbeat_interval,
|
26
|
-
:idle_timeout
|
26
|
+
:idle_timeout, :schema_refresh_delay, :schema_refresh_timeout
|
27
27
|
attr_accessor :protocol_version
|
28
28
|
|
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)
|
30
|
-
@protocol_version
|
31
|
-
@credentials
|
32
|
-
@auth_provider
|
33
|
-
@compressor
|
34
|
-
@port
|
35
|
-
@connect_timeout
|
36
|
-
@ssl
|
37
|
-
@heartbeat_interval
|
38
|
-
@idle_timeout
|
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, synchronize_schema, schema_refresh_delay, schema_refresh_timeout)
|
30
|
+
@protocol_version = protocol_version
|
31
|
+
@credentials = credentials
|
32
|
+
@auth_provider = auth_provider
|
33
|
+
@compressor = compressor
|
34
|
+
@port = port
|
35
|
+
@connect_timeout = connect_timeout
|
36
|
+
@ssl = ssl
|
37
|
+
@heartbeat_interval = heartbeat_interval
|
38
|
+
@idle_timeout = idle_timeout
|
39
|
+
@synchronize_schema = synchronize_schema
|
40
|
+
@schema_refresh_delay = schema_refresh_delay
|
41
|
+
@schema_refresh_timeout = schema_refresh_timeout
|
39
42
|
|
40
43
|
@connections_per_local_node = connections_per_local_node
|
41
44
|
@connections_per_remote_node = connections_per_remote_node
|
42
45
|
end
|
43
46
|
|
47
|
+
def synchronize_schema?
|
48
|
+
@synchronize_schema
|
49
|
+
end
|
50
|
+
|
44
51
|
def compression
|
45
52
|
@compressor && @compressor.algorithm
|
46
53
|
end
|
@@ -130,6 +130,9 @@ module Cassandra
|
|
130
130
|
|
131
131
|
return self unless keyspace
|
132
132
|
|
133
|
+
columns = columns.each_with_object(::Hash.new) do |row, index|
|
134
|
+
index[row['column_name']] = row
|
135
|
+
end
|
133
136
|
table = create_table(table, columns, host.release_version)
|
134
137
|
keyspace = keyspace.update_table(table)
|
135
138
|
|
@@ -139,7 +142,25 @@ module Cassandra
|
|
139
142
|
@keyspaces = keyspaces
|
140
143
|
end
|
141
144
|
|
142
|
-
|
145
|
+
keyspace_changed(keyspace)
|
146
|
+
|
147
|
+
self
|
148
|
+
end
|
149
|
+
|
150
|
+
def delete_table(keyspace_name, table_name)
|
151
|
+
keyspace = @keyspaces[keyspace_name]
|
152
|
+
|
153
|
+
return self unless keyspace
|
154
|
+
|
155
|
+
keyspace = keyspace.delete_table(table_name)
|
156
|
+
|
157
|
+
synchronize do
|
158
|
+
keyspaces = @keyspaces.dup
|
159
|
+
keyspaces[keyspace_name] = keyspace
|
160
|
+
@keyspaces = keyspaces
|
161
|
+
end
|
162
|
+
|
163
|
+
keyspace_changed(keyspace)
|
143
164
|
|
144
165
|
self
|
145
166
|
end
|
data/lib/cassandra/driver.rb
CHANGED
@@ -20,7 +20,7 @@ module Cassandra
|
|
20
20
|
# @private
|
21
21
|
class Driver
|
22
22
|
def self.let(name, &block)
|
23
|
-
define_method(name) { @instances[name]
|
23
|
+
define_method(name) { @instances.has_key?(name) ? @instances[name] : @instances[name] = instance_eval(&block) }
|
24
24
|
define_method(:"#{name}=") { |object| @instances[name] = object }
|
25
25
|
end
|
26
26
|
|
@@ -42,7 +42,9 @@ module Cassandra
|
|
42
42
|
no_replication_strategy
|
43
43
|
)
|
44
44
|
}
|
45
|
-
|
45
|
+
|
46
|
+
let(:executor) { Executors::ThreadPool.new(thread_pool_size) }
|
47
|
+
let(:futures_factory) { Future::Factory.new(executor) }
|
46
48
|
|
47
49
|
let(:schema_type_parser) { Cluster::Schema::TypeParser.new }
|
48
50
|
|
@@ -56,9 +58,9 @@ module Cassandra
|
|
56
58
|
|
57
59
|
let(:connector) { Cluster::Connector.new(logger, io_reactor, cluster_registry, connection_options, execution_options) }
|
58
60
|
|
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) }
|
61
|
+
let(:control_connection) { Cluster::ControlConnection.new(logger, io_reactor, cluster_registry, cluster_schema, cluster_metadata, load_balancing_policy, reconnection_policy, address_resolution_policy, connector, connection_options) }
|
60
62
|
|
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) }
|
63
|
+
let(:cluster) { Cluster.new(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) }
|
62
64
|
|
63
65
|
let(:execution_options) do
|
64
66
|
Execution::Options.new({
|
@@ -69,7 +71,24 @@ module Cassandra
|
|
69
71
|
})
|
70
72
|
end
|
71
73
|
|
72
|
-
let(:connection_options)
|
74
|
+
let(:connection_options) do
|
75
|
+
Cluster::Options.new(
|
76
|
+
protocol_version,
|
77
|
+
credentials,
|
78
|
+
auth_provider,
|
79
|
+
compressor,
|
80
|
+
port,
|
81
|
+
connect_timeout,
|
82
|
+
ssl,
|
83
|
+
connections_per_local_node,
|
84
|
+
connections_per_remote_node,
|
85
|
+
heartbeat_interval,
|
86
|
+
idle_timeout,
|
87
|
+
synchronize_schema,
|
88
|
+
schema_refresh_delay,
|
89
|
+
schema_refresh_timeout
|
90
|
+
)
|
91
|
+
end
|
73
92
|
|
74
93
|
let(:port) { 9042 }
|
75
94
|
let(:protocol_version) { 2 }
|
@@ -80,7 +99,7 @@ module Cassandra
|
|
80
99
|
let(:credentials) { nil }
|
81
100
|
let(:auth_provider) { nil }
|
82
101
|
let(:datacenter) { nil }
|
83
|
-
let(:load_balancing_policy) { LoadBalancing::Policies::TokenAware.new(LoadBalancing::Policies::DCAwareRoundRobin.new(datacenter, 0)) }
|
102
|
+
let(:load_balancing_policy) { LoadBalancing::Policies::TokenAware.new(LoadBalancing::Policies::DCAwareRoundRobin.new(datacenter, 0), shuffle_replicas) }
|
84
103
|
let(:reconnection_policy) { Reconnection::Policies::Exponential.new(0.5, 30, 2) }
|
85
104
|
let(:retry_policy) { Retry::Policies::Default.new }
|
86
105
|
let(:address_resolution_policy) { AddressResolution::Policies::None.new }
|
@@ -90,6 +109,11 @@ module Cassandra
|
|
90
109
|
let(:heartbeat_interval) { 30 }
|
91
110
|
let(:idle_timeout) { 60 }
|
92
111
|
let(:timeout) { 10 }
|
112
|
+
let(:synchronize_schema) { true }
|
113
|
+
let(:schema_refresh_delay) { 1 }
|
114
|
+
let(:schema_refresh_timeout) { 10 }
|
115
|
+
let(:thread_pool_size) { 4 }
|
116
|
+
let(:shuffle_replicas) { true }
|
93
117
|
|
94
118
|
let(:connections_per_local_node) { 2 }
|
95
119
|
let(:connections_per_remote_node) { 1 }
|
@@ -97,8 +121,7 @@ module Cassandra
|
|
97
121
|
let(:listeners) { [] }
|
98
122
|
|
99
123
|
def initialize(defaults = {})
|
100
|
-
@
|
101
|
-
@instances = {}
|
124
|
+
@instances = defaults
|
102
125
|
end
|
103
126
|
|
104
127
|
def connect(addresses)
|
@@ -113,7 +136,18 @@ module Cassandra
|
|
113
136
|
addresses.each {|address| cluster_registry.host_found(address)}
|
114
137
|
|
115
138
|
logger.info('Establishing control connection')
|
116
|
-
|
139
|
+
|
140
|
+
promise = futures_factory.promise
|
141
|
+
|
142
|
+
control_connection.connect_async.on_complete do |f|
|
143
|
+
if f.resolved?
|
144
|
+
promise.fulfill(cluster)
|
145
|
+
else
|
146
|
+
f.on_failure {|e| promise.break(e)}
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
promise.future
|
117
151
|
end
|
118
152
|
end
|
119
153
|
end
|
@@ -31,6 +31,20 @@ module Cassandra
|
|
31
31
|
# @return [Numeric] request timeout interval
|
32
32
|
attr_reader :timeout
|
33
33
|
|
34
|
+
# @return [String] paging state
|
35
|
+
#
|
36
|
+
# @note Although this feature exists to allow web applications to store
|
37
|
+
# paging state in an [HTTP cookie](http://en.wikipedia.org/wiki/HTTP_cookie), **it is not safe to
|
38
|
+
# expose without encrypting or otherwise securing it**. Paging state
|
39
|
+
# contains information internal to the Apache Cassandra cluster, such as
|
40
|
+
# partition key and data. Additionally, if a paging state is sent with CQL
|
41
|
+
# statement, different from the original, the behavior of Cassandra is
|
42
|
+
# undefined and will likely cause a server process of the coordinator of
|
43
|
+
# such request to abort.
|
44
|
+
#
|
45
|
+
# @see Cassandra::Result#paging_state
|
46
|
+
attr_reader :paging_state
|
47
|
+
|
34
48
|
# @private
|
35
49
|
def initialize(options)
|
36
50
|
consistency = options[:consistency]
|
@@ -38,6 +52,7 @@ module Cassandra
|
|
38
52
|
trace = options[:trace]
|
39
53
|
timeout = options[:timeout]
|
40
54
|
serial_consistency = options[:serial_consistency]
|
55
|
+
paging_state = options[:paging_state]
|
41
56
|
|
42
57
|
Util.assert_one_of(CONSISTENCIES, consistency) { ":consistency must be one of #{CONSISTENCIES.inspect}, #{consistency.inspect} given" }
|
43
58
|
|
@@ -46,7 +61,7 @@ module Cassandra
|
|
46
61
|
end
|
47
62
|
|
48
63
|
unless page_size.nil?
|
49
|
-
page_size =
|
64
|
+
page_size = Integer(page_size)
|
50
65
|
Util.assert(page_size > 0) { ":page_size must be a positive integer, #{page_size.inspect} given" }
|
51
66
|
end
|
52
67
|
|
@@ -55,11 +70,17 @@ module Cassandra
|
|
55
70
|
Util.assert(timeout > 0) { ":timeout must be greater than 0, #{timeout} given" }
|
56
71
|
end
|
57
72
|
|
73
|
+
unless paging_state.nil?
|
74
|
+
paging_state = String(paging_state)
|
75
|
+
Util.assert_not_empty(paging_state) { ":paging_state must not be empty" }
|
76
|
+
end
|
77
|
+
|
58
78
|
@consistency = consistency
|
59
79
|
@page_size = page_size
|
60
80
|
@trace = !!trace
|
61
81
|
@timeout = timeout
|
62
82
|
@serial_consistency = serial_consistency
|
83
|
+
@paging_state = paging_state
|
63
84
|
end
|
64
85
|
|
65
86
|
# @return [Boolean] whether request tracing was enabled
|
@@ -68,8 +89,14 @@ module Cassandra
|
|
68
89
|
end
|
69
90
|
|
70
91
|
# @private
|
71
|
-
def override(options)
|
72
|
-
|
92
|
+
def override(*options)
|
93
|
+
merged = options.unshift(to_h).inject do |base, opts|
|
94
|
+
next base unless opts
|
95
|
+
Util.assert_instance_of(::Hash, opts) { "options must be a Hash, #{options.inspect} given" }
|
96
|
+
base.merge!(opts)
|
97
|
+
end
|
98
|
+
|
99
|
+
Options.new(merged)
|
73
100
|
end
|
74
101
|
|
75
102
|
# @private
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
#--
|
4
|
+
# Copyright 2013-2014 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
|
+
# @private
|
21
|
+
module Executors
|
22
|
+
class ThreadPool
|
23
|
+
# @private
|
24
|
+
class Task
|
25
|
+
def initialize(*args, &block)
|
26
|
+
@args = args
|
27
|
+
@block = block
|
28
|
+
end
|
29
|
+
|
30
|
+
def run
|
31
|
+
@block.call(*@args)
|
32
|
+
rescue ::Exception
|
33
|
+
ensure
|
34
|
+
@args = @block = nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
include MonitorMixin
|
39
|
+
|
40
|
+
def initialize(size)
|
41
|
+
mon_initialize
|
42
|
+
|
43
|
+
@cond = new_cond
|
44
|
+
@tasks = ::Array.new
|
45
|
+
@waiting = 0
|
46
|
+
@pool = ::Array.new(size, &method(:spawn_thread))
|
47
|
+
@term = false
|
48
|
+
end
|
49
|
+
|
50
|
+
def execute(*args, &block)
|
51
|
+
synchronize do
|
52
|
+
@tasks << Task.new(*args, &block)
|
53
|
+
@cond.signal if @waiting > 0
|
54
|
+
end
|
55
|
+
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
|
59
|
+
def shutdown
|
60
|
+
execute do
|
61
|
+
synchronize do
|
62
|
+
@term = true
|
63
|
+
@cond.broadcast if @waiting > 0
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
nil
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def spawn_thread(i)
|
73
|
+
Thread.new(&method(:run))
|
74
|
+
end
|
75
|
+
|
76
|
+
def run
|
77
|
+
Thread.current.abort_on_exception = true
|
78
|
+
|
79
|
+
loop do
|
80
|
+
tasks = nil
|
81
|
+
|
82
|
+
synchronize do
|
83
|
+
@waiting += 1
|
84
|
+
@cond.wait while !@term && @tasks.empty?
|
85
|
+
@waiting -= 1
|
86
|
+
|
87
|
+
return if @tasks.empty?
|
88
|
+
|
89
|
+
tasks = @tasks
|
90
|
+
@tasks = ::Array.new
|
91
|
+
end
|
92
|
+
|
93
|
+
tasks.each(&:run).clear
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
class SameThread
|
99
|
+
def execute(*args, &block)
|
100
|
+
yield(*args)
|
101
|
+
nil
|
102
|
+
rescue ::Exception
|
103
|
+
nil
|
104
|
+
end
|
105
|
+
|
106
|
+
def shutdown
|
107
|
+
nil
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
data/lib/cassandra/future.rb
CHANGED
@@ -48,8 +48,6 @@ module Cassandra
|
|
48
48
|
def initialize(error)
|
49
49
|
raise ::ArgumentError, "error must be an exception, #{error.inspect} given" unless error.is_a?(::Exception)
|
50
50
|
|
51
|
-
error.set_backtrace(caller) unless error.backtrace
|
52
|
-
|
53
51
|
@error = error
|
54
52
|
end
|
55
53
|
|
@@ -163,18 +161,64 @@ module Cassandra
|
|
163
161
|
end
|
164
162
|
end
|
165
163
|
|
164
|
+
# @private
|
165
|
+
class Factory
|
166
|
+
def initialize(executor)
|
167
|
+
@executor = executor
|
168
|
+
end
|
169
|
+
|
170
|
+
def value(value)
|
171
|
+
Value.new(value)
|
172
|
+
end
|
173
|
+
|
174
|
+
def error(error)
|
175
|
+
Error.new(error)
|
176
|
+
end
|
177
|
+
|
178
|
+
def promise
|
179
|
+
Promise.new(@executor)
|
180
|
+
end
|
181
|
+
|
182
|
+
def all(*futures)
|
183
|
+
futures = Array(futures.first) if futures.one?
|
184
|
+
monitor = Monitor.new
|
185
|
+
promise = Promise.new(@executor)
|
186
|
+
remaining = futures.length
|
187
|
+
values = Array.new(remaining)
|
188
|
+
|
189
|
+
futures.each_with_index do |future, i|
|
190
|
+
future.on_complete do |v, e|
|
191
|
+
if e
|
192
|
+
promise.break(e)
|
193
|
+
else
|
194
|
+
done = false
|
195
|
+
monitor.synchronize do
|
196
|
+
remaining -= 1
|
197
|
+
done = (remaining == 0)
|
198
|
+
values[i] = v
|
199
|
+
end
|
200
|
+
promise.fulfill(values) if done
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
# @private
|
208
|
+
@@factory = Factory.new(Executors::SameThread.new)
|
209
|
+
|
166
210
|
# Returns a future resolved to a given value
|
167
211
|
# @param value [Object] value for the future
|
168
212
|
# @return [Cassandra::Future<Object>] a future value
|
169
213
|
def self.value(value)
|
170
|
-
|
214
|
+
@@factory.value(value)
|
171
215
|
end
|
172
216
|
|
173
217
|
# Returns a future resolved to a given error
|
174
218
|
# @param error [Exception] error for the future
|
175
219
|
# @return [Cassandra::Future<Exception>] a future error
|
176
220
|
def self.error(error)
|
177
|
-
|
221
|
+
@@factory.error(error)
|
178
222
|
end
|
179
223
|
|
180
224
|
# Returns a future that resolves with values of all futures
|
@@ -186,35 +230,7 @@ module Cassandra
|
|
186
230
|
# combine
|
187
231
|
# @return [Cassandra::Future<Array<Object>>] a combined future
|
188
232
|
def self.all(*futures)
|
189
|
-
|
190
|
-
monitor = Monitor.new
|
191
|
-
promise = Promise.new
|
192
|
-
remaining = futures.length
|
193
|
-
values = Array.new(remaining)
|
194
|
-
|
195
|
-
futures.each_with_index do |future, i|
|
196
|
-
future.on_complete do |v, e|
|
197
|
-
if e
|
198
|
-
promise.break(e)
|
199
|
-
else
|
200
|
-
done = false
|
201
|
-
monitor.synchronize do
|
202
|
-
remaining -= 1
|
203
|
-
done = (remaining == 0)
|
204
|
-
values[i] = v
|
205
|
-
end
|
206
|
-
promise.fulfill(values) if done
|
207
|
-
end
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
promise.future
|
212
|
-
end
|
213
|
-
|
214
|
-
# @private
|
215
|
-
# Returns a new promise instance
|
216
|
-
def self.promise
|
217
|
-
Promise.new
|
233
|
+
@@factory.all(*futures)
|
218
234
|
end
|
219
235
|
|
220
236
|
# @private
|
@@ -222,24 +238,6 @@ module Cassandra
|
|
222
238
|
@signal = signal
|
223
239
|
end
|
224
240
|
|
225
|
-
# Returns future value or raises future error
|
226
|
-
# @note This method blocks until a future is resolved
|
227
|
-
# @raise [Exception] error used to resolve this future if any
|
228
|
-
# @return [Object] value used to resolve this future if any
|
229
|
-
def get
|
230
|
-
@signal.get
|
231
|
-
end
|
232
|
-
|
233
|
-
# Block until the future has been resolved
|
234
|
-
# @note This method blocks until a future is resolved
|
235
|
-
# @note This method won't raise any errors or return anything but the
|
236
|
-
# future itself
|
237
|
-
# @return [self]
|
238
|
-
def join
|
239
|
-
@signal.join
|
240
|
-
self
|
241
|
-
end
|
242
|
-
|
243
241
|
# Run block when future resolves to a value
|
244
242
|
# @note The block can be called synchronously from current thread if the
|
245
243
|
# future has already been resolved, or, asynchronously, from background
|
@@ -350,6 +348,25 @@ module Cassandra
|
|
350
348
|
raise ::ArgumentError, "no block given" unless block_given?
|
351
349
|
@signal.fallback(&block)
|
352
350
|
end
|
351
|
+
|
352
|
+
# Returns future value or raises future error
|
353
|
+
# @note This method blocks until a future is resolved
|
354
|
+
# @raise [Exception] error used to resolve this future if any
|
355
|
+
# @return [Object] value used to resolve this future if any
|
356
|
+
def get
|
357
|
+
@signal.get
|
358
|
+
|
359
|
+
end
|
360
|
+
|
361
|
+
# Block until the future has been resolved
|
362
|
+
# @note This method blocks until a future is resolved
|
363
|
+
# @note This method won't raise any errors or return anything but the
|
364
|
+
# future itself
|
365
|
+
# @return [self]
|
366
|
+
def join
|
367
|
+
@signal.join
|
368
|
+
self
|
369
|
+
end
|
353
370
|
end
|
354
371
|
|
355
372
|
# @private
|
@@ -457,10 +474,11 @@ module Cassandra
|
|
457
474
|
|
458
475
|
include MonitorMixin
|
459
476
|
|
460
|
-
def initialize
|
477
|
+
def initialize(executor)
|
461
478
|
mon_initialize
|
462
479
|
|
463
480
|
@cond = new_cond
|
481
|
+
@executor = executor
|
464
482
|
@state = :pending
|
465
483
|
@waiting = 0
|
466
484
|
@error = nil
|
@@ -473,8 +491,6 @@ module Cassandra
|
|
473
491
|
raise ::ArgumentError, "error must be an exception, #{error.inspect} given"
|
474
492
|
end
|
475
493
|
|
476
|
-
error.set_backtrace(caller) unless error.backtrace
|
477
|
-
|
478
494
|
return unless @state == :pending
|
479
495
|
|
480
496
|
listeners = nil
|
@@ -488,12 +504,14 @@ module Cassandra
|
|
488
504
|
listeners, @listeners = @listeners, nil
|
489
505
|
end
|
490
506
|
|
491
|
-
|
492
|
-
|
493
|
-
|
507
|
+
@executor.execute do
|
508
|
+
listeners.each do |listener|
|
509
|
+
listener.failure(error) rescue nil
|
510
|
+
end
|
494
511
|
|
495
|
-
|
496
|
-
|
512
|
+
synchronize do
|
513
|
+
@cond.broadcast if @waiting > 0
|
514
|
+
end
|
497
515
|
end
|
498
516
|
|
499
517
|
self
|
@@ -513,12 +531,14 @@ module Cassandra
|
|
513
531
|
listeners, @listeners = @listeners, nil
|
514
532
|
end
|
515
533
|
|
516
|
-
|
517
|
-
|
518
|
-
|
534
|
+
@executor.execute do
|
535
|
+
listeners.each do |listener|
|
536
|
+
listener.success(value) rescue nil
|
537
|
+
end
|
519
538
|
|
520
|
-
|
521
|
-
|
539
|
+
synchronize do
|
540
|
+
@cond.broadcast if @waiting > 0
|
541
|
+
end
|
522
542
|
end
|
523
543
|
|
524
544
|
self
|
@@ -612,7 +632,7 @@ module Cassandra
|
|
612
632
|
if @state == :pending
|
613
633
|
synchronize do
|
614
634
|
if @state == :pending
|
615
|
-
promise = Promise.new
|
635
|
+
promise = Promise.new(@executor)
|
616
636
|
listener = Listeners::Then.new(promise, &block)
|
617
637
|
@listeners << listener
|
618
638
|
return promise.future
|
@@ -635,7 +655,7 @@ module Cassandra
|
|
635
655
|
if @state == :pending
|
636
656
|
synchronize do
|
637
657
|
if @state == :pending
|
638
|
-
promise = Promise.new
|
658
|
+
promise = Promise.new(@executor)
|
639
659
|
listener = Listeners::Fallback.new(promise, &block)
|
640
660
|
@listeners << listener
|
641
661
|
return promise.future
|
@@ -657,8 +677,8 @@ module Cassandra
|
|
657
677
|
|
658
678
|
attr_reader :future
|
659
679
|
|
660
|
-
def initialize
|
661
|
-
@signal = Signal.new
|
680
|
+
def initialize(executor)
|
681
|
+
@signal = Signal.new(executor)
|
662
682
|
@future = Future.new(@signal)
|
663
683
|
end
|
664
684
|
|