cassandra-driver 2.1.7 → 3.0.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/README.md +31 -53
- data/lib/cassandra.rb +22 -3
- data/lib/cassandra/aggregate.rb +109 -0
- data/lib/cassandra/argument.rb +51 -0
- data/lib/cassandra/auth/providers/password.rb +7 -4
- data/lib/cassandra/cluster.rb +14 -3
- data/lib/cassandra/cluster/client.rb +56 -34
- data/lib/cassandra/cluster/connector.rb +6 -6
- data/lib/cassandra/cluster/control_connection.rb +204 -251
- data/lib/cassandra/cluster/metadata.rb +2 -0
- data/lib/cassandra/cluster/schema.rb +131 -209
- data/lib/cassandra/cluster/schema/cql_type_parser.rb +104 -0
- data/lib/cassandra/cluster/schema/fetchers.rb +1174 -0
- data/lib/cassandra/cluster/schema/{type_parser.rb → fqcn_type_parser.rb} +7 -3
- data/lib/cassandra/column.rb +2 -2
- data/lib/cassandra/driver.rb +27 -9
- data/lib/cassandra/errors.rb +179 -25
- data/lib/cassandra/execution/info.rb +8 -1
- data/lib/cassandra/execution/options.rb +34 -0
- data/lib/cassandra/execution/trace.rb +42 -10
- data/lib/cassandra/function.rb +150 -0
- data/lib/cassandra/future.rb +66 -35
- data/lib/cassandra/host.rb +7 -4
- data/lib/cassandra/keyspace.rb +112 -13
- data/lib/cassandra/load_balancing.rb +1 -1
- data/lib/cassandra/protocol.rb +9 -3
- data/lib/cassandra/protocol/coder.rb +434 -155
- data/lib/cassandra/protocol/cql_byte_buffer.rb +43 -0
- data/lib/cassandra/protocol/cql_protocol_handler.rb +4 -1
- data/lib/cassandra/protocol/request.rb +4 -0
- data/lib/cassandra/protocol/requests/auth_response_request.rb +5 -1
- data/lib/cassandra/protocol/requests/batch_request.rb +7 -2
- data/lib/cassandra/protocol/requests/credentials_request.rb +5 -1
- data/lib/cassandra/protocol/requests/execute_request.rb +16 -10
- data/lib/cassandra/protocol/requests/prepare_request.rb +12 -3
- data/lib/cassandra/protocol/requests/query_request.rb +20 -11
- data/lib/cassandra/protocol/responses/already_exists_error_response.rb +4 -4
- data/lib/cassandra/protocol/responses/error_response.rb +14 -14
- data/lib/cassandra/protocol/responses/function_failure_error_response.rb +41 -0
- data/lib/cassandra/protocol/responses/prepared_result_response.rb +12 -9
- data/lib/cassandra/protocol/responses/raw_rows_result_response.rb +5 -3
- data/lib/cassandra/protocol/responses/read_failure_error_response.rb +43 -0
- data/lib/cassandra/protocol/responses/read_timeout_error_response.rb +4 -4
- data/lib/cassandra/protocol/responses/ready_response.rb +5 -1
- data/lib/cassandra/protocol/responses/result_response.rb +3 -3
- data/lib/cassandra/protocol/responses/rows_result_response.rb +2 -2
- data/lib/cassandra/protocol/responses/schema_change_event_response.rb +25 -24
- data/lib/cassandra/protocol/responses/schema_change_result_response.rb +20 -23
- data/lib/cassandra/protocol/responses/set_keyspace_result_response.rb +2 -2
- data/lib/cassandra/protocol/responses/unavailable_error_response.rb +4 -4
- data/lib/cassandra/protocol/responses/unprepared_error_response.rb +4 -4
- data/lib/cassandra/protocol/responses/write_failure_error_response.rb +45 -0
- data/lib/cassandra/protocol/responses/write_timeout_error_response.rb +4 -4
- data/lib/cassandra/protocol/v1.rb +38 -13
- data/lib/cassandra/protocol/v3.rb +34 -29
- data/lib/cassandra/protocol/v4.rb +334 -0
- data/lib/cassandra/result.rb +10 -9
- data/lib/cassandra/retry.rb +17 -3
- data/lib/cassandra/retry/policies/default.rb +9 -3
- data/lib/cassandra/session.rb +15 -7
- data/lib/cassandra/statement.rb +5 -0
- data/lib/cassandra/statements/batch.rb +36 -12
- data/lib/cassandra/statements/bound.rb +2 -1
- data/lib/cassandra/statements/prepared.rb +106 -35
- data/lib/cassandra/statements/simple.rb +4 -2
- data/lib/cassandra/table.rb +70 -105
- data/lib/cassandra/time.rb +98 -0
- data/lib/cassandra/time_uuid.rb +1 -1
- data/lib/cassandra/tuple.rb +7 -0
- data/lib/cassandra/types.rb +472 -272
- data/lib/cassandra/udt.rb +10 -0
- data/lib/cassandra/util.rb +32 -1
- data/lib/cassandra/uuid.rb +6 -1
- data/lib/cassandra/uuid/generator.rb +7 -7
- data/lib/cassandra/version.rb +1 -1
- data/lib/datastax/cassandra.rb +5 -2
- metadata +16 -6
@@ -49,6 +49,19 @@ module Cassandra
|
|
49
49
|
# @see Cassandra::Result#paging_state
|
50
50
|
attr_reader :paging_state
|
51
51
|
|
52
|
+
# @return [nil, Hash<String, String>] custom outgoing payload, a map of
|
53
|
+
# string and byte buffers.
|
54
|
+
#
|
55
|
+
# @see https://github.com/apache/cassandra/blob/33f1edcce97779c971d4f78712a9a8bf014ffbbc/doc/native_protocol_v4.spec#L127-L133 Description of custom payload in Cassandra native protocol v4.
|
56
|
+
# @see https://datastax.github.io/java-driver/features/custom_payloads/#enabling-custom-payloads-on-c-nodes Enabling custom payloads on Cassandra nodes.
|
57
|
+
#
|
58
|
+
# @example Sending a custom payload
|
59
|
+
# result = session.execute(payload: {
|
60
|
+
# 'some key' => Cassandra::Protocol::CqlByteBuffer.new
|
61
|
+
# .append_string('some value')
|
62
|
+
# })
|
63
|
+
attr_reader :payload
|
64
|
+
|
52
65
|
# @private
|
53
66
|
def initialize(options)
|
54
67
|
consistency = options[:consistency]
|
@@ -59,6 +72,8 @@ module Cassandra
|
|
59
72
|
paging_state = options[:paging_state]
|
60
73
|
arguments = options[:arguments]
|
61
74
|
type_hints = options[:type_hints]
|
75
|
+
idempotent = options[:idempotent]
|
76
|
+
payload = options[:payload]
|
62
77
|
|
63
78
|
Util.assert_one_of(CONSISTENCIES, consistency) { ":consistency must be one of #{CONSISTENCIES.inspect}, #{consistency.inspect} given" }
|
64
79
|
|
@@ -94,6 +109,17 @@ module Cassandra
|
|
94
109
|
Util.assert_instance_of_one_of([::Array, ::Hash], type_hints) { ":type_hints must be an Array or a Hash, #{type_hints.inspect} given" }
|
95
110
|
end
|
96
111
|
|
112
|
+
unless payload.nil?
|
113
|
+
Util.assert_instance_of(::Hash, payload) { ":payload must be a Hash" }
|
114
|
+
Util.assert_not_empty(payload) { ":payload must not be empty" }
|
115
|
+
Util.assert(payload.size <= 65535) { ":payload cannot contain more than 65535 key/value pairs" }
|
116
|
+
|
117
|
+
payload = payload.each_with_object(::Hash.new) do |(key, value), payload|
|
118
|
+
payload[String(key)] = String(value)
|
119
|
+
end
|
120
|
+
payload.freeze
|
121
|
+
end
|
122
|
+
|
97
123
|
@consistency = consistency
|
98
124
|
@page_size = page_size
|
99
125
|
@trace = !!trace
|
@@ -102,6 +128,8 @@ module Cassandra
|
|
102
128
|
@paging_state = paging_state
|
103
129
|
@arguments = arguments
|
104
130
|
@type_hints = type_hints
|
131
|
+
@idempotent = !!idempotent
|
132
|
+
@payload = payload
|
105
133
|
end
|
106
134
|
|
107
135
|
# @return [Boolean] whether request tracing was enabled
|
@@ -109,6 +137,12 @@ module Cassandra
|
|
109
137
|
@trace
|
110
138
|
end
|
111
139
|
|
140
|
+
# @return [Boolean] whether statement can be retried on timeout
|
141
|
+
def idempotent?
|
142
|
+
@idempotent
|
143
|
+
end
|
144
|
+
|
145
|
+
# @private
|
112
146
|
def eql?(other)
|
113
147
|
other.is_a?(Options) &&
|
114
148
|
other.consistency == @consistency &&
|
@@ -39,6 +39,7 @@ module Cassandra
|
|
39
39
|
@thread = thread
|
40
40
|
end
|
41
41
|
|
42
|
+
# @private
|
42
43
|
def ==(other)
|
43
44
|
other == @id
|
44
45
|
end
|
@@ -53,41 +54,61 @@ module Cassandra
|
|
53
54
|
|
54
55
|
# @private
|
55
56
|
def initialize(id, client)
|
56
|
-
@id
|
57
|
-
@client
|
57
|
+
@id = id
|
58
|
+
@client = client
|
59
|
+
@coordinator = nil
|
60
|
+
@duration = nil
|
61
|
+
@parameters = nil
|
62
|
+
@request = nil
|
63
|
+
@started_at = nil
|
64
|
+
@events = nil
|
65
|
+
@client_ip = nil
|
66
|
+
@loaded = false
|
67
|
+
@loaded_events = false
|
58
68
|
|
59
69
|
mon_initialize
|
60
70
|
end
|
61
71
|
|
62
|
-
# Returns the ip of coordinator node. Typically the same as
|
72
|
+
# Returns the ip of coordinator node. Typically the same as
|
73
|
+
# {Cassandra::Execution::Info#hosts}`.last`
|
63
74
|
#
|
64
75
|
# @return [IPAddr] ip of the coordinator node
|
65
76
|
def coordinator
|
66
|
-
load unless @
|
77
|
+
load unless @loaded
|
67
78
|
|
68
79
|
@coordinator
|
69
80
|
end
|
70
81
|
|
82
|
+
# Returns the ip of the client node, the node that ran the driver
|
83
|
+
# instance that started tracing.
|
84
|
+
#
|
85
|
+
# @return [IPAddr, nil] ip of the client node running the driver
|
86
|
+
def client
|
87
|
+
load unless @loaded
|
88
|
+
|
89
|
+
@client_ip
|
90
|
+
end
|
91
|
+
|
71
92
|
def duration
|
72
|
-
load unless @
|
93
|
+
load unless @loaded
|
73
94
|
|
74
95
|
@duration
|
75
96
|
end
|
76
97
|
|
77
98
|
def parameters
|
78
|
-
load unless @
|
99
|
+
load unless @loaded
|
79
100
|
|
80
101
|
@parameters
|
81
102
|
end
|
82
103
|
|
83
104
|
def request
|
84
|
-
load unless @
|
105
|
+
load unless @loaded
|
85
106
|
|
86
107
|
@request
|
87
108
|
end
|
88
109
|
|
89
110
|
def started_at
|
90
|
-
load unless @
|
111
|
+
load unless @loaded
|
91
112
|
|
92
113
|
@started_at
|
93
114
|
end
|
@@ -96,11 +117,12 @@ module Cassandra
|
|
96
117
|
#
|
97
118
|
# @return [Array<Cassandra::Execution::Trace::Event>] events
|
98
119
|
def events
|
99
|
-
load_events unless @
|
120
|
+
load_events unless @loaded_events
|
100
121
|
|
101
122
|
@events
|
102
123
|
end
|
103
124
|
|
125
|
+
# @private
|
104
126
|
def inspect
|
105
127
|
"#<#{self.class.name}:0x#{self.object_id.to_s(16)} @id=#{@id.inspect}>"
|
106
128
|
end
|
@@ -117,7 +139,16 @@ module Cassandra
|
|
117
139
|
synchronize do
|
118
140
|
return if @loaded
|
119
141
|
|
120
|
-
|
142
|
+
attempt = 1
|
143
|
+
data = @client.query(Statements::Simple.new(SELECT_SESSION % @id), VOID_OPTIONS).get.first
|
144
|
+
|
145
|
+
while data.nil? && attempt <= 5
|
146
|
+
sleep(attempt * 0.4)
|
147
|
+
data = @client.query(Statements::Simple.new(SELECT_SESSION % @id), VOID_OPTIONS).get.first
|
148
|
+
break if data
|
149
|
+
attempt += 1
|
150
|
+
end
|
151
|
+
|
121
152
|
raise ::RuntimeError, "unable to load trace #{@id}" if data.nil?
|
122
153
|
|
123
154
|
@coordinator = data['coordinator']
|
@@ -125,6 +156,7 @@ module Cassandra
|
|
125
156
|
@parameters = data['parameters']
|
126
157
|
@request = data['request']
|
127
158
|
@started_at = data['started_at']
|
159
|
+
@client_ip = data['client']
|
128
160
|
@loaded = true
|
129
161
|
end
|
130
162
|
|
@@ -0,0 +1,150 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
#--
|
4
|
+
# Copyright 2013-2015 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
|
+
# Represents a cassandra user defined function
|
21
|
+
# @see Cassandra::Keyspace#each_function
|
22
|
+
# @see Cassandra::Keyspace#function
|
23
|
+
# @see Cassandra::Keyspace#has_function?
|
24
|
+
class Function
|
25
|
+
# @private
|
26
|
+
attr_reader :keyspace
|
27
|
+
# @return [String] function name
|
28
|
+
attr_reader :name
|
29
|
+
# @return [String] function language
|
30
|
+
attr_reader :language
|
31
|
+
# @return [Cassandra::Type] function return type
|
32
|
+
attr_reader :type
|
33
|
+
# @return [String] function body
|
34
|
+
attr_reader :body
|
35
|
+
|
36
|
+
# @private
|
37
|
+
def initialize(keyspace, name, language, type, arguments, body, called_on_null)
|
38
|
+
@keyspace = keyspace
|
39
|
+
@name = name
|
40
|
+
@language = language
|
41
|
+
@type = type
|
42
|
+
@arguments = arguments
|
43
|
+
@body = body
|
44
|
+
@called_on_null = called_on_null
|
45
|
+
|
46
|
+
# Build up an arguments hash keyed on arg-name.
|
47
|
+
@arguments_hash = @arguments.each_with_object({}) do |arg, h|
|
48
|
+
h[arg.name] = arg
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# @return [Boolean] whether this function will be called on null input
|
53
|
+
def called_on_null?
|
54
|
+
@called_on_null
|
55
|
+
end
|
56
|
+
|
57
|
+
# @param name [String] argument name
|
58
|
+
# @return [Boolean] whether this function has a given argument
|
59
|
+
def has_argument?(name)
|
60
|
+
@arguments_hash.has_key?(name)
|
61
|
+
end
|
62
|
+
|
63
|
+
# @param name [String] argument name
|
64
|
+
# @return [Cassandra::Argument, nil] an argument or nil
|
65
|
+
def argument(name)
|
66
|
+
@arguments_hash[name]
|
67
|
+
end
|
68
|
+
|
69
|
+
# Yield or enumerate each argument defined in this function
|
70
|
+
# @overload each_argument
|
71
|
+
# @yieldparam argument [Cassandra::Argument] current argument
|
72
|
+
# @return [Cassandra::Table] self
|
73
|
+
# @overload each_argument
|
74
|
+
# @return [Array<Cassandra::Argument>] a list of arguments
|
75
|
+
def each_argument(&block)
|
76
|
+
if block_given?
|
77
|
+
@arguments.each(&block)
|
78
|
+
self
|
79
|
+
else
|
80
|
+
# We return a dup of the arguments so that the caller can manipulate
|
81
|
+
# the array however they want without affecting the source.
|
82
|
+
@arguments.dup
|
83
|
+
end
|
84
|
+
end
|
85
|
+
alias :arguments :each_argument
|
86
|
+
|
87
|
+
# Get the list of argument types for this function.
|
88
|
+
# @return [Array<Cassandra::Type>] a list of argument types.
|
89
|
+
def argument_types
|
90
|
+
@arguments.map { |argument| argument.type }
|
91
|
+
end
|
92
|
+
|
93
|
+
# @private
|
94
|
+
def eql?(other)
|
95
|
+
other.is_a?(Function) && \
|
96
|
+
@keyspace == other.keyspace && \
|
97
|
+
@name == other.name && \
|
98
|
+
@language == other.language && \
|
99
|
+
@type == other.type && \
|
100
|
+
@arguments == other.arguments && \
|
101
|
+
@body == other.body && \
|
102
|
+
@called_on_null == other.called_on_null?
|
103
|
+
end
|
104
|
+
alias :== :eql?
|
105
|
+
|
106
|
+
# @private
|
107
|
+
def hash
|
108
|
+
@hash ||= begin
|
109
|
+
h = 17
|
110
|
+
h = 31 * h + @keyspace.hash
|
111
|
+
h = 31 * h + @name.hash
|
112
|
+
h = 31 * h + @language.hash
|
113
|
+
h = 31 * h + @type.hash
|
114
|
+
h = 31 * h + @arguments.hash
|
115
|
+
h = 31 * h + @body.hash
|
116
|
+
h = 31 * h + @called_on_null.hash
|
117
|
+
h
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# @private
|
122
|
+
def inspect
|
123
|
+
"#<Cassandra::Function:0x#{self.object_id.to_s(16)} @keyspace=#{@keyspace.inspect}, @name=#{@name.inspect}, @language=#{@language.inspect}, @type=#{@type.inspect}, @arguments=#{@arguments.inspect} @body=#{@body.inspect}>"
|
124
|
+
end
|
125
|
+
|
126
|
+
# @return [String] a cql representation of this function
|
127
|
+
def to_cql
|
128
|
+
cql = "CREATE FUNCTION #{Util.escape_name(@keyspace)}.#{Util.escape_name(@name)}("
|
129
|
+
first = true
|
130
|
+
@arguments.each do |argument|
|
131
|
+
if first
|
132
|
+
first = false
|
133
|
+
else
|
134
|
+
cql << ', '
|
135
|
+
end
|
136
|
+
cql << "#{argument.name} #{argument.type}"
|
137
|
+
end
|
138
|
+
cql << ")"
|
139
|
+
if @called_on_null
|
140
|
+
cql << "\n CALLED ON NULL INPUT"
|
141
|
+
else
|
142
|
+
cql << "\n RETURNS NULL ON NULL INPUT"
|
143
|
+
end
|
144
|
+
cql << "\n RETURNS #{@type}"
|
145
|
+
cql << "\n LANGUAGE #{@language}"
|
146
|
+
cql << "\n AS $$#{@body}$$"
|
147
|
+
cql << ";"
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
data/lib/cassandra/future.rb
CHANGED
@@ -51,10 +51,12 @@ module Cassandra
|
|
51
51
|
@error = error
|
52
52
|
end
|
53
53
|
|
54
|
-
def get
|
54
|
+
def get(timeout = nil)
|
55
55
|
raise(@error, @error.message, @error.backtrace)
|
56
56
|
end
|
57
57
|
|
58
|
+
alias :join :get
|
59
|
+
|
58
60
|
def on_success
|
59
61
|
raise ::ArgumentError, "no block given" unless block_given?
|
60
62
|
self
|
@@ -81,10 +83,6 @@ module Cassandra
|
|
81
83
|
self
|
82
84
|
end
|
83
85
|
|
84
|
-
def join
|
85
|
-
self
|
86
|
-
end
|
87
|
-
|
88
86
|
def then
|
89
87
|
raise ::ArgumentError, "no block given" unless block_given?
|
90
88
|
self
|
@@ -109,10 +107,12 @@ module Cassandra
|
|
109
107
|
@value = value
|
110
108
|
end
|
111
109
|
|
112
|
-
def get
|
110
|
+
def get(timeout = nil)
|
113
111
|
@value
|
114
112
|
end
|
115
113
|
|
114
|
+
alias :join :get
|
115
|
+
|
116
116
|
def on_success
|
117
117
|
raise ::ArgumentError, "no block given" unless block_given?
|
118
118
|
yield(@value) rescue nil
|
@@ -356,23 +356,23 @@ module Cassandra
|
|
356
356
|
end
|
357
357
|
|
358
358
|
# Returns future value or raises future error
|
359
|
-
#
|
360
|
-
# @
|
361
|
-
#
|
362
|
-
|
363
|
-
|
364
|
-
|
359
|
+
#
|
360
|
+
# @note This method blocks until a future is resolved or a times out
|
361
|
+
#
|
362
|
+
# @param timeout [nil, Numeric] a maximum number of seconds to block
|
363
|
+
# current thread for while waiting for this future to resolve. Will
|
364
|
+
# wait indefinitely if passed `nil`.
|
365
|
+
#
|
366
|
+
# @raise [Errors::TimeoutError] raised when wait time exceeds the timeout
|
367
|
+
# @raise [Exception] raises when the future has been resolved with an
|
368
|
+
# error. The original exception will be raised.
|
369
|
+
#
|
370
|
+
# @return [Object] the value that the future has been resolved with
|
371
|
+
def get(timeout = nil)
|
372
|
+
@signal.get(timeout)
|
365
373
|
end
|
366
374
|
|
367
|
-
|
368
|
-
# @note This method blocks until a future is resolved
|
369
|
-
# @note This method won't raise any errors or return anything but the
|
370
|
-
# future itself
|
371
|
-
# @return [self]
|
372
|
-
def join
|
373
|
-
@signal.join
|
374
|
-
self
|
375
|
-
end
|
375
|
+
alias :join :get
|
376
376
|
end
|
377
377
|
|
378
378
|
# @private
|
@@ -550,28 +550,59 @@ module Cassandra
|
|
550
550
|
self
|
551
551
|
end
|
552
552
|
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
553
|
+
# @param timeout [nil, Numeric] a maximum number of seconds to block
|
554
|
+
# current thread for while waiting for this future to resolve. Will
|
555
|
+
# wait indefinitely if passed `nil`.
|
556
|
+
#
|
557
|
+
# @raise [ArgumentError] raised when a negative timeout is given
|
558
|
+
# @raise [Errors::TimeoutError] raised when wait time exceeds the timeout
|
559
|
+
# @raise [Exception] raises when the future has been resolved with an
|
560
|
+
# error. The original exception will be raised.
|
561
|
+
#
|
562
|
+
# @return [Object] the value that the future has been resolved with
|
563
|
+
def get(timeout = nil)
|
564
|
+
timeout = timeout && Float(timeout)
|
565
|
+
|
566
|
+
if timeout
|
567
|
+
raise ::ArgumentError, "timeout cannot be negative, #{timeout.inspect} given" if timeout < 0
|
568
|
+
|
569
|
+
start = ::Time.now
|
570
|
+
now = start
|
571
|
+
deadline = start + timeout
|
562
572
|
end
|
563
573
|
|
564
|
-
|
565
|
-
|
574
|
+
if @state == :pending
|
575
|
+
synchronize do
|
576
|
+
if @state == :pending
|
577
|
+
@waiting += 1
|
578
|
+
while @state == :pending
|
579
|
+
if deadline
|
580
|
+
@cond.wait(deadline - now)
|
581
|
+
now = ::Time.now
|
582
|
+
break if now >= deadline
|
583
|
+
else
|
584
|
+
@cond.wait
|
585
|
+
end
|
586
|
+
end
|
587
|
+
@waiting -= 1
|
588
|
+
end
|
589
|
+
end
|
566
590
|
|
567
|
-
|
568
|
-
|
591
|
+
if @state == :pending
|
592
|
+
total_wait = deadline - start
|
593
|
+
raise Errors::TimeoutError, "Future did not complete within #{timeout.inspect} seconds. Wait time: #{total_wait.inspect}"
|
594
|
+
end
|
595
|
+
end
|
569
596
|
|
570
|
-
|
597
|
+
if @state == :broken
|
598
|
+
raise(@error, @error.message, @error.backtrace)
|
599
|
+
end
|
571
600
|
|
572
601
|
@value
|
573
602
|
end
|
574
603
|
|
604
|
+
alias :join :get
|
605
|
+
|
575
606
|
def add_listener(listener)
|
576
607
|
if @state == :pending
|
577
608
|
synchronize do
|