moped 2.0.0.beta3 → 2.0.0.beta4
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of moped might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/moped/authenticatable.rb +17 -8
- data/lib/moped/cluster.rb +38 -5
- data/lib/moped/connection/manager.rb +35 -2
- data/lib/moped/connection.rb +2 -4
- data/lib/moped/database.rb +2 -2
- data/lib/moped/failover/retry.rb +3 -1
- data/lib/moped/node.rb +61 -51
- data/lib/moped/operation/read.rb +1 -6
- data/lib/moped/protocol/reply.rb +1 -1
- data/lib/moped/query.rb +11 -0
- data/lib/moped/session.rb +12 -2
- data/lib/moped/version.rb +1 -1
- metadata +21 -10
- data/lib/moped/connection/pool.rb +0 -198
- data/lib/moped/connection/queue.rb +0 -93
- data/lib/moped/connection/reaper.rb +0 -52
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dcc02534c2e5692e3ec6ec5d413a84affae01928
|
4
|
+
data.tar.gz: 9f68b061f00712169ab5b0ff7cab3013bb70275d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c4e346563b648daf55642a42cd4df9292848bd03cc87f31edfca2f5f5661a3a884ed97fe064a0355325bbde151cac169d00a4bf24b074ad173bff2efbcf8bb1c
|
7
|
+
data.tar.gz: e476c83c7abc0d42e73629962457cc8403658e645ae7ee62ad2041659a69745172861793db667eeef781b45015a175a9ecea4c7d88fa5cae31321bbbbc365472
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Moped [![Build Status](https://secure.travis-ci.org/mongoid/moped.png?branch=master
|
1
|
+
Moped [![Build Status](https://secure.travis-ci.org/mongoid/moped.png?branch=master)](http://travis-ci.org/mongoid/moped) [![Code Climate](https://codeclimate.com/github/mongoid/moped.png)](https://codeclimate.com/github/mongoid/moped) [![Coverage Status](https://coveralls.io/repos/mongoid/moped/badge.png?branch=master)](https://coveralls.io/r/mongoid/moped?branch=master)
|
2
2
|
========
|
3
3
|
|
4
4
|
Moped is a MongoDB driver for Ruby, which exposes a simple, elegant, and fast
|
@@ -60,14 +60,19 @@ module Moped
|
|
60
60
|
# @since 2.0.0
|
61
61
|
def login(database, username, password)
|
62
62
|
getnonce = Protocol::Command.new(database, getnonce: 1)
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
document = conn.read.documents.first
|
68
|
-
raise Errors::AuthenticationFailure.new(authenticate, document) unless document["ok"] == 1
|
69
|
-
credentials[database] = [username, password]
|
63
|
+
self.write([getnonce])
|
64
|
+
reply = self.receive_replies([getnonce]).first
|
65
|
+
if getnonce.failure?(reply)
|
66
|
+
return
|
70
67
|
end
|
68
|
+
result = getnonce.results(reply)
|
69
|
+
|
70
|
+
authenticate = Protocol::Commands::Authenticate.new(database, username, password, result["nonce"])
|
71
|
+
self.write([ authenticate ])
|
72
|
+
document = self.read.documents.first
|
73
|
+
|
74
|
+
raise Errors::AuthenticationFailure.new(authenticate, document) unless document["ok"] == 1
|
75
|
+
credentials[database] = [username, password]
|
71
76
|
end
|
72
77
|
|
73
78
|
# Logout the user from the provided database.
|
@@ -82,7 +87,11 @@ module Moped
|
|
82
87
|
# @since 2.0.0
|
83
88
|
def logout(database)
|
84
89
|
command = Protocol::Command.new(database, logout: 1)
|
85
|
-
|
90
|
+
self.write([command])
|
91
|
+
reply = self.receive_replies([command]).first
|
92
|
+
if command.failure?(reply)
|
93
|
+
return
|
94
|
+
end
|
86
95
|
credentials.delete(database)
|
87
96
|
end
|
88
97
|
end
|
data/lib/moped/cluster.rb
CHANGED
@@ -32,16 +32,32 @@ module Moped
|
|
32
32
|
# @return [ Array<Node> ] The seed nodes.
|
33
33
|
attr_reader :options, :peers, :seeds
|
34
34
|
|
35
|
-
#
|
35
|
+
# Add a credential to the cluster
|
36
36
|
#
|
37
37
|
# @example Get the applied credentials.
|
38
38
|
# node.credentials
|
39
39
|
#
|
40
|
-
# @return [
|
40
|
+
# @return [ Boolean ] true
|
41
41
|
#
|
42
42
|
# @since 2.0.0
|
43
|
-
def
|
43
|
+
def add_credential(db, username, password)
|
44
44
|
@credentials ||= {}
|
45
|
+
@credentials[db] = [ username, password ]
|
46
|
+
apply_credentials
|
47
|
+
end
|
48
|
+
|
49
|
+
# Remove a credential from the cluster
|
50
|
+
#
|
51
|
+
# @example Get the applied credentials.
|
52
|
+
# node.delete_credential(database_name)
|
53
|
+
#
|
54
|
+
# @return [ Boolean ] true
|
55
|
+
#
|
56
|
+
# @since 2.0.0
|
57
|
+
def delete_credential(db)
|
58
|
+
return true unless @credentials
|
59
|
+
@credentials.delete(db)
|
60
|
+
apply_credentials
|
45
61
|
end
|
46
62
|
|
47
63
|
# Disconnects all nodes in the cluster. This should only be used in cases
|
@@ -224,7 +240,7 @@ module Moped
|
|
224
240
|
if node = nodes.find(&:primary?)
|
225
241
|
begin
|
226
242
|
node.ensure_primary do
|
227
|
-
return yield(node
|
243
|
+
return yield(node)
|
228
244
|
end
|
229
245
|
rescue Errors::ConnectionFailure, Errors::ReplicaSetReconfigured
|
230
246
|
end
|
@@ -251,7 +267,7 @@ module Moped
|
|
251
267
|
available_nodes = nodes.select(&:secondary?).shuffle!
|
252
268
|
while node = available_nodes.shift
|
253
269
|
begin
|
254
|
-
return yield(node
|
270
|
+
return yield(node)
|
255
271
|
rescue Errors::ConnectionFailure => e
|
256
272
|
next
|
257
273
|
end
|
@@ -261,6 +277,23 @@ module Moped
|
|
261
277
|
|
262
278
|
private
|
263
279
|
|
280
|
+
# Apply the credentials on all nodes
|
281
|
+
#
|
282
|
+
# @api private
|
283
|
+
#
|
284
|
+
# @example Apply the credentials.
|
285
|
+
# cluster.apply_credentials
|
286
|
+
#
|
287
|
+
# @return [ Boolean ] True
|
288
|
+
#
|
289
|
+
# @since 2.0.0
|
290
|
+
def apply_credentials
|
291
|
+
seeds.each do |node|
|
292
|
+
node.credentials = @credentials || {}
|
293
|
+
end
|
294
|
+
true
|
295
|
+
end
|
296
|
+
|
264
297
|
# Get the boundary where a node that is down would need to be refreshed.
|
265
298
|
#
|
266
299
|
# @api private
|
@@ -1,4 +1,6 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
require "connection_pool"
|
3
|
+
|
2
4
|
module Moped
|
3
5
|
class Connection
|
4
6
|
|
@@ -11,6 +13,12 @@ module Moped
|
|
11
13
|
# Used for synchronization of pools access.
|
12
14
|
MUTEX = Mutex.new
|
13
15
|
|
16
|
+
# The default max size for the connection pool.
|
17
|
+
POOL_SIZE = 5
|
18
|
+
|
19
|
+
# The default timeout for getting connections from the queue.
|
20
|
+
TIMEOUT = 0.5
|
21
|
+
|
14
22
|
# Get a connection pool for the provided node.
|
15
23
|
#
|
16
24
|
# @example Get a connection pool for the node.
|
@@ -23,13 +31,38 @@ module Moped
|
|
23
31
|
# @since 2.0.0
|
24
32
|
def pool(node)
|
25
33
|
MUTEX.synchronize do
|
26
|
-
pools[node.address.resolved] ||=
|
27
|
-
Pool.new(node.address.ip, node.address.port, node.options)
|
34
|
+
pools[node.address.resolved] ||= create_pool(node)
|
28
35
|
end
|
29
36
|
end
|
30
37
|
|
31
38
|
private
|
32
39
|
|
40
|
+
# Create a new connection pool for the provided node.
|
41
|
+
#
|
42
|
+
# @api private
|
43
|
+
#
|
44
|
+
# @example Get a connection pool for the node.
|
45
|
+
# Manager.create_pool(node)
|
46
|
+
#
|
47
|
+
# @param [ Node ] node The node.
|
48
|
+
#
|
49
|
+
# @return [ ConnectionPool ] A connection pool.
|
50
|
+
#
|
51
|
+
# @since 2.0.0
|
52
|
+
def create_pool(node)
|
53
|
+
ConnectionPool.new(
|
54
|
+
size: node.options[:pool_size] || POOL_SIZE,
|
55
|
+
timeout: node.options[:pool_timeout] || TIMEOUT
|
56
|
+
) do
|
57
|
+
Connection.new(
|
58
|
+
node.address.ip,
|
59
|
+
node.address.port,
|
60
|
+
node.options[:timeout] || Connection::TIMEOUT,
|
61
|
+
node.options
|
62
|
+
)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
33
66
|
# Get all the connection pools. This is a cache that stores each pool
|
34
67
|
# with lookup by it's resolved address.
|
35
68
|
#
|
data/lib/moped/connection.rb
CHANGED
@@ -1,8 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
require "moped/connection/manager"
|
3
|
-
require "moped/connection/pool"
|
4
|
-
require "moped/connection/queue"
|
5
|
-
require "moped/connection/reaper"
|
6
3
|
require "moped/connection/sockets"
|
7
4
|
|
8
5
|
module Moped
|
@@ -11,6 +8,7 @@ module Moped
|
|
11
8
|
#
|
12
9
|
# @since 2.0.0
|
13
10
|
class Connection
|
11
|
+
include Authenticatable
|
14
12
|
|
15
13
|
# The default connection timeout, in seconds.
|
16
14
|
#
|
@@ -170,7 +168,7 @@ module Moped
|
|
170
168
|
sock_read = read_data(socket, reply.length - 36)
|
171
169
|
buffer = StringIO.new(sock_read)
|
172
170
|
reply.documents = reply.count.times.map do
|
173
|
-
BSON::Document.from_bson(buffer)
|
171
|
+
::BSON::Document.from_bson(buffer)
|
174
172
|
end
|
175
173
|
end
|
176
174
|
reply
|
data/lib/moped/database.rb
CHANGED
@@ -112,7 +112,7 @@ module Moped
|
|
112
112
|
#
|
113
113
|
# @since 1.0.0
|
114
114
|
def login(username, password)
|
115
|
-
cluster.
|
115
|
+
cluster.add_credential(name, username, password)
|
116
116
|
end
|
117
117
|
|
118
118
|
# Log out from the current database.
|
@@ -122,7 +122,7 @@ module Moped
|
|
122
122
|
#
|
123
123
|
# @since 1.0.0
|
124
124
|
def logout
|
125
|
-
cluster.
|
125
|
+
cluster.delete_credential(name)
|
126
126
|
end
|
127
127
|
end
|
128
128
|
end
|
data/lib/moped/failover/retry.rb
CHANGED
data/lib/moped/node.rb
CHANGED
@@ -13,7 +13,6 @@ module Moped
|
|
13
13
|
#
|
14
14
|
# @since 1.0.0
|
15
15
|
class Node
|
16
|
-
include Authenticatable
|
17
16
|
include Executable
|
18
17
|
include Instrumentable
|
19
18
|
|
@@ -29,6 +28,10 @@ module Moped
|
|
29
28
|
# @return [ Time ] The last time the node did a refresh.
|
30
29
|
attr_reader :address, :down_at, :latency, :options, :refreshed_at
|
31
30
|
|
31
|
+
# @!attribute credentials
|
32
|
+
# @return [ Hash ] The credentials of the node.
|
33
|
+
attr_accessor :credentials
|
34
|
+
|
32
35
|
# Is this node equal to another?
|
33
36
|
#
|
34
37
|
# @example Is the node equal to another.
|
@@ -87,24 +90,6 @@ module Moped
|
|
87
90
|
read(Protocol::Command.new(database, cmd, options))
|
88
91
|
end
|
89
92
|
|
90
|
-
# Connect the node on the underlying connection.
|
91
|
-
#
|
92
|
-
# @example Connect the node.
|
93
|
-
# node.connect
|
94
|
-
#
|
95
|
-
# @raise [ Errors::ConnectionFailure ] If connection failed.
|
96
|
-
#
|
97
|
-
# @return [ true ] If the connection suceeded.
|
98
|
-
#
|
99
|
-
# @since 2.0.0
|
100
|
-
def connect
|
101
|
-
start = Time.now
|
102
|
-
connection{ |conn| conn.connect }
|
103
|
-
@latency = Time.now - start
|
104
|
-
@down_at = nil
|
105
|
-
true
|
106
|
-
end
|
107
|
-
|
108
93
|
# Is the node currently connected?
|
109
94
|
#
|
110
95
|
# @example Is the node connected?
|
@@ -126,11 +111,23 @@ module Moped
|
|
126
111
|
#
|
127
112
|
# @since 2.0.0
|
128
113
|
def connection
|
129
|
-
pool.
|
114
|
+
pool.with do |conn|
|
130
115
|
yield(conn)
|
131
116
|
end
|
132
117
|
end
|
133
118
|
|
119
|
+
# Is the node down?
|
120
|
+
#
|
121
|
+
# @example Is the node down?
|
122
|
+
# node.down?
|
123
|
+
#
|
124
|
+
# @return [ Time, nil ] The time the node went down, or nil if up.
|
125
|
+
#
|
126
|
+
# @since 1.0.0
|
127
|
+
def down?
|
128
|
+
@down_at
|
129
|
+
end
|
130
|
+
|
134
131
|
# Force the node to disconnect from the server.
|
135
132
|
#
|
136
133
|
# @example Disconnect the node.
|
@@ -140,23 +137,11 @@ module Moped
|
|
140
137
|
#
|
141
138
|
# @since 1.2.0
|
142
139
|
def disconnect
|
143
|
-
credentials.clear
|
140
|
+
@credentials.clear
|
144
141
|
connection{ |conn| conn.disconnect }
|
145
142
|
true
|
146
143
|
end
|
147
144
|
|
148
|
-
# Is the node down?
|
149
|
-
#
|
150
|
-
# @example Is the node down?
|
151
|
-
# node.down?
|
152
|
-
#
|
153
|
-
# @return [ Time, nil ] The time the node went down, or nil if up.
|
154
|
-
#
|
155
|
-
# @since 1.0.0
|
156
|
-
def down?
|
157
|
-
@down_at
|
158
|
-
end
|
159
|
-
|
160
145
|
# Mark the node as down.
|
161
146
|
#
|
162
147
|
# @example Mark the node as down.
|
@@ -168,7 +153,7 @@ module Moped
|
|
168
153
|
def down!
|
169
154
|
@down_at = Time.new
|
170
155
|
@latency = nil
|
171
|
-
disconnect
|
156
|
+
disconnect
|
172
157
|
end
|
173
158
|
|
174
159
|
# Yields the block if a connection can be established, retrying when a
|
@@ -185,15 +170,23 @@ module Moped
|
|
185
170
|
#
|
186
171
|
# @since 1.0.0
|
187
172
|
def ensure_connected(&block)
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
173
|
+
unless (conn = stack(:connection)).empty?
|
174
|
+
return yield(conn.first)
|
175
|
+
end
|
176
|
+
|
177
|
+
begin
|
178
|
+
connection do |conn|
|
179
|
+
stack(:connection) << conn
|
180
|
+
connect(conn) unless conn.connected?
|
181
|
+
conn.apply_credentials(@credentials)
|
182
|
+
yield(conn)
|
195
183
|
end
|
184
|
+
rescue Exception => e
|
185
|
+
Failover.get(e).execute(e, self, &block)
|
186
|
+
ensure
|
187
|
+
end_execution(:connection)
|
196
188
|
end
|
189
|
+
|
197
190
|
end
|
198
191
|
|
199
192
|
# Set a flag on the node for the duration of provided block so that an
|
@@ -259,6 +252,7 @@ module Moped
|
|
259
252
|
@latency = nil
|
260
253
|
@primary = nil
|
261
254
|
@secondary = nil
|
255
|
+
@credentials = {}
|
262
256
|
@instrumenter = options[:instrumenter] || Instrumentable::Log
|
263
257
|
@address = Address.new(address, timeout)
|
264
258
|
@address.resolve(self)
|
@@ -523,6 +517,24 @@ module Moped
|
|
523
517
|
|
524
518
|
private
|
525
519
|
|
520
|
+
# Connect the node on the underlying connection.
|
521
|
+
#
|
522
|
+
# @example Connect the node.
|
523
|
+
# node.connect
|
524
|
+
#
|
525
|
+
# @raise [ Errors::ConnectionFailure ] If connection failed.
|
526
|
+
#
|
527
|
+
# @return [ true ] If the connection suceeded.
|
528
|
+
#
|
529
|
+
# @since 2.0.0
|
530
|
+
def connect(conn)
|
531
|
+
start = Time.now
|
532
|
+
conn.connect
|
533
|
+
@latency = Time.now - start
|
534
|
+
@down_at = nil
|
535
|
+
true
|
536
|
+
end
|
537
|
+
|
526
538
|
# Configure the node based on the return from the ismaster command.
|
527
539
|
#
|
528
540
|
# @api private
|
@@ -554,7 +566,7 @@ module Moped
|
|
554
566
|
def discover(*nodes)
|
555
567
|
nodes.flatten.compact.each do |peer|
|
556
568
|
node = Node.new(peer, options)
|
557
|
-
node.credentials.merge!(credentials)
|
569
|
+
node.credentials.merge!(@credentials)
|
558
570
|
peers.push(node)
|
559
571
|
end
|
560
572
|
end
|
@@ -574,16 +586,14 @@ module Moped
|
|
574
586
|
def flush(ops = queue)
|
575
587
|
operations, callbacks = ops.transpose
|
576
588
|
logging(operations) do
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
replies = conn.receive_replies(operations)
|
582
|
-
end
|
583
|
-
replies.zip(callbacks).map do |reply, callback|
|
584
|
-
callback ? callback[reply] : reply
|
585
|
-
end.last
|
589
|
+
replies = nil
|
590
|
+
ensure_connected do |conn|
|
591
|
+
conn.write(operations)
|
592
|
+
replies = conn.receive_replies(operations)
|
586
593
|
end
|
594
|
+
replies.zip(callbacks).map do |reply, callback|
|
595
|
+
callback ? callback[reply] : reply
|
596
|
+
end.last
|
587
597
|
end
|
588
598
|
ensure
|
589
599
|
ops.clear
|
data/lib/moped/operation/read.rb
CHANGED
@@ -47,12 +47,7 @@ module Moped
|
|
47
47
|
def execute(node)
|
48
48
|
node.process(operation) do |reply|
|
49
49
|
if operation.failure?(reply)
|
50
|
-
|
51
|
-
node.login(database, *node.credentials[database])
|
52
|
-
return execute(node)
|
53
|
-
else
|
54
|
-
raise operation.failure_exception(reply)
|
55
|
-
end
|
50
|
+
raise operation.failure_exception(reply)
|
56
51
|
end
|
57
52
|
operation.results(reply)
|
58
53
|
end
|
data/lib/moped/protocol/reply.rb
CHANGED
data/lib/moped/query.rb
CHANGED
@@ -77,6 +77,17 @@ module Moped
|
|
77
77
|
cursor.each(*args, &blk)
|
78
78
|
end
|
79
79
|
|
80
|
+
# Get the Moped cursor to iterate over documents
|
81
|
+
# on the db.
|
82
|
+
#
|
83
|
+
# @example Iterate over the matching documents.
|
84
|
+
# db[:people].cursor.each do |doc|
|
85
|
+
# #...
|
86
|
+
# end
|
87
|
+
#
|
88
|
+
# @return [ Moped::Cursor ]
|
89
|
+
#
|
90
|
+
# @since 2.0.0
|
80
91
|
def cursor
|
81
92
|
Cursor.new(session, operation)
|
82
93
|
end
|
data/lib/moped/session.rb
CHANGED
@@ -215,10 +215,15 @@ module Moped
|
|
215
215
|
# @since 2.0.0
|
216
216
|
option(:retry_interval).allow(Optionable.any(Numeric))
|
217
217
|
|
218
|
-
# Setup validation of allowed
|
218
|
+
# Setup validation of allowed refresh interval options. (Any numeric)
|
219
219
|
#
|
220
220
|
# @since 2.0.0
|
221
|
-
option(:
|
221
|
+
option(:refresh_interval).allow(Optionable.any(Numeric))
|
222
|
+
|
223
|
+
# Setup validation of allowed down interval options. (Any numeric)
|
224
|
+
#
|
225
|
+
# @since 2.0.0
|
226
|
+
option(:down_interval).allow(Optionable.any(Numeric))
|
222
227
|
|
223
228
|
# Setup validation of allowed ssl options. (Any boolean)
|
224
229
|
#
|
@@ -230,6 +235,11 @@ module Moped
|
|
230
235
|
# @since 2.0.0
|
231
236
|
option(:timeout).allow(Optionable.any(Numeric))
|
232
237
|
|
238
|
+
# Pass an object that responds to instrument as an instrumenter.
|
239
|
+
#
|
240
|
+
# @since 2.0.0
|
241
|
+
option(:instrumenter).allow(Optionable.any(Object))
|
242
|
+
|
233
243
|
# Initialize a new database session.
|
234
244
|
#
|
235
245
|
# @example Initialize a new session.
|
data/lib/moped/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: moped
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.0.
|
4
|
+
version: 2.0.0.beta4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Durran Jordan
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-12-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bson
|
@@ -17,28 +17,42 @@ dependencies:
|
|
17
17
|
requirements:
|
18
18
|
- - ~>
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: 2.0
|
20
|
+
version: '2.0'
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
25
|
- - ~>
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: 2.0
|
27
|
+
version: '2.0'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: connection_pool
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ~>
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '1.2'
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ~>
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '1.2'
|
28
42
|
- !ruby/object:Gem::Dependency
|
29
43
|
name: optionable
|
30
44
|
requirement: !ruby/object:Gem::Requirement
|
31
45
|
requirements:
|
32
46
|
- - ~>
|
33
47
|
- !ruby/object:Gem::Version
|
34
|
-
version: 0.
|
48
|
+
version: 0.2.0
|
35
49
|
type: :runtime
|
36
50
|
prerelease: false
|
37
51
|
version_requirements: !ruby/object:Gem::Requirement
|
38
52
|
requirements:
|
39
53
|
- - ~>
|
40
54
|
- !ruby/object:Gem::Version
|
41
|
-
version: 0.
|
55
|
+
version: 0.2.0
|
42
56
|
description: A MongoDB driver for Ruby.
|
43
57
|
email:
|
44
58
|
- durran@gmail.com
|
@@ -51,9 +65,6 @@ files:
|
|
51
65
|
- lib/moped/cluster.rb
|
52
66
|
- lib/moped/collection.rb
|
53
67
|
- lib/moped/connection/manager.rb
|
54
|
-
- lib/moped/connection/pool.rb
|
55
|
-
- lib/moped/connection/queue.rb
|
56
|
-
- lib/moped/connection/reaper.rb
|
57
68
|
- lib/moped/connection/socket/connectable.rb
|
58
69
|
- lib/moped/connection/socket/ssl.rb
|
59
70
|
- lib/moped/connection/socket/tcp.rb
|
@@ -128,7 +139,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
128
139
|
version: 1.3.1
|
129
140
|
requirements: []
|
130
141
|
rubyforge_project:
|
131
|
-
rubygems_version: 2.
|
142
|
+
rubygems_version: 2.1.11
|
132
143
|
signing_key:
|
133
144
|
specification_version: 4
|
134
145
|
summary: A MongoDB driver for Ruby.
|
@@ -1,198 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
module Moped
|
3
|
-
class Connection
|
4
|
-
|
5
|
-
# This class contains behaviour of connection pools for specific addresses.
|
6
|
-
#
|
7
|
-
# @since 2.0.0
|
8
|
-
class Pool
|
9
|
-
|
10
|
-
# The default max size for the connection pool.
|
11
|
-
POOL_SIZE = 5
|
12
|
-
|
13
|
-
# The default timeout for getting connections from the queue.
|
14
|
-
TIMEOUT = 0.25
|
15
|
-
|
16
|
-
# @!attribute host
|
17
|
-
# @return [ String ] The host the pool is for.
|
18
|
-
# @!attribute port
|
19
|
-
# @return [ Integer ] The port on the host.
|
20
|
-
# @!attribute options
|
21
|
-
# @return [ Hash ] The connection pool options.
|
22
|
-
# @!attribute reaper
|
23
|
-
# @return [ Reaper ] The connection pool reaper.
|
24
|
-
attr_reader :host, :port, :options, :reaper
|
25
|
-
|
26
|
-
# Checkout a connection from the connection pool. If there exists a
|
27
|
-
# connection pinned to the current thread, then we return that first. If
|
28
|
-
# no connection is pinned, we will take an unpinned connection or create
|
29
|
-
# a new one if no unpinned exist and the pool is not saturated.
|
30
|
-
#
|
31
|
-
# @example Checkout a connection.
|
32
|
-
# pool.checkout
|
33
|
-
#
|
34
|
-
# @return [ Connection ] A connection.
|
35
|
-
#
|
36
|
-
# @since 2.0.0
|
37
|
-
def checkout
|
38
|
-
mutex.synchronize do
|
39
|
-
connection = pinned[thread_id]
|
40
|
-
if connection
|
41
|
-
unless connection.expired?
|
42
|
-
raise Errors::ConnectionInUse, "The connection on thread: #{thread_id} is in use."
|
43
|
-
else
|
44
|
-
lease(connection)
|
45
|
-
end
|
46
|
-
else
|
47
|
-
connection = pinned[thread_id] = next_connection
|
48
|
-
lease(connection)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
# Checkin the connection, indicating that it is finished being used. The
|
54
|
-
# connection will stay pinned to the current thread.
|
55
|
-
#
|
56
|
-
# @example Checkin the connection.
|
57
|
-
# pool.checkin(connection)
|
58
|
-
#
|
59
|
-
# @param [ Connection ] connection The connection to checkin.
|
60
|
-
#
|
61
|
-
# @since 2.0.0
|
62
|
-
def checkin(connection)
|
63
|
-
mutex.synchronize do
|
64
|
-
expire(connection)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
# Initialize the connection pool.
|
69
|
-
#
|
70
|
-
# @example Instantiate the connection pool.
|
71
|
-
# Pool.new(max_size: 4)
|
72
|
-
#
|
73
|
-
# @param [ Hash ] options The connection pool options.
|
74
|
-
#
|
75
|
-
# @since 2.0.0
|
76
|
-
def initialize(host, port, options = {})
|
77
|
-
@host = host
|
78
|
-
@port = port
|
79
|
-
@options = options
|
80
|
-
@reaper = Reaper.new(options[:reap_interval] || Reaper::INTERVAL, self)
|
81
|
-
@mutex = Mutex.new
|
82
|
-
@resource = ConditionVariable.new
|
83
|
-
@pinned = {}
|
84
|
-
@unpinned = Queue.new(max_size) do
|
85
|
-
Connection.new(host, port, options[:timeout] || Connection::TIMEOUT, options)
|
86
|
-
end
|
87
|
-
reaper.start
|
88
|
-
end
|
89
|
-
|
90
|
-
# Get the max size for the connection pool.
|
91
|
-
#
|
92
|
-
# @example Get the max size.
|
93
|
-
# pool.max_size
|
94
|
-
#
|
95
|
-
# @return [ Integer ] The max size of the pool.
|
96
|
-
#
|
97
|
-
# @since 2.0.0
|
98
|
-
def max_size
|
99
|
-
@max_size ||= (options[:pool_size] || POOL_SIZE)
|
100
|
-
end
|
101
|
-
|
102
|
-
# Reap all connections that are active and associated with dead threads.
|
103
|
-
#
|
104
|
-
# @example Reap the connections.
|
105
|
-
# pool.reap([ 12351122313 ])
|
106
|
-
#
|
107
|
-
# @param [ Array<Integer> ] ids The ids of the current active threads.
|
108
|
-
#
|
109
|
-
# @return [ Pool ] The connection pool.
|
110
|
-
#
|
111
|
-
# @since 2.0.0
|
112
|
-
def reap(ids = active_threads)
|
113
|
-
pinned.each do |id, conn|
|
114
|
-
unless ids.include?(id)
|
115
|
-
conn.expire
|
116
|
-
unpinned.push(pinned.delete(id))
|
117
|
-
end
|
118
|
-
end and self
|
119
|
-
end
|
120
|
-
|
121
|
-
# Get the current size of the connection pool. Is the total of pinned
|
122
|
-
# plus unpinned connections.
|
123
|
-
#
|
124
|
-
# @example Get the pool's current size.
|
125
|
-
# pool.size
|
126
|
-
#
|
127
|
-
# @return [ Integer ] The current size of the pool.
|
128
|
-
#
|
129
|
-
# @since 2.0.0
|
130
|
-
def size
|
131
|
-
unpinned.size + pinned.size
|
132
|
-
end
|
133
|
-
|
134
|
-
# Get the timeout when attempting to check out items from the pool.
|
135
|
-
#
|
136
|
-
# @example Get the checkout timeout.
|
137
|
-
# pool.timeout
|
138
|
-
#
|
139
|
-
# @return [ Float ] The pool timeout.
|
140
|
-
#
|
141
|
-
# @since 2.0.0
|
142
|
-
def timeout
|
143
|
-
@timeout ||= (options[:pool_timeout] || TIMEOUT)
|
144
|
-
end
|
145
|
-
|
146
|
-
# Execute the block with a connection, ensuring that the checkin/checkout
|
147
|
-
# workflow is properly executed.
|
148
|
-
#
|
149
|
-
# @example Execute the block with a connection.
|
150
|
-
# pool.with_connection do |conn|
|
151
|
-
# conn.connect
|
152
|
-
# end
|
153
|
-
#
|
154
|
-
# @return [ Object ] The result of the yield.
|
155
|
-
#
|
156
|
-
# @since 2.0.0
|
157
|
-
def with_connection
|
158
|
-
connection = checkout
|
159
|
-
begin
|
160
|
-
yield(connection)
|
161
|
-
ensure
|
162
|
-
checkin(connection)
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
private
|
167
|
-
|
168
|
-
attr_reader :mutex, :resource, :pinned, :unpinned
|
169
|
-
|
170
|
-
def expire(connection)
|
171
|
-
connection.expire
|
172
|
-
pinned[thread_id] = connection
|
173
|
-
end
|
174
|
-
|
175
|
-
def lease(connection)
|
176
|
-
connection.lease
|
177
|
-
connection
|
178
|
-
end
|
179
|
-
|
180
|
-
def next_connection
|
181
|
-
reap if saturated?
|
182
|
-
unpinned.pop(timeout)
|
183
|
-
end
|
184
|
-
|
185
|
-
def saturated?
|
186
|
-
size == max_size
|
187
|
-
end
|
188
|
-
|
189
|
-
def thread_id
|
190
|
-
Thread.current.object_id
|
191
|
-
end
|
192
|
-
|
193
|
-
def active_threads
|
194
|
-
Thread.list.select{ |thread| thread.alive? }.map{ |thread| thread.object_id }
|
195
|
-
end
|
196
|
-
end
|
197
|
-
end
|
198
|
-
end
|
@@ -1,93 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
module Moped
|
3
|
-
class Connection
|
4
|
-
|
5
|
-
# This class contains behaviour of a queue of unpinned connections.
|
6
|
-
#
|
7
|
-
# @since 2.0.0
|
8
|
-
class Queue
|
9
|
-
|
10
|
-
# Initialize a queue with the provided size.
|
11
|
-
#
|
12
|
-
# @example Instantiate the queue.
|
13
|
-
# Moped::Connection::Queue.new(10)
|
14
|
-
#
|
15
|
-
# @param [ Integer ] size The number of connections in the queue.
|
16
|
-
#
|
17
|
-
# @since 2.0.0
|
18
|
-
def initialize(size)
|
19
|
-
@queue = Array.new(size) { yield }
|
20
|
-
@mutex = Mutex.new
|
21
|
-
@resource = ConditionVariable.new
|
22
|
-
end
|
23
|
-
|
24
|
-
# Push a connection on the queue.
|
25
|
-
#
|
26
|
-
# @example Push a connection on the queue.
|
27
|
-
# queue.push(connection)
|
28
|
-
#
|
29
|
-
# @param [ Moped::Connection ] connection The connection to add.
|
30
|
-
#
|
31
|
-
# @since 2.0.0
|
32
|
-
def push(connection)
|
33
|
-
mutex.synchronize do
|
34
|
-
queue.push(connection)
|
35
|
-
resource.broadcast
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
# Pop the next connection off the queue.
|
40
|
-
#
|
41
|
-
# @example Pop a connection off the queue.
|
42
|
-
# queue.pop(0.5)
|
43
|
-
#
|
44
|
-
# @param [ Float ] timeout The time to wait for the connection.
|
45
|
-
#
|
46
|
-
# @return [ Moped::Connection ] The next connection.
|
47
|
-
#
|
48
|
-
# @since 2.0.0
|
49
|
-
def pop(timeout = 0.5)
|
50
|
-
mutex.synchronize do
|
51
|
-
wait_for_next(Time.now + timeout)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
# Is the queue empty?
|
56
|
-
#
|
57
|
-
# @example Is the queue empty?
|
58
|
-
# queue.empty?
|
59
|
-
#
|
60
|
-
# @return [ true, false ] Is the queue empty?
|
61
|
-
#
|
62
|
-
# @since 2.0.0
|
63
|
-
def empty?
|
64
|
-
queue.empty?
|
65
|
-
end
|
66
|
-
|
67
|
-
# Get the current size of the queue.
|
68
|
-
#
|
69
|
-
# @example Get the size of the queue.
|
70
|
-
# queue.size
|
71
|
-
#
|
72
|
-
# @return [ Integer ] The number of connections in the queue.
|
73
|
-
#
|
74
|
-
# @since 2.0.0
|
75
|
-
def size
|
76
|
-
queue.size
|
77
|
-
end
|
78
|
-
|
79
|
-
private
|
80
|
-
|
81
|
-
attr_reader :queue, :mutex, :resource
|
82
|
-
|
83
|
-
def wait_for_next(deadline)
|
84
|
-
loop do
|
85
|
-
return queue.pop unless queue.empty?
|
86
|
-
wait = deadline - Time.now
|
87
|
-
raise Timeout::Error, "Waited for item but none was pushed." if wait <= 0
|
88
|
-
resource.wait(mutex, wait)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
@@ -1,52 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
module Moped
|
3
|
-
class Connection
|
4
|
-
|
5
|
-
# This object cleans up connections on dead threads at a specified time
|
6
|
-
# interval.
|
7
|
-
#
|
8
|
-
# @since 2.0.0
|
9
|
-
class Reaper
|
10
|
-
|
11
|
-
# The default interval for reaping connections.
|
12
|
-
#
|
13
|
-
# @since 2.0.0
|
14
|
-
INTERVAL = 5
|
15
|
-
|
16
|
-
# @!attribute interval
|
17
|
-
# @return [ Float ] The reaping interval, in seconds.
|
18
|
-
# @!attribute pool
|
19
|
-
# @return [ Pool ] The connection pool to reap.
|
20
|
-
attr_reader :interval, :pool
|
21
|
-
|
22
|
-
# Initialize a new connection pool reaper.
|
23
|
-
#
|
24
|
-
# @example Initialize the reaper.
|
25
|
-
# Moped::Connection::Reaper.new(5, pool)
|
26
|
-
#
|
27
|
-
# @param [ Float ] interval The reaping interval.
|
28
|
-
# @param [ Pool ] pool The connection pool to reap.
|
29
|
-
#
|
30
|
-
# @since 2.0.0
|
31
|
-
def initialize(interval, pool)
|
32
|
-
@interval = interval
|
33
|
-
@pool = pool
|
34
|
-
end
|
35
|
-
|
36
|
-
# Start the reaper. Will execute continually on a separate thread.
|
37
|
-
#
|
38
|
-
# @example Start the reaper.
|
39
|
-
# reaper.start
|
40
|
-
#
|
41
|
-
# @since 2.0.0
|
42
|
-
def start
|
43
|
-
Thread.new(interval, pool) do |i, p|
|
44
|
-
while (true)
|
45
|
-
sleep(i)
|
46
|
-
p.reap
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|