mongo 1.4.0 → 1.5.0.rc0
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.
- data/docs/HISTORY.md +15 -0
- data/docs/REPLICA_SETS.md +19 -7
- data/lib/mongo.rb +1 -0
- data/lib/mongo/collection.rb +1 -1
- data/lib/mongo/connection.rb +29 -351
- data/lib/mongo/cursor.rb +88 -6
- data/lib/mongo/gridfs/grid.rb +4 -2
- data/lib/mongo/gridfs/grid_file_system.rb +4 -2
- data/lib/mongo/networking.rb +345 -0
- data/lib/mongo/repl_set_connection.rb +236 -191
- data/lib/mongo/util/core_ext.rb +45 -0
- data/lib/mongo/util/logging.rb +5 -0
- data/lib/mongo/util/node.rb +6 -4
- data/lib/mongo/util/pool.rb +73 -26
- data/lib/mongo/util/pool_manager.rb +100 -30
- data/lib/mongo/util/uri_parser.rb +29 -21
- data/lib/mongo/version.rb +1 -1
- data/test/bson/binary_test.rb +6 -8
- data/test/bson/bson_test.rb +1 -0
- data/test/bson/ordered_hash_test.rb +2 -0
- data/test/bson/test_helper.rb +0 -17
- data/test/collection_test.rb +22 -0
- data/test/connection_test.rb +1 -1
- data/test/cursor_test.rb +3 -3
- data/test/load/thin/load.rb +4 -7
- data/test/replica_sets/basic_test.rb +46 -0
- data/test/replica_sets/connect_test.rb +35 -58
- data/test/replica_sets/count_test.rb +15 -6
- data/test/replica_sets/insert_test.rb +6 -7
- data/test/replica_sets/query_test.rb +4 -6
- data/test/replica_sets/read_preference_test.rb +112 -8
- data/test/replica_sets/refresh_test.rb +66 -36
- data/test/replica_sets/refresh_with_threads_test.rb +55 -0
- data/test/replica_sets/replication_ack_test.rb +3 -6
- data/test/replica_sets/rs_test_helper.rb +12 -6
- data/test/replica_sets/threading_test.rb +111 -0
- data/test/test_helper.rb +9 -2
- data/test/threading_test.rb +14 -6
- data/test/tools/repl_set_manager.rb +55 -40
- data/test/unit/collection_test.rb +2 -1
- data/test/unit/connection_test.rb +8 -8
- data/test/unit/grid_test.rb +4 -2
- data/test/unit/pool_manager_test.rb +1 -0
- data/test/unit/read_test.rb +17 -5
- data/test/uri_test.rb +9 -4
- metadata +13 -28
- data/test/replica_sets/connection_string_test.rb +0 -29
- data/test/replica_sets/pooled_insert_test.rb +0 -58
- data/test/replica_sets/query_secondaries.rb +0 -109
@@ -16,15 +16,14 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
# ++
|
18
18
|
|
19
|
-
require 'sync'
|
20
|
-
|
21
19
|
module Mongo
|
22
20
|
|
23
21
|
# Instantiates and manages connections to a MongoDB replica set.
|
24
22
|
class ReplSetConnection < Connection
|
25
|
-
|
26
|
-
|
27
|
-
|
23
|
+
CLEANUP_INTERVAL = 300
|
24
|
+
|
25
|
+
attr_reader :replica_set_name, :seeds, :refresh_interval, :refresh_mode,
|
26
|
+
:refresh_version
|
28
27
|
|
29
28
|
# Create a connection to a MongoDB replica set.
|
30
29
|
#
|
@@ -57,11 +56,10 @@ module Mongo
|
|
57
56
|
# @option opts [Float] :connect_timeout (nil) The number of seconds to wait before timing out a
|
58
57
|
# connection attempt.
|
59
58
|
# @option opts [Boolean] :ssl (false) If true, create the connection to the server using SSL.
|
60
|
-
# @option opts [Boolean] :refresh_mode (
|
61
|
-
#
|
62
|
-
#
|
63
|
-
#
|
64
|
-
# synchronously. If +false+, no automatic refresh will occur unless there's a connection failure.
|
59
|
+
# @option opts [Boolean] :refresh_mode (false) Set this to :sync to periodically update the
|
60
|
+
# state of the connection every :refresh_interval seconds. Replica set connection failures
|
61
|
+
# will always trigger a complete refresh. This option is useful when you want to add new nodes
|
62
|
+
# or remove replica set nodes not currently in use by the driver.
|
65
63
|
# @option opts [Integer] :refresh_interval (90) If :refresh_mode is enabled, this is the number of seconds
|
66
64
|
# between calls to check the replica set's state.
|
67
65
|
# @option opts [Boolean] :require_primary (true) If true, require a primary node for the connection
|
@@ -83,8 +81,6 @@ module Mongo
|
|
83
81
|
# @raise [ReplicaSetConnectionError] This is raised if a replica set name is specified and the
|
84
82
|
# driver fails to connect to a replica set with that name.
|
85
83
|
def initialize(*args)
|
86
|
-
extend Sync_m
|
87
|
-
|
88
84
|
if args.last.is_a?(Hash)
|
89
85
|
opts = args.pop
|
90
86
|
else
|
@@ -101,31 +97,21 @@ module Mongo
|
|
101
97
|
# TODO: get rid of this
|
102
98
|
@nodes = @seeds.dup
|
103
99
|
|
104
|
-
# The members of the replica set, stored as instances of Mongo::Node.
|
105
|
-
@members = []
|
106
|
-
|
107
|
-
# Connection pool for primary node
|
108
|
-
@primary = nil
|
109
|
-
@primary_pool = nil
|
110
|
-
|
111
|
-
# Connection pools for each secondary node
|
112
|
-
@secondaries = []
|
113
|
-
@secondary_pools = []
|
114
|
-
|
115
|
-
# The secondary pool to which we'll be sending reads.
|
116
|
-
# This may be identical to the primary pool.
|
117
|
-
@read_pool = nil
|
118
|
-
|
119
|
-
# A list of arbiter addresses (for client information only)
|
120
|
-
@arbiters = []
|
121
|
-
|
122
100
|
# Refresh
|
123
|
-
@refresh_mode = opts.fetch(:refresh_mode,
|
101
|
+
@refresh_mode = opts.fetch(:refresh_mode, false)
|
124
102
|
@refresh_interval = opts[:refresh_interval] || 90
|
103
|
+
@last_refresh = Time.now
|
125
104
|
|
126
|
-
|
105
|
+
# No connection manager by default.
|
106
|
+
@manager = nil
|
107
|
+
@pool_mutex = Mutex.new
|
108
|
+
|
109
|
+
if @refresh_mode == :async
|
110
|
+
warn ":async refresh mode has been deprecated. Refresh
|
111
|
+
mode will be disabled."
|
112
|
+
elsif ![:sync, false].include?(@refresh_mode)
|
127
113
|
raise MongoArgumentError,
|
128
|
-
"Refresh mode must be
|
114
|
+
"Refresh mode must be either :sync or false."
|
129
115
|
end
|
130
116
|
|
131
117
|
# Are we allowing reads from secondaries?
|
@@ -140,13 +126,7 @@ module Mongo
|
|
140
126
|
end
|
141
127
|
|
142
128
|
@connected = false
|
143
|
-
|
144
|
-
# Store the refresher thread
|
145
|
-
@refresh_thread = nil
|
146
|
-
|
147
|
-
# Maps
|
148
|
-
@sockets_to_pools = {}
|
149
|
-
@tags_to_pools = {}
|
129
|
+
@refresh_version = 0
|
150
130
|
|
151
131
|
# Replica set name
|
152
132
|
if opts[:rs_name]
|
@@ -164,68 +144,75 @@ module Mongo
|
|
164
144
|
end
|
165
145
|
|
166
146
|
def inspect
|
167
|
-
"<Mongo::ReplSetConnection:0x#{self.object_id.to_s(16)} @seeds=#{@seeds} " +
|
147
|
+
"<Mongo::ReplSetConnection:0x#{self.object_id.to_s(16)} @seeds=#{@seeds.inspect} " +
|
168
148
|
"@connected=#{@connected}>"
|
169
149
|
end
|
170
150
|
|
171
151
|
# Initiate a connection to the replica set.
|
172
152
|
def connect
|
173
153
|
log(:info, "Connecting...")
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
end
|
154
|
+
return if @connected
|
155
|
+
manager = PoolManager.new(self, @seeds)
|
156
|
+
manager.connect
|
157
|
+
|
158
|
+
update_config(manager)
|
159
|
+
|
160
|
+
if @require_primary && self.primary.nil? #TODO: in v2.0, we'll let this be optional and do a lazy connect.
|
161
|
+
close
|
162
|
+
raise ConnectionFailure, "Failed to connect to primary node."
|
163
|
+
elsif self.read_pool.nil?
|
164
|
+
close
|
165
|
+
raise ConnectionFailure, "Failed to connect to any node."
|
166
|
+
else
|
167
|
+
@connected = true
|
189
168
|
end
|
190
169
|
end
|
191
170
|
|
192
|
-
#
|
193
|
-
#
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
@primary_pool = manager.primary_pool
|
201
|
-
@read_pool = manager.read_pool
|
202
|
-
@secondary_pools = manager.secondary_pools
|
203
|
-
@tags_to_pools = manager.tags_to_pools
|
204
|
-
@seeds = manager.seeds
|
205
|
-
@manager = manager
|
206
|
-
@nodes = manager.nodes
|
207
|
-
@max_bson_size = manager.max_bson_size
|
208
|
-
end
|
209
|
-
|
210
|
-
# Refresh the current replica set configuration.
|
171
|
+
# Determine whether a replica set refresh is
|
172
|
+
# required. If so, run a hard refresh. You can
|
173
|
+
# force a hard refresh by running
|
174
|
+
# ReplSetConnection#hard_refresh!
|
175
|
+
#
|
176
|
+
# @return [Boolean] +true+ unless a hard refresh
|
177
|
+
# is run and the refresh lock can't be acquired.
|
211
178
|
def refresh(opts={})
|
212
|
-
|
179
|
+
if !connected?
|
180
|
+
log(:info, "Trying to check replica set health but not " +
|
181
|
+
"connected...")
|
182
|
+
return hard_refresh!
|
183
|
+
end
|
213
184
|
|
214
|
-
|
215
|
-
|
185
|
+
log(:debug, "Checking replica set connection health...")
|
186
|
+
@manager.check_connection_health
|
216
187
|
|
217
|
-
|
218
|
-
|
219
|
-
@background_manager ||= PoolManager.new(self, @seeds)
|
220
|
-
@background_manager.connect
|
221
|
-
update_config(@background_manager)
|
188
|
+
if @manager.refresh_required?
|
189
|
+
return hard_refresh!
|
222
190
|
end
|
223
191
|
|
224
192
|
return true
|
225
193
|
end
|
226
194
|
|
195
|
+
# Force a hard refresh of this connection's view
|
196
|
+
# of the replica set.
|
197
|
+
#
|
198
|
+
# @return [Boolean] +true+ if hard refresh
|
199
|
+
# occurred. +false+ is returned when unable
|
200
|
+
# to get the refresh lock.
|
201
|
+
def hard_refresh!
|
202
|
+
log(:info, "Initiating hard refresh...")
|
203
|
+
background_manager = PoolManager.new(self, @seeds)
|
204
|
+
background_manager.connect
|
205
|
+
|
206
|
+
# TODO: make sure that connect has succeeded
|
207
|
+
old_manager = @manager
|
208
|
+
update_config(background_manager)
|
209
|
+
old_manager.close(:soft => true)
|
210
|
+
|
211
|
+
return true
|
212
|
+
end
|
213
|
+
|
227
214
|
def connected?
|
228
|
-
|
215
|
+
self.primary_pool || self.read_pool
|
229
216
|
end
|
230
217
|
|
231
218
|
# @deprecated
|
@@ -238,14 +225,14 @@ module Mongo
|
|
238
225
|
#
|
239
226
|
# @return [String]
|
240
227
|
def host
|
241
|
-
|
228
|
+
self.primary_pool.host
|
242
229
|
end
|
243
230
|
|
244
231
|
# The replica set primary's port.
|
245
232
|
#
|
246
233
|
# @return [Integer]
|
247
234
|
def port
|
248
|
-
|
235
|
+
self.primary_pool.port
|
249
236
|
end
|
250
237
|
|
251
238
|
def nodes
|
@@ -259,9 +246,7 @@ module Mongo
|
|
259
246
|
#
|
260
247
|
# @return [Boolean]
|
261
248
|
def read_primary?
|
262
|
-
|
263
|
-
@read_pool == @primary_pool
|
264
|
-
end
|
249
|
+
self.read_pool == self.primary_pool
|
265
250
|
end
|
266
251
|
alias :primary? :read_primary?
|
267
252
|
|
@@ -271,36 +256,8 @@ module Mongo
|
|
271
256
|
|
272
257
|
# Close the connection to the database.
|
273
258
|
def close
|
274
|
-
|
275
|
-
|
276
|
-
super
|
277
|
-
|
278
|
-
if @refresh_thread
|
279
|
-
@refresh_thread.kill
|
280
|
-
@refresh_thread = nil
|
281
|
-
end
|
282
|
-
|
283
|
-
if @nodes
|
284
|
-
@nodes.each do |member|
|
285
|
-
member.close
|
286
|
-
end
|
287
|
-
end
|
288
|
-
|
289
|
-
@nodes = []
|
290
|
-
@read_pool = nil
|
291
|
-
|
292
|
-
if @secondary_pools
|
293
|
-
@secondary_pools.each do |pool|
|
294
|
-
pool.close
|
295
|
-
end
|
296
|
-
end
|
297
|
-
|
298
|
-
@secondaries = []
|
299
|
-
@secondary_pools = []
|
300
|
-
@arbiters = []
|
301
|
-
@tags_to_pools.clear
|
302
|
-
@sockets_to_pools.clear
|
303
|
-
end
|
259
|
+
@connected = false
|
260
|
+
@manager.close(:soft => true) if @manager
|
304
261
|
end
|
305
262
|
|
306
263
|
# If a ConnectionFailure is raised, this method will be called
|
@@ -324,45 +281,29 @@ module Mongo
|
|
324
281
|
end
|
325
282
|
|
326
283
|
def authenticate_pools
|
327
|
-
|
328
|
-
|
284
|
+
self.primary_pool.authenticate_existing
|
285
|
+
self.secondary_pools.each do |pool|
|
329
286
|
pool.authenticate_existing
|
330
287
|
end
|
331
288
|
end
|
332
289
|
|
333
290
|
def logout_pools(db)
|
334
|
-
|
335
|
-
|
291
|
+
self.primary_pool.logout_existing(db)
|
292
|
+
self.secondary_pools.each do |pool|
|
336
293
|
pool.logout_existing(db)
|
337
294
|
end
|
338
295
|
end
|
339
296
|
|
340
|
-
private
|
341
|
-
|
342
|
-
def initiate_refresh_mode
|
343
|
-
if @refresh_mode == :async
|
344
|
-
return if @refresh_thread && @refresh_thread.alive?
|
345
|
-
@refresh_thread = Thread.new do
|
346
|
-
while true do
|
347
|
-
sleep(@refresh_interval)
|
348
|
-
refresh
|
349
|
-
end
|
350
|
-
end
|
351
|
-
end
|
352
|
-
|
353
|
-
@last_refresh = Time.now
|
354
|
-
end
|
355
|
-
|
356
297
|
# Checkout a socket for reading (i.e., a secondary node).
|
357
298
|
# Note that @read_pool might point to the primary pool
|
358
299
|
# if no read pool has been defined.
|
359
300
|
def checkout_reader
|
360
301
|
connect unless connected?
|
361
|
-
socket = get_socket_from_pool(
|
302
|
+
socket = get_socket_from_pool(self.read_pool)
|
362
303
|
|
363
304
|
if !socket
|
364
|
-
|
365
|
-
socket = get_socket_from_pool(
|
305
|
+
connect
|
306
|
+
socket = get_socket_from_pool(self.primary_pool)
|
366
307
|
end
|
367
308
|
|
368
309
|
if socket
|
@@ -372,35 +313,14 @@ module Mongo
|
|
372
313
|
end
|
373
314
|
end
|
374
315
|
|
375
|
-
# Checkout a socket connected to a node with one of
|
376
|
-
# the provided tags. If no such node exists, raise
|
377
|
-
# an exception.
|
378
|
-
#
|
379
|
-
# NOTE: will be available in driver release v2.0.
|
380
|
-
def checkout_tagged(tags)
|
381
|
-
sync_synchronize(:SH) do
|
382
|
-
tags.each do |k, v|
|
383
|
-
pool = @tags_to_pools[{k.to_s => v}]
|
384
|
-
if pool
|
385
|
-
socket = pool.checkout
|
386
|
-
@sockets_to_pools[socket] = pool
|
387
|
-
return socket
|
388
|
-
end
|
389
|
-
end
|
390
|
-
end
|
391
|
-
|
392
|
-
raise NodeWithTagsNotFound,
|
393
|
-
"Could not find a connection tagged with #{tags}."
|
394
|
-
end
|
395
|
-
|
396
316
|
# Checkout a socket for writing (i.e., a primary node).
|
397
317
|
def checkout_writer
|
398
318
|
connect unless connected?
|
399
|
-
socket = get_socket_from_pool(
|
319
|
+
socket = get_socket_from_pool(self.primary_pool)
|
400
320
|
|
401
321
|
if !socket
|
402
|
-
|
403
|
-
socket = get_socket_from_pool(
|
322
|
+
connect
|
323
|
+
socket = get_socket_from_pool(self.primary_pool)
|
404
324
|
end
|
405
325
|
|
406
326
|
if socket
|
@@ -410,49 +330,174 @@ module Mongo
|
|
410
330
|
end
|
411
331
|
end
|
412
332
|
|
333
|
+
# Checkin a socket used for reading.
|
334
|
+
def checkin_reader(socket)
|
335
|
+
if !self.read_pool.checkin(socket) &&
|
336
|
+
!self.primary_pool.checkin(socket)
|
337
|
+
close_socket(socket)
|
338
|
+
end
|
339
|
+
sync_refresh
|
340
|
+
end
|
341
|
+
|
342
|
+
# Checkin a socket used for writing.
|
343
|
+
def checkin_writer(socket)
|
344
|
+
if !self.primary_pool.checkin(socket)
|
345
|
+
close_socket(socket)
|
346
|
+
end
|
347
|
+
sync_refresh
|
348
|
+
end
|
349
|
+
|
350
|
+
def close_socket(socket)
|
351
|
+
begin
|
352
|
+
socket.close
|
353
|
+
rescue IOError
|
354
|
+
log(:info, "Tried to close socket #{socket} but already closed.")
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
413
358
|
def get_socket_from_pool(pool)
|
414
359
|
begin
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
@sockets_to_pools[socket] = pool
|
419
|
-
socket
|
420
|
-
end
|
360
|
+
if pool
|
361
|
+
socket = pool.checkout
|
362
|
+
socket
|
421
363
|
end
|
422
|
-
|
423
364
|
rescue ConnectionFailure => ex
|
424
365
|
log(:info, "Failed to checkout from #{pool} with #{ex.class}; #{ex.message}")
|
425
366
|
return nil
|
426
367
|
end
|
427
368
|
end
|
428
369
|
|
429
|
-
|
430
|
-
|
431
|
-
warn "ReplSetConnection#checkin_writer is deprecated and will be removed " +
|
432
|
-
"in driver v2.0. Use ReplSetConnection#checkin instead."
|
433
|
-
checkin(socket)
|
370
|
+
def arbiters
|
371
|
+
@manager.arbiters.nil? ? [] : @manager.arbiters
|
434
372
|
end
|
435
373
|
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
374
|
+
def primary
|
375
|
+
@manager.primary
|
376
|
+
end
|
377
|
+
|
378
|
+
# Note: might want to freeze these after connecting.
|
379
|
+
def secondaries
|
380
|
+
@manager.secondaries
|
381
|
+
end
|
382
|
+
|
383
|
+
def hosts
|
384
|
+
@manager.hosts
|
385
|
+
end
|
386
|
+
|
387
|
+
def primary_pool
|
388
|
+
@manager.primary_pool
|
389
|
+
end
|
390
|
+
|
391
|
+
def read_pool
|
392
|
+
@manager.read_pool
|
393
|
+
end
|
394
|
+
|
395
|
+
def secondary_pools
|
396
|
+
@manager.secondary_pools
|
397
|
+
end
|
398
|
+
|
399
|
+
def tag_map
|
400
|
+
@manager.tag_map
|
401
|
+
end
|
402
|
+
|
403
|
+
def max_bson_size
|
404
|
+
@manager.max_bson_size
|
405
|
+
end
|
406
|
+
|
407
|
+
private
|
408
|
+
|
409
|
+
# Generic initialization code.
|
410
|
+
def setup(opts)
|
411
|
+
# Default maximum BSON object size
|
412
|
+
@max_bson_size = Mongo::DEFAULT_MAX_BSON_SIZE
|
413
|
+
|
414
|
+
@safe_mutex_lock = Mutex.new
|
415
|
+
@safe_mutexes = Hash.new {|hash, key| hash[key] = Mutex.new}
|
416
|
+
|
417
|
+
# Determine whether to use SSL.
|
418
|
+
@ssl = opts.fetch(:ssl, false)
|
419
|
+
if @ssl
|
420
|
+
@socket_class = Mongo::SSLSocket
|
421
|
+
else
|
422
|
+
@socket_class = ::TCPSocket
|
423
|
+
end
|
424
|
+
|
425
|
+
# Authentication objects
|
426
|
+
@auths = opts.fetch(:auths, [])
|
427
|
+
|
428
|
+
# Lock for request ids.
|
429
|
+
@id_lock = Mutex.new
|
430
|
+
|
431
|
+
# Pool size and timeout.
|
432
|
+
@pool_size = opts[:pool_size] || 1
|
433
|
+
if opts[:timeout]
|
434
|
+
warn "The :timeout option has been deprecated " +
|
435
|
+
"and will be removed in the 2.0 release. Use :pool_timeout instead."
|
436
|
+
end
|
437
|
+
@pool_timeout = opts[:pool_timeout] || opts[:timeout] || 5.0
|
438
|
+
|
439
|
+
# Timeout on socket read operation.
|
440
|
+
@op_timeout = opts[:op_timeout] || nil
|
441
|
+
|
442
|
+
# Timeout on socket connect.
|
443
|
+
@connect_timeout = opts[:connect_timeout] || nil
|
444
|
+
|
445
|
+
# Mutex for synchronizing pool access
|
446
|
+
# TODO: remove this.
|
447
|
+
@connection_mutex = Mutex.new
|
448
|
+
|
449
|
+
# Global safe option. This is false by default.
|
450
|
+
@safe = opts[:safe] || false
|
451
|
+
|
452
|
+
# Condition variable for signal and wait
|
453
|
+
@queue = ConditionVariable.new
|
454
|
+
|
455
|
+
@logger = opts[:logger] || nil
|
456
|
+
|
457
|
+
# Clean up connections to dead threads.
|
458
|
+
@last_cleanup = Time.now
|
459
|
+
@cleanup_lock = Mutex.new
|
460
|
+
|
461
|
+
if @logger
|
462
|
+
write_logging_startup_message
|
463
|
+
end
|
464
|
+
|
465
|
+
@last_refresh = Time.now
|
466
|
+
|
467
|
+
should_connect = opts.fetch(:connect, true)
|
468
|
+
connect if should_connect
|
441
469
|
end
|
442
470
|
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
471
|
+
# Given a pool manager, update this connection's
|
472
|
+
# view of the replica set.
|
473
|
+
def update_config(new_manager)
|
474
|
+
@manager = new_manager
|
475
|
+
@seeds = @manager.seeds.dup
|
476
|
+
@refresh_version += 1
|
477
|
+
end
|
478
|
+
|
479
|
+
# Checkout a socket connected to a node with one of
|
480
|
+
# the provided tags. If no such node exists, raise
|
481
|
+
# an exception.
|
482
|
+
#
|
483
|
+
# NOTE: will be available in driver release v2.0.
|
484
|
+
def checkout_tagged(tags)
|
485
|
+
tags.each do |k, v|
|
486
|
+
pool = self.tag_map[{k.to_s => v}]
|
487
|
+
if pool
|
488
|
+
socket = pool.checkout
|
489
|
+
return socket
|
449
490
|
end
|
450
491
|
end
|
451
492
|
|
452
|
-
|
453
|
-
|
493
|
+
raise NodeWithTagsNotFound,
|
494
|
+
"Could not find a connection tagged with #{tags}."
|
495
|
+
end
|
496
|
+
|
497
|
+
def sync_refresh
|
454
498
|
if @refresh_mode == :sync &&
|
455
499
|
((Time.now - @last_refresh) > @refresh_interval)
|
500
|
+
@last_refresh = Time.now
|
456
501
|
refresh
|
457
502
|
end
|
458
503
|
end
|