mongo 1.8.5 → 1.8.6
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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/Rakefile +2 -2
- data/VERSION +1 -1
- data/lib/mongo/db.rb +6 -1
- data/lib/mongo/mongo_client.rb +28 -27
- data/lib/mongo/mongo_replica_set_client.rb +15 -21
- data/lib/mongo/mongo_sharded_client.rb +6 -9
- data/lib/mongo/util/node.rb +10 -3
- data/lib/mongo/util/pool_manager.rb +47 -29
- data/lib/mongo/util/read_preference.rb +6 -6
- data/lib/mongo/util/sharding_pool_manager.rb +31 -18
- data/test/functional/authentication_test.rb +1 -4
- data/test/replica_set/authentication_test.rb +2 -5
- data/test/replica_set/client_test.rb +15 -0
- data/test/replica_set/max_values_test.rb +35 -20
- data/test/replica_set/refresh_test.rb +31 -0
- data/test/sharded_cluster/basic_test.rb +2 -2
- data/test/shared/authentication.rb +17 -0
- data/test/test_helper.rb +7 -1
- data/test/tools/mongo_config.rb +13 -7
- data/test/unit/cursor_test.rb +6 -6
- data/test/unit/mongo_sharded_client_test.rb +4 -4
- data/test/unit/read_pref_test.rb +21 -0
- data/test/unit/sharding_pool_manager_test.rb +0 -25
- metadata +6 -4
- metadata.gz.sig +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5bdb78ad2291ea3ecb387526ccdbd162ffd51687
|
4
|
+
data.tar.gz: 6b3ec42fadc3f0beea953a08fe07a2d2ff206cba
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 83bb86f711779590a47d0d8d83fea4d844cd8ebdcde6617109c9172dd9d6961688d3faf03c1c7d0c0601575ed1a253522aecc2b26f2e81fb7980079ca3dff9fd
|
7
|
+
data.tar.gz: 880a70826f29e9e60fff3d26ede30390da593e78ad095f635743ffec711ce22af34da2d89318fd48f7825e2583bbec02da80c78899d4388386a76c769ee1e80e
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/Rakefile
CHANGED
@@ -8,10 +8,10 @@ rescue LoadError
|
|
8
8
|
raise '[FAIL] Bundler not found! Install it with `gem install bundler; bundle install`.'
|
9
9
|
end
|
10
10
|
|
11
|
-
if ENV
|
11
|
+
if ENV.has_key?('TEST') || ENV.has_key?('TRAVIS_TEST')
|
12
12
|
Bundler.require(:default, :testing)
|
13
13
|
else
|
14
|
-
Bundler.require(:default, :deploy, :
|
14
|
+
Bundler.require(:default, :testing, :deploy, :development)
|
15
15
|
end
|
16
16
|
|
17
17
|
Dir.glob(File.join('tasks', '**', '*.rake')).sort.each { |rake| load File.expand_path(rake) }
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.8.
|
1
|
+
1.8.6
|
data/lib/mongo/db.rb
CHANGED
@@ -192,7 +192,12 @@ module Mongo
|
|
192
192
|
user = users.find_one({:user => username}) || {:user => username}
|
193
193
|
user['pwd'] = Mongo::Support.hash_password(username, password)
|
194
194
|
user['readOnly'] = true if read_only;
|
195
|
-
|
195
|
+
begin
|
196
|
+
users.save(user)
|
197
|
+
rescue OperationFailure => ex
|
198
|
+
# adding first admin user fails GLE in MongoDB 2.2
|
199
|
+
raise ex unless ex.message =~ /login/
|
200
|
+
end
|
196
201
|
user
|
197
202
|
end
|
198
203
|
|
data/lib/mongo/mongo_client.rb
CHANGED
@@ -160,7 +160,7 @@ module Mongo
|
|
160
160
|
|
161
161
|
# Initialize a connection to MongoDB using the MongoDB URI spec.
|
162
162
|
#
|
163
|
-
# Since MongoClient.new cannot be used with any <code>ENV["MONGODB_URI"]</code> that has multiple hosts (implying a replicaset),
|
163
|
+
# Since MongoClient.new cannot be used with any <code>ENV["MONGODB_URI"]</code> that has multiple hosts (implying a replicaset),
|
164
164
|
# you may use this when the type of your connection varies by environment and should be determined solely from <code>ENV["MONGODB_URI"]</code>.
|
165
165
|
#
|
166
166
|
# @param uri [String]
|
@@ -469,7 +469,7 @@ module Mongo
|
|
469
469
|
# NOTE: Do check if this needs to be more stringent.
|
470
470
|
# Probably not since if any node raises a connection failure, all nodes will be closed.
|
471
471
|
def connected?
|
472
|
-
@primary_pool && !@primary_pool.closed?
|
472
|
+
!!(@primary_pool && !@primary_pool.closed?)
|
473
473
|
end
|
474
474
|
|
475
475
|
# Determine if the connection is active. In a normal case the *server_info* operation
|
@@ -545,6 +545,32 @@ module Mongo
|
|
545
545
|
end
|
546
546
|
end
|
547
547
|
|
548
|
+
# Internal method for checking isMaster() on a given node.
|
549
|
+
#
|
550
|
+
# @param node [Array] Port and host for the target node
|
551
|
+
# @return [Hash] Response from isMaster()
|
552
|
+
#
|
553
|
+
# @private
|
554
|
+
def check_is_master(node)
|
555
|
+
begin
|
556
|
+
host, port = *node
|
557
|
+
config = nil
|
558
|
+
socket = @socket_class.new(host, port, @op_timeout, @connect_timeout)
|
559
|
+
if @connect_timeout
|
560
|
+
Timeout::timeout(@connect_timeout, OperationTimeout) do
|
561
|
+
config = self['admin'].command({:ismaster => 1}, :socket => socket)
|
562
|
+
end
|
563
|
+
else
|
564
|
+
config = self['admin'].command({:ismaster => 1}, :socket => socket)
|
565
|
+
end
|
566
|
+
rescue OperationFailure, SocketError, SystemCallError, IOError
|
567
|
+
close
|
568
|
+
ensure
|
569
|
+
socket.close unless socket.nil? || socket.closed?
|
570
|
+
end
|
571
|
+
config
|
572
|
+
end
|
573
|
+
|
548
574
|
protected
|
549
575
|
|
550
576
|
def valid_opts
|
@@ -621,31 +647,6 @@ module Mongo
|
|
621
647
|
|
622
648
|
private
|
623
649
|
|
624
|
-
def check_is_master(node)
|
625
|
-
begin
|
626
|
-
host, port = *node
|
627
|
-
socket = nil
|
628
|
-
config = nil
|
629
|
-
|
630
|
-
socket = @socket_class.new(host, port, @op_timeout, @connect_timeout)
|
631
|
-
if(@connect_timeout)
|
632
|
-
Timeout::timeout(@connect_timeout, OperationTimeout) do
|
633
|
-
config = self['admin'].command({:ismaster => 1}, :socket => socket)
|
634
|
-
end
|
635
|
-
else
|
636
|
-
config = self['admin'].command({:ismaster => 1}, :socket => socket)
|
637
|
-
end
|
638
|
-
rescue OperationFailure, SocketError, SystemCallError, IOError
|
639
|
-
close
|
640
|
-
ensure
|
641
|
-
if socket
|
642
|
-
socket.close unless socket.closed?
|
643
|
-
end
|
644
|
-
end
|
645
|
-
|
646
|
-
config
|
647
|
-
end
|
648
|
-
|
649
650
|
# Set the specified node as primary.
|
650
651
|
def set_primary(node)
|
651
652
|
host, port = *node
|
@@ -137,14 +137,9 @@ module Mongo
|
|
137
137
|
# Lock for request ids.
|
138
138
|
@id_lock = Mutex.new
|
139
139
|
|
140
|
-
@pool_mutex = Mutex.new
|
141
140
|
@connected = false
|
142
141
|
|
143
|
-
@safe_mutex_lock = Mutex.new
|
144
|
-
@safe_mutexes = Hash.new {|hash, key| hash[key] = Mutex.new}
|
145
|
-
|
146
142
|
@connect_mutex = Mutex.new
|
147
|
-
@refresh_mutex = Mutex.new
|
148
143
|
|
149
144
|
@mongos = false
|
150
145
|
|
@@ -162,7 +157,8 @@ module Mongo
|
|
162
157
|
end
|
163
158
|
|
164
159
|
# Initiate a connection to the replica set.
|
165
|
-
def connect
|
160
|
+
def connect(force = !connected?)
|
161
|
+
return unless force
|
166
162
|
log(:info, "Connecting...")
|
167
163
|
|
168
164
|
# Prevent recursive connection attempts from the same thread.
|
@@ -170,15 +166,18 @@ module Mongo
|
|
170
166
|
# infinitely while attempting to connect and continually failing. Instead, fail fast.
|
171
167
|
raise ConnectionFailure, "Failed to get node data." if thread_local[:locks][:connecting] == true
|
172
168
|
|
169
|
+
current_version = @refresh_version
|
173
170
|
@connect_mutex.synchronize do
|
174
|
-
|
171
|
+
# don't try to connect if another thread has done so while we were waiting for the lock
|
172
|
+
return unless current_version == @refresh_version
|
175
173
|
begin
|
176
174
|
thread_local[:locks][:connecting] = true
|
177
175
|
if @manager
|
178
|
-
|
176
|
+
ensure_manager
|
177
|
+
@manager.refresh!(@seeds)
|
179
178
|
else
|
180
179
|
@manager = PoolManager.new(self, @seeds)
|
181
|
-
|
180
|
+
ensure_manager
|
182
181
|
@manager.connect
|
183
182
|
end
|
184
183
|
ensure
|
@@ -210,6 +209,7 @@ module Mongo
|
|
210
209
|
end
|
211
210
|
|
212
211
|
log(:debug, "Checking replica set connection health...")
|
212
|
+
ensure_manager
|
213
213
|
@manager.check_connection_health
|
214
214
|
|
215
215
|
if @manager.refresh_required?
|
@@ -227,9 +227,7 @@ module Mongo
|
|
227
227
|
# to get the refresh lock.
|
228
228
|
def hard_refresh!
|
229
229
|
log(:info, "Initiating hard refresh...")
|
230
|
-
|
231
|
-
|
232
|
-
@refresh_version += 1
|
230
|
+
connect(true)
|
233
231
|
return true
|
234
232
|
end
|
235
233
|
|
@@ -420,6 +418,10 @@ module Mongo
|
|
420
418
|
local_manager ? local_manager.secondary_pools : []
|
421
419
|
end
|
422
420
|
|
421
|
+
def pools
|
422
|
+
local_manager ? local_manager.pools : []
|
423
|
+
end
|
424
|
+
|
423
425
|
def tag_map
|
424
426
|
local_manager ? local_manager.tag_map : {}
|
425
427
|
end
|
@@ -475,16 +477,8 @@ module Mongo
|
|
475
477
|
def sync_refresh
|
476
478
|
if @refresh_mode == :sync &&
|
477
479
|
((Time.now - @last_refresh) > @refresh_interval)
|
478
|
-
|
479
480
|
@last_refresh = Time.now
|
480
|
-
|
481
|
-
if @refresh_mutex.try_lock
|
482
|
-
begin
|
483
|
-
refresh
|
484
|
-
ensure
|
485
|
-
@refresh_mutex.unlock
|
486
|
-
end
|
487
|
-
end
|
481
|
+
refresh
|
488
482
|
end
|
489
483
|
end
|
490
484
|
end
|
@@ -41,14 +41,9 @@ module Mongo
|
|
41
41
|
# Lock for request ids.
|
42
42
|
@id_lock = Mutex.new
|
43
43
|
|
44
|
-
@pool_mutex = Mutex.new
|
45
44
|
@connected = false
|
46
45
|
|
47
|
-
@safe_mutex_lock = Mutex.new
|
48
|
-
@safe_mutexes = Hash.new {|hash, key| hash[key] = Mutex.new}
|
49
|
-
|
50
46
|
@connect_mutex = Mutex.new
|
51
|
-
@refresh_mutex = Mutex.new
|
52
47
|
|
53
48
|
@mongos = true
|
54
49
|
|
@@ -66,7 +61,7 @@ module Mongo
|
|
66
61
|
end
|
67
62
|
|
68
63
|
# Initiate a connection to the sharded cluster.
|
69
|
-
def connect(force =
|
64
|
+
def connect(force = !connected?)
|
70
65
|
return unless force
|
71
66
|
log(:info, "Connecting...")
|
72
67
|
|
@@ -79,10 +74,11 @@ module Mongo
|
|
79
74
|
begin
|
80
75
|
thread_local[:locks][:connecting] = true
|
81
76
|
if @manager
|
77
|
+
thread_local[:managers][self] = @manager
|
82
78
|
@manager.refresh! @seeds
|
83
79
|
else
|
84
80
|
@manager = ShardingPoolManager.new(self, @seeds)
|
85
|
-
|
81
|
+
ensure_manager
|
86
82
|
@manager.connect
|
87
83
|
end
|
88
84
|
ensure
|
@@ -108,7 +104,7 @@ module Mongo
|
|
108
104
|
end
|
109
105
|
|
110
106
|
def connected?
|
111
|
-
@connected && @manager.primary_pool
|
107
|
+
!!(@connected && @manager.primary_pool)
|
112
108
|
end
|
113
109
|
|
114
110
|
# Returns +true+ if it's okay to read from a secondary node.
|
@@ -140,7 +136,8 @@ module Mongo
|
|
140
136
|
# @param opts [ Hash ] Any of the options available for MongoShardedClient.new
|
141
137
|
#
|
142
138
|
# @return [ Mongo::MongoShardedClient ] The sharded client.
|
143
|
-
def self.from_uri(uri
|
139
|
+
def self.from_uri(uri, options = {})
|
140
|
+
uri ||= ENV['MONGODB_URI']
|
144
141
|
URIParser.new(uri).connection(options, false, true)
|
145
142
|
end
|
146
143
|
end
|
data/lib/mongo/util/node.rb
CHANGED
@@ -90,6 +90,7 @@ module Mongo
|
|
90
90
|
end
|
91
91
|
|
92
92
|
@config = @client['admin'].command({:ismaster => 1}, :socket => @socket)
|
93
|
+
update_max_sizes
|
93
94
|
|
94
95
|
if @config['msg']
|
95
96
|
@client.log(:warn, "#{config['msg']}")
|
@@ -106,7 +107,6 @@ module Mongo
|
|
106
107
|
close
|
107
108
|
end
|
108
109
|
end
|
109
|
-
@manager.update_max_sizes
|
110
110
|
end
|
111
111
|
|
112
112
|
# Return a list of replica set nodes from the config.
|
@@ -151,11 +151,11 @@ module Mongo
|
|
151
151
|
end
|
152
152
|
|
153
153
|
def max_bson_size
|
154
|
-
|
154
|
+
@max_bson_size || DEFAULT_MAX_BSON_SIZE
|
155
155
|
end
|
156
156
|
|
157
157
|
def max_message_size
|
158
|
-
|
158
|
+
@max_message_size || max_bson_size * MESSAGE_SIZE_FACTOR
|
159
159
|
end
|
160
160
|
|
161
161
|
protected
|
@@ -186,5 +186,12 @@ module Mongo
|
|
186
186
|
end
|
187
187
|
end
|
188
188
|
end
|
189
|
+
|
190
|
+
private
|
191
|
+
|
192
|
+
def update_max_sizes
|
193
|
+
@max_bson_size = config['maxBsonObjectSize'] || DEFAULT_MAX_BSON_SIZE
|
194
|
+
@max_message_size = config['maxMessageSizeBytes'] || @max_bson_size * MESSAGE_SIZE_FACTOR
|
195
|
+
end
|
189
196
|
end
|
190
197
|
end
|
@@ -9,8 +9,6 @@ module Mongo
|
|
9
9
|
:primary_pool,
|
10
10
|
:secondary_pools,
|
11
11
|
:hosts,
|
12
|
-
:nodes,
|
13
|
-
:members,
|
14
12
|
:seeds,
|
15
13
|
:pools,
|
16
14
|
:max_bson_size,
|
@@ -24,19 +22,21 @@ module Mongo
|
|
24
22
|
# time. The union of these lists will be used when attempting to connect,
|
25
23
|
# with the newly-discovered nodes being used first.
|
26
24
|
def initialize(client, seeds=[])
|
27
|
-
@client
|
28
|
-
@seeds
|
29
|
-
|
30
|
-
@pools
|
31
|
-
@primary
|
32
|
-
@primary_pool
|
33
|
-
@secondaries
|
34
|
-
@secondary_pools
|
35
|
-
@hosts
|
36
|
-
@members
|
37
|
-
@refresh_required
|
38
|
-
@max_bson_size
|
39
|
-
@max_message_size
|
25
|
+
@client = client
|
26
|
+
@seeds = seeds
|
27
|
+
|
28
|
+
@pools = Set.new
|
29
|
+
@primary = nil
|
30
|
+
@primary_pool = nil
|
31
|
+
@secondaries = Set.new
|
32
|
+
@secondary_pools = []
|
33
|
+
@hosts = Set.new
|
34
|
+
@members = Set.new
|
35
|
+
@refresh_required = false
|
36
|
+
@max_bson_size = DEFAULT_MAX_BSON_SIZE
|
37
|
+
@max_message_size = @max_bson_size * MESSAGE_SIZE_FACTOR
|
38
|
+
@connect_mutex = Mutex.new
|
39
|
+
thread_local[:locks][:connecting_manager] = false
|
40
40
|
end
|
41
41
|
|
42
42
|
def inspect
|
@@ -44,11 +44,19 @@ module Mongo
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def connect
|
47
|
-
@
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
47
|
+
@connect_mutex.synchronize do
|
48
|
+
begin
|
49
|
+
thread_local[:locks][:connecting_manager] = true
|
50
|
+
@refresh_required = false
|
51
|
+
disconnect_old_members
|
52
|
+
connect_to_members
|
53
|
+
initialize_pools(@members)
|
54
|
+
update_max_sizes
|
55
|
+
@seeds = discovered_seeds
|
56
|
+
ensure
|
57
|
+
thread_local[:locks][:connecting_manager] = false
|
58
|
+
end
|
59
|
+
end
|
52
60
|
end
|
53
61
|
|
54
62
|
def refresh!(additional_seeds)
|
@@ -61,6 +69,8 @@ module Mongo
|
|
61
69
|
# to our view. If any of these isn't the case,
|
62
70
|
# set @refresh_required to true, and return.
|
63
71
|
def check_connection_health
|
72
|
+
return if thread_local[:locks][:connecting_manager]
|
73
|
+
members = copy_members
|
64
74
|
begin
|
65
75
|
seed = get_valid_seed_node
|
66
76
|
rescue ConnectionFailure
|
@@ -74,14 +84,14 @@ module Mongo
|
|
74
84
|
return
|
75
85
|
end
|
76
86
|
|
77
|
-
if current_config['hosts'].length !=
|
87
|
+
if current_config['hosts'].length != members.length
|
78
88
|
@refresh_required = true
|
79
89
|
seed.close
|
80
90
|
return
|
81
91
|
end
|
82
92
|
|
83
93
|
current_config['hosts'].each do |host|
|
84
|
-
member =
|
94
|
+
member = members.detect do |m|
|
85
95
|
m.address == host
|
86
96
|
end
|
87
97
|
|
@@ -90,7 +100,7 @@ module Mongo
|
|
90
100
|
else
|
91
101
|
@refresh_required = true
|
92
102
|
seed.close
|
93
|
-
return
|
103
|
+
return
|
94
104
|
end
|
95
105
|
end
|
96
106
|
|
@@ -117,6 +127,8 @@ module Mongo
|
|
117
127
|
read_pool.host_port
|
118
128
|
end
|
119
129
|
|
130
|
+
private
|
131
|
+
|
120
132
|
def update_max_sizes
|
121
133
|
unless @members.size == 0
|
122
134
|
@max_bson_size = @members.map(&:max_bson_size).min
|
@@ -124,8 +136,6 @@ module Mongo
|
|
124
136
|
end
|
125
137
|
end
|
126
138
|
|
127
|
-
private
|
128
|
-
|
129
139
|
def validate_existing_member(current_config, member)
|
130
140
|
if current_config['ismaster'] && member.last_state != :primary
|
131
141
|
return false
|
@@ -152,13 +162,13 @@ module Mongo
|
|
152
162
|
existing.set_config
|
153
163
|
# If we are unhealthy after refreshing our config, drop from the set.
|
154
164
|
if !existing.healthy?
|
155
|
-
@members.delete
|
165
|
+
@members.delete(existing)
|
156
166
|
else
|
157
167
|
next
|
158
168
|
end
|
159
169
|
else
|
160
170
|
existing.close
|
161
|
-
@members.delete
|
171
|
+
@members.delete(existing)
|
162
172
|
end
|
163
173
|
end
|
164
174
|
|
@@ -242,11 +252,19 @@ module Mongo
|
|
242
252
|
"#{@seeds.map {|s| "#{s[0]}:#{s[1]}" }.join(', ')}"
|
243
253
|
end
|
244
254
|
|
245
|
-
private
|
246
|
-
|
247
255
|
def discovered_seeds
|
248
256
|
@members.map(&:host_port)
|
249
257
|
end
|
250
258
|
|
259
|
+
def copy_members
|
260
|
+
members = Set.new
|
261
|
+
@connect_mutex.synchronize do
|
262
|
+
@members.map do |m|
|
263
|
+
members << m.dup
|
264
|
+
end
|
265
|
+
end
|
266
|
+
members
|
267
|
+
end
|
268
|
+
|
251
269
|
end
|
252
270
|
end
|
@@ -9,11 +9,11 @@ module Mongo
|
|
9
9
|
]
|
10
10
|
|
11
11
|
MONGOS_MODES = {
|
12
|
-
:primary =>
|
13
|
-
:primary_preferred =>
|
14
|
-
:secondary =>
|
15
|
-
:secondary_preferred =>
|
16
|
-
:nearest =>
|
12
|
+
:primary => 'primary',
|
13
|
+
:primary_preferred => 'primaryPreferred',
|
14
|
+
:secondary => 'secondary',
|
15
|
+
:secondary_preferred => 'secondaryPreferred',
|
16
|
+
:nearest => 'nearest'
|
17
17
|
}
|
18
18
|
|
19
19
|
def self.mongos(mode, tag_sets)
|
@@ -77,7 +77,7 @@ module Mongo
|
|
77
77
|
when :secondary_preferred
|
78
78
|
select_secondary_pool(secondary_pools, read_pref) || primary_pool
|
79
79
|
when :nearest
|
80
|
-
|
80
|
+
select_near_pool(pools, read_pref)
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
@@ -12,30 +12,43 @@ module Mongo
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def connect
|
15
|
-
@
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
@connect_mutex.synchronize do
|
16
|
+
begin
|
17
|
+
thread_local[:locks][:connecting_manager] = true
|
18
|
+
@refresh_required = false
|
19
|
+
disconnect_old_members
|
20
|
+
connect_to_members
|
21
|
+
initialize_pools best(@members)
|
22
|
+
update_max_sizes
|
23
|
+
@seeds = discovered_seeds
|
24
|
+
ensure
|
25
|
+
thread_local[:locks][:connecting_manager] = false
|
26
|
+
end
|
27
|
+
end
|
20
28
|
end
|
21
29
|
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
30
|
+
# Checks that each node is healthy (via check_is_master) and that each
|
31
|
+
# node is in fact a mongos. If either criteria are not true, a refresh is
|
32
|
+
# set to be triggered and close() is called on the node.
|
33
|
+
#
|
34
|
+
# @return [Boolean] indicating if a refresh is required.
|
27
35
|
def check_connection_health
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
36
|
+
@refresh_required = false
|
37
|
+
@members.each do |member|
|
38
|
+
begin
|
39
|
+
config = @client.check_is_master([member.host, member.port])
|
40
|
+
unless config && config.has_key?('msg')
|
41
|
+
@refresh_required = true
|
42
|
+
member.close
|
43
|
+
end
|
44
|
+
rescue OperationTimeout
|
34
45
|
@refresh_required = true
|
46
|
+
member.close
|
35
47
|
end
|
36
|
-
|
37
|
-
@refresh_required = true
|
48
|
+
break if @refresh_required
|
38
49
|
end
|
50
|
+
@refresh_required
|
39
51
|
end
|
52
|
+
|
40
53
|
end
|
41
54
|
end
|
@@ -8,11 +8,8 @@ class ReplicaSetAuthenticationTest < Test::Unit::TestCase
|
|
8
8
|
def setup
|
9
9
|
ensure_cluster(:rs)
|
10
10
|
@client = MongoReplicaSetClient.new(@rs.repl_set_seeds, :name => @rs.repl_set_name, :connect_timeout => 60)
|
11
|
-
@db
|
12
|
-
|
13
|
-
|
14
|
-
def teardown
|
15
|
-
@db['system.users'].remove
|
11
|
+
@db = @client[MONGO_TEST_DB]
|
12
|
+
init_auth
|
16
13
|
end
|
17
14
|
|
18
15
|
def test_authenticate_with_connection_uri
|
@@ -11,6 +11,21 @@ class ClientTest < Test::Unit::TestCase
|
|
11
11
|
@client.close if @client
|
12
12
|
end
|
13
13
|
|
14
|
+
def test_reconnection
|
15
|
+
@client = MongoReplicaSetClient.new @rs.repl_set_seeds
|
16
|
+
assert @client.connected?
|
17
|
+
|
18
|
+
manager = @client.local_manager
|
19
|
+
|
20
|
+
@client.close
|
21
|
+
assert !@client.connected?
|
22
|
+
assert !@client.local_manager
|
23
|
+
|
24
|
+
@client.connect
|
25
|
+
assert @client.connected?
|
26
|
+
assert_equal @client.local_manager, manager
|
27
|
+
end
|
28
|
+
|
14
29
|
# TODO: test connect timeout.
|
15
30
|
|
16
31
|
def test_connect_with_deprecated_multi
|
@@ -7,6 +7,12 @@ class MaxValuesTest < Test::Unit::TestCase
|
|
7
7
|
def setup
|
8
8
|
ensure_cluster(:rs)
|
9
9
|
@client = MongoReplicaSetClient.new(@rs.repl_set_seeds, :name => @rs.repl_set_name)
|
10
|
+
@db = new_mock_db
|
11
|
+
@client.stubs(:[]).returns(@db)
|
12
|
+
@ismaster = {
|
13
|
+
'hosts' => @client.local_manager.hosts.to_a,
|
14
|
+
'arbiters' => @client.local_manager.arbiters
|
15
|
+
}
|
10
16
|
end
|
11
17
|
|
12
18
|
def test_initial_max_sizes
|
@@ -15,43 +21,52 @@ class MaxValuesTest < Test::Unit::TestCase
|
|
15
21
|
end
|
16
22
|
|
17
23
|
def test_updated_max_sizes_after_node_config_change
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
24
|
+
@db.stubs(:command).returns(
|
25
|
+
@ismaster.merge({'ismaster' => true}),
|
26
|
+
@ismaster.merge({'secondary' => true, 'maxMessageSizeBytes' => 1024 * MESSAGE_SIZE_FACTOR}),
|
27
|
+
@ismaster.merge({'secondary' => true, 'maxBsonObjectSize' => 1024})
|
28
|
+
)
|
29
|
+
@client.local_manager.stubs(:refresh_required?).returns(true)
|
30
|
+
@client.refresh
|
25
31
|
|
26
32
|
assert_equal 1024, @client.max_bson_size
|
27
33
|
assert_equal 1024 * MESSAGE_SIZE_FACTOR, @client.max_message_size
|
28
34
|
end
|
29
35
|
|
30
36
|
def test_neither_max_sizes_in_config
|
31
|
-
@
|
32
|
-
|
33
|
-
|
34
|
-
|
37
|
+
@db.stubs(:command).returns(
|
38
|
+
@ismaster.merge({'ismaster' => true}),
|
39
|
+
@ismaster.merge({'secondary' => true}),
|
40
|
+
@ismaster.merge({'secondary' => true})
|
41
|
+
)
|
42
|
+
@client.local_manager.stubs(:refresh_required?).returns(true)
|
43
|
+
@client.refresh
|
35
44
|
|
36
45
|
assert_equal DEFAULT_MAX_BSON_SIZE, @client.max_bson_size
|
37
46
|
assert_equal DEFAULT_MAX_BSON_SIZE * MESSAGE_SIZE_FACTOR, @client.max_message_size
|
38
47
|
end
|
39
48
|
|
40
49
|
def test_only_bson_size_in_config
|
41
|
-
@
|
42
|
-
|
43
|
-
|
44
|
-
|
50
|
+
@db.stubs(:command).returns(
|
51
|
+
@ismaster.merge({'ismaster' => true}),
|
52
|
+
@ismaster.merge({'secondary' => true}),
|
53
|
+
@ismaster.merge({'secondary' => true, 'maxBsonObjectSize' => 1024})
|
54
|
+
)
|
55
|
+
@client.local_manager.stubs(:refresh_required?).returns(true)
|
56
|
+
@client.refresh
|
57
|
+
|
45
58
|
assert_equal 1024, @client.max_bson_size
|
46
59
|
assert_equal 1024 * MESSAGE_SIZE_FACTOR, @client.max_message_size
|
47
60
|
end
|
48
61
|
|
49
62
|
def test_both_sizes_in_config
|
50
|
-
@
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
63
|
+
@db.stubs(:command).returns(
|
64
|
+
@ismaster.merge({'ismaster' => true, 'maxMessageSizeBytes' => 1024 * 2 * MESSAGE_SIZE_FACTOR, 'maxBsonObjectSize' => 1024}),
|
65
|
+
@ismaster.merge({'secondary' => true, 'maxMessageSizeBytes' => 1024 * 2 * MESSAGE_SIZE_FACTOR, 'maxBsonObjectSize' => 1024}),
|
66
|
+
@ismaster.merge({'secondary' => true, 'maxMessageSizeBytes' => 1024 * 2 * MESSAGE_SIZE_FACTOR, 'maxBsonObjectSize' => 1024})
|
67
|
+
)
|
68
|
+
@client.local_manager.stubs(:refresh_required?).returns(true)
|
69
|
+
@client.refresh
|
55
70
|
|
56
71
|
assert_equal 1024, @client.max_bson_size
|
57
72
|
assert_equal 1024 * 2 * MESSAGE_SIZE_FACTOR, @client.max_message_size
|
@@ -78,6 +78,37 @@ class ReplicaSetRefreshTest < Test::Unit::TestCase
|
|
78
78
|
"No secondaries have been added."
|
79
79
|
assert_equal num_secondaries, client.secondary_pools.size
|
80
80
|
end
|
81
|
+
|
82
|
+
def test_concurrent_refreshes
|
83
|
+
factor = 5
|
84
|
+
nthreads = factor * 10
|
85
|
+
threads = []
|
86
|
+
client = MongoReplicaSetClient.new(@rs.repl_set_seeds, :refresh_mode => :sync, :refresh_interval => 1)
|
87
|
+
|
88
|
+
nthreads.times do |i|
|
89
|
+
threads << Thread.new do
|
90
|
+
# force a connection failure every couple of threads that causes a refresh
|
91
|
+
if i % factor == 0
|
92
|
+
cursor = client['foo']['bar'].find
|
93
|
+
cursor.stubs(:checkout_socket_from_connection).raises(ConnectionFailure)
|
94
|
+
begin
|
95
|
+
cursor.next
|
96
|
+
rescue => ex
|
97
|
+
raise ex unless ex.class == ConnectionFailure
|
98
|
+
next
|
99
|
+
end
|
100
|
+
else
|
101
|
+
# synchronous refreshes will happen every couple of find_ones
|
102
|
+
cursor = client['foo']['bar'].find_one
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
threads.each do |t|
|
108
|
+
t.join
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
81
112
|
=begin
|
82
113
|
def test_automated_refresh_with_removed_node
|
83
114
|
client = MongoReplicaSetClient.new(@rs.repl_set_seeds,
|
@@ -36,7 +36,7 @@ class BasicTest < Test::Unit::TestCase
|
|
36
36
|
@client = MongoClient.new(host, port, {:read => :secondary, :tag_sets => tags})
|
37
37
|
assert @client.connected?
|
38
38
|
cursor = Cursor.new(@client[MONGO_TEST_DB]['whatever'], {})
|
39
|
-
assert_equal cursor.construct_query_spec['$readPreference'], {:mode =>
|
39
|
+
assert_equal cursor.construct_query_spec['$readPreference'], {:mode => 'secondary', :tags => tags}
|
40
40
|
end
|
41
41
|
|
42
42
|
def test_find_one_with_read_secondary
|
@@ -68,7 +68,7 @@ class BasicTest < Test::Unit::TestCase
|
|
68
68
|
@client = MongoShardedClient.new(@seeds, {:read => :secondary, :tag_sets => tags})
|
69
69
|
assert @client.connected?
|
70
70
|
cursor = Cursor.new(@client[MONGO_TEST_DB]['whatever'], {})
|
71
|
-
assert_equal cursor.construct_query_spec['$readPreference'], {:mode =>
|
71
|
+
assert_equal cursor.construct_query_spec['$readPreference'], {:mode => 'secondary', :tags => tags}
|
72
72
|
end
|
73
73
|
|
74
74
|
def test_hard_refresh
|
@@ -1,4 +1,21 @@
|
|
1
1
|
module AuthenticationTests
|
2
|
+
|
3
|
+
def init_auth
|
4
|
+
# enable authentication by creating and logging in as admin user
|
5
|
+
@admin = @client['admin']
|
6
|
+
@admin.add_user('admin', 'password')
|
7
|
+
@admin.authenticate('admin', 'password')
|
8
|
+
end
|
9
|
+
|
10
|
+
def teardown
|
11
|
+
@admin.logout
|
12
|
+
@admin.authenticate('admin','password')
|
13
|
+
@admin['system.users'].remove
|
14
|
+
@db['system.users'].remove
|
15
|
+
@db['test'].remove
|
16
|
+
@admin.logout
|
17
|
+
end
|
18
|
+
|
2
19
|
def test_add_user
|
3
20
|
@db.add_user('bob','user')
|
4
21
|
assert @db['system.users'].find_one({:user => 'bob'})
|
data/test/test_helper.rb
CHANGED
@@ -1,4 +1,10 @@
|
|
1
|
-
|
1
|
+
begin
|
2
|
+
require 'pry-rescue'
|
3
|
+
require 'pry-nav'
|
4
|
+
rescue LoadError
|
5
|
+
# failed to load, skipping pry
|
6
|
+
end
|
7
|
+
|
2
8
|
# SimpleCov must load before our code - A coverage report summary line will print after each test suite
|
3
9
|
if RUBY_VERSION >= '1.9.0' && RUBY_ENGINE == 'ruby'
|
4
10
|
if ENV.key?('COVERAGE')
|
data/test/tools/mongo_config.rb
CHANGED
@@ -35,7 +35,7 @@ module Mongo
|
|
35
35
|
MONGODS_OPT_KEYS = [:mongods]
|
36
36
|
CLUSTER_OPT_KEYS = SHARDING_OPT_KEYS + REPLICA_OPT_KEYS + MONGODS_OPT_KEYS
|
37
37
|
|
38
|
-
FLAGS = [:noprealloc, :smallfiles, :logappend, :configsvr, :shardsvr, :quiet, :fastsync]
|
38
|
+
FLAGS = [:noprealloc, :smallfiles, :logappend, :configsvr, :shardsvr, :quiet, :fastsync, :auth]
|
39
39
|
|
40
40
|
DEFAULT_VERIFIES = 60
|
41
41
|
BASE_PORT = 3000
|
@@ -108,18 +108,24 @@ module Mongo
|
|
108
108
|
:smallfiles => smallfiles,
|
109
109
|
:noprealloc => noprealloc,
|
110
110
|
:quiet => quiet,
|
111
|
-
:fastsync => fast_sync
|
111
|
+
:fastsync => fast_sync,
|
112
|
+
:auth => auth)
|
112
113
|
end
|
113
114
|
|
114
|
-
def self.make_replica(opts,
|
115
|
+
def self.make_replica(opts, id)
|
115
116
|
params = make_mongod('replicas', opts)
|
116
117
|
|
117
118
|
replSet = opts[:replSet] || 'ruby-driver-test'
|
118
|
-
|
119
|
+
oplogSize = opts[:oplog_size] || 5
|
120
|
+
keyFile = opts[:key_file] || '/test/tools/keyfile.txt'
|
119
121
|
|
120
|
-
|
122
|
+
keyFile = Dir.pwd << keyFile
|
123
|
+
system "chmod 600 #{keyFile}"
|
124
|
+
|
125
|
+
params.merge(:_id => id,
|
121
126
|
:replSet => replSet,
|
122
|
-
:oplogSize =>
|
127
|
+
:oplogSize => oplogSize,
|
128
|
+
:keyFile => keyFile)
|
123
129
|
end
|
124
130
|
|
125
131
|
def self.make_config(opts)
|
@@ -187,7 +193,7 @@ module Mongo
|
|
187
193
|
if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
|
188
194
|
@pid = Process.spawn(*@cmd)
|
189
195
|
else
|
190
|
-
cmd_and_opts = [@cmd, {:out =>
|
196
|
+
cmd_and_opts = [@cmd, {:out => '/dev/null'}].flatten
|
191
197
|
@pid = Process.spawn(*cmd_and_opts)
|
192
198
|
end
|
193
199
|
verify(verifies) if verifies > 0
|
data/test/unit/cursor_test.rb
CHANGED
@@ -124,7 +124,7 @@ class CursorTest < Test::Unit::TestCase
|
|
124
124
|
|
125
125
|
spec = cursor.construct_query_spec
|
126
126
|
assert spec.has_key?('$readPreference')
|
127
|
-
assert_equal
|
127
|
+
assert_equal 'secondary', spec['$readPreference'][:mode]
|
128
128
|
assert !spec['$readPreference'].has_key?(:tags)
|
129
129
|
|
130
130
|
# secondary preferred with tags
|
@@ -132,7 +132,7 @@ class CursorTest < Test::Unit::TestCase
|
|
132
132
|
|
133
133
|
spec = cursor.construct_query_spec
|
134
134
|
assert spec.has_key?('$readPreference')
|
135
|
-
assert_equal
|
135
|
+
assert_equal 'secondaryPreferred', spec['$readPreference'][:mode]
|
136
136
|
assert_equal @tag_sets, spec['$readPreference'][:tags]
|
137
137
|
|
138
138
|
# primary preferred
|
@@ -140,7 +140,7 @@ class CursorTest < Test::Unit::TestCase
|
|
140
140
|
|
141
141
|
spec = cursor.construct_query_spec
|
142
142
|
assert spec.has_key?('$readPreference')
|
143
|
-
assert_equal
|
143
|
+
assert_equal 'primaryPreferred', spec['$readPreference'][:mode]
|
144
144
|
assert !spec['$readPreference'].has_key?(:tags)
|
145
145
|
|
146
146
|
# primary preferred with tags
|
@@ -148,7 +148,7 @@ class CursorTest < Test::Unit::TestCase
|
|
148
148
|
|
149
149
|
spec = cursor.construct_query_spec
|
150
150
|
assert spec.has_key?('$readPreference')
|
151
|
-
assert_equal
|
151
|
+
assert_equal 'primaryPreferred', spec['$readPreference'][:mode]
|
152
152
|
assert_equal @tag_sets, spec['$readPreference'][:tags]
|
153
153
|
|
154
154
|
# nearest
|
@@ -156,7 +156,7 @@ class CursorTest < Test::Unit::TestCase
|
|
156
156
|
|
157
157
|
spec = cursor.construct_query_spec
|
158
158
|
assert spec.has_key?('$readPreference')
|
159
|
-
assert_equal
|
159
|
+
assert_equal 'nearest', spec['$readPreference'][:mode]
|
160
160
|
assert !spec['$readPreference'].has_key?(:tags)
|
161
161
|
|
162
162
|
# nearest with tags
|
@@ -164,7 +164,7 @@ class CursorTest < Test::Unit::TestCase
|
|
164
164
|
|
165
165
|
spec = cursor.construct_query_spec
|
166
166
|
assert spec.has_key?('$readPreference')
|
167
|
-
assert_equal
|
167
|
+
assert_equal 'nearest', spec['$readPreference'][:mode]
|
168
168
|
assert_equal @tag_sets, spec['$readPreference'][:tags]
|
169
169
|
end
|
170
170
|
|
@@ -9,24 +9,24 @@ class MongoShardedClientTest < Test::Unit::TestCase
|
|
9
9
|
|
10
10
|
def test_initialize_with_single_mongos_uri
|
11
11
|
ENV["MONGODB_URI"] = "mongodb://localhost:27017"
|
12
|
-
client = MongoShardedClient.new
|
12
|
+
client = MongoShardedClient.new(:connect => false)
|
13
13
|
assert_equal [[ "localhost", 27017 ]], client.seeds
|
14
14
|
end
|
15
15
|
|
16
16
|
def test_initialize_with_multiple_mongos_uris
|
17
17
|
ENV["MONGODB_URI"] = "mongodb://localhost:27017,localhost:27018"
|
18
|
-
client = MongoShardedClient.new
|
18
|
+
client = MongoShardedClient.new(:connect => false)
|
19
19
|
assert_equal [[ "localhost", 27017 ], [ "localhost", 27018 ]], client.seeds
|
20
20
|
end
|
21
21
|
|
22
22
|
def test_from_uri_with_string
|
23
|
-
client = MongoShardedClient.from_uri("mongodb://localhost:27017,localhost:27018")
|
23
|
+
client = MongoShardedClient.from_uri("mongodb://localhost:27017,localhost:27018", :connect => false)
|
24
24
|
assert_equal [[ "localhost", 27017 ], [ "localhost", 27018 ]], client.seeds
|
25
25
|
end
|
26
26
|
|
27
27
|
def test_from_uri_with_env_variable
|
28
28
|
ENV["MONGODB_URI"] = "mongodb://localhost:27017,localhost:27018"
|
29
|
-
client = MongoShardedClient.from_uri
|
29
|
+
client = MongoShardedClient.from_uri(nil, :connect => false)
|
30
30
|
assert_equal [[ "localhost", 27017 ], [ "localhost", 27018 ]], client.seeds
|
31
31
|
end
|
32
32
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ReadPrefTest < Test::Unit::TestCase
|
4
|
+
include ReadPreference
|
5
|
+
|
6
|
+
def setup
|
7
|
+
mock_pool = mock()
|
8
|
+
mock_pool.stubs(:ping_time).returns(Pool::MAX_PING_TIME)
|
9
|
+
|
10
|
+
stubs(:primary_pool).returns(mock_pool)
|
11
|
+
stubs(:secondary_pools).returns([mock_pool])
|
12
|
+
stubs(:pools).returns([mock_pool])
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_select_pool
|
16
|
+
ReadPreference::READ_PREFERENCES.map do |rp|
|
17
|
+
assert select_pool({:mode => rp, :tags => [], :latency => 15})
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -59,30 +59,5 @@ class ShardingPoolManagerTest < Test::Unit::TestCase
|
|
59
59
|
assert_equal 500, manager.max_bson_size
|
60
60
|
assert_equal 700 , manager.max_message_size
|
61
61
|
end
|
62
|
-
|
63
|
-
should "maintain seed format when checking connection health" do
|
64
|
-
|
65
|
-
@db.stubs(:command).returns(
|
66
|
-
# First call to get a socket.
|
67
|
-
@ismaster.merge({'ismaster' => true}),
|
68
|
-
|
69
|
-
# Subsequent calls to configure pools.
|
70
|
-
@ismaster.merge({'ismaster' => true}),
|
71
|
-
@ismaster.merge({'secondary' => true, 'maxMessageSizeBytes' => 700}),
|
72
|
-
@ismaster.merge({'secondary' => true, 'maxBsonObjectSize' => 500}),
|
73
|
-
@ismaster.merge({'arbiterOnly' => true})
|
74
|
-
)
|
75
|
-
|
76
|
-
config_db = new_mock_db
|
77
|
-
mongos_coll = mock('collection')
|
78
|
-
mongos_coll.stubs(:find).returns(@hosts.map{|h| {'_id' => h}})
|
79
|
-
config_db.stubs(:[]).with('mongos').returns(mongos_coll)
|
80
|
-
@client.stubs(:[]).with('config').returns(config_db)
|
81
|
-
|
82
|
-
manager = Mongo::ShardingPoolManager.new(@client, @hosts)
|
83
|
-
manager.check_connection_health
|
84
|
-
|
85
|
-
assert manager.seeds.all? {|s| s.is_a?(Array) && s[0].is_a?(String) && s[1].is_a?(Integer)}
|
86
|
-
end
|
87
62
|
end
|
88
63
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.8.
|
4
|
+
version: 1.8.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tyler Brock
|
@@ -33,7 +33,7 @@ cert_chain:
|
|
33
33
|
8v7zLF2XliYbfurYIwkcXs8yPn8ggApBIy9bX6VJxRs/l2+UvqzaHIFaFy/F8/GP
|
34
34
|
RNTuXsVG5NDACo7Q
|
35
35
|
-----END CERTIFICATE-----
|
36
|
-
date: 2013-
|
36
|
+
date: 2013-05-16 00:00:00.000000000 Z
|
37
37
|
dependencies:
|
38
38
|
- !ruby/object:Gem::Dependency
|
39
39
|
name: bson
|
@@ -41,14 +41,14 @@ dependencies:
|
|
41
41
|
requirements:
|
42
42
|
- - ~>
|
43
43
|
- !ruby/object:Gem::Version
|
44
|
-
version: 1.8.
|
44
|
+
version: 1.8.6
|
45
45
|
type: :runtime
|
46
46
|
prerelease: false
|
47
47
|
version_requirements: !ruby/object:Gem::Requirement
|
48
48
|
requirements:
|
49
49
|
- - ~>
|
50
50
|
- !ruby/object:Gem::Version
|
51
|
-
version: 1.8.
|
51
|
+
version: 1.8.6
|
52
52
|
description: A Ruby driver for MongoDB. For more information about Mongo, see http://www.mongodb.org.
|
53
53
|
email: mongodb-dev@googlegroups.com
|
54
54
|
executables:
|
@@ -143,6 +143,7 @@ files:
|
|
143
143
|
- test/unit/node_test.rb
|
144
144
|
- test/unit/pool_manager_test.rb
|
145
145
|
- test/unit/pool_test.rb
|
146
|
+
- test/unit/read_pref_test.rb
|
146
147
|
- test/unit/read_test.rb
|
147
148
|
- test/unit/safe_test.rb
|
148
149
|
- test/unit/sharding_pool_manager_test.rb
|
@@ -223,6 +224,7 @@ test_files:
|
|
223
224
|
- test/unit/node_test.rb
|
224
225
|
- test/unit/pool_manager_test.rb
|
225
226
|
- test/unit/pool_test.rb
|
227
|
+
- test/unit/read_pref_test.rb
|
226
228
|
- test/unit/read_test.rb
|
227
229
|
- test/unit/safe_test.rb
|
228
230
|
- test/unit/sharding_pool_manager_test.rb
|
metadata.gz.sig
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
;cJ�g����H�#~������Ç���������J�.�۞(T�.7{��<�!����:ݬ���T;�S���RJ��y��A��x��D8ʒ�=k���nL7�пk�Y�[>�����1*+>)5� ���i�qJ3��^*q&��f��
|