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 +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
|
|