moped 1.5.3 → 2.0.0.beta
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.
Potentially problematic release.
This version of moped might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +42 -5
- data/README.md +1 -1
- data/lib/moped.rb +10 -13
- data/lib/moped/address.rb +56 -0
- data/lib/moped/authenticatable.rb +89 -0
- data/lib/moped/cluster.rb +169 -136
- data/lib/moped/collection.rb +53 -19
- data/lib/moped/connection.rb +69 -10
- data/lib/moped/connection/manager.rb +49 -0
- data/lib/moped/connection/pool.rb +198 -0
- data/lib/moped/connection/queue.rb +93 -0
- data/lib/moped/connection/reaper.rb +52 -0
- data/lib/moped/connection/socket.rb +4 -0
- data/lib/moped/connection/socket/connectable.rb +169 -0
- data/lib/moped/connection/socket/ssl.rb +52 -0
- data/lib/moped/connection/socket/tcp.rb +25 -0
- data/lib/moped/connection/sockets.rb +4 -0
- data/lib/moped/cursor.rb +3 -5
- data/lib/moped/database.rb +18 -24
- data/lib/moped/errors.rb +35 -6
- data/lib/moped/executable.rb +96 -0
- data/lib/moped/failover.rb +41 -0
- data/lib/moped/failover/disconnect.rb +31 -0
- data/lib/moped/failover/ignore.rb +29 -0
- data/lib/moped/failover/reconfigure.rb +34 -0
- data/lib/moped/failover/retry.rb +37 -0
- data/lib/moped/indexes.rb +4 -1
- data/lib/moped/instrumentable.rb +39 -0
- data/lib/moped/instrumentable/log.rb +43 -0
- data/lib/moped/instrumentable/noop.rb +31 -0
- data/lib/moped/loggable.rb +110 -0
- data/lib/moped/node.rb +316 -297
- data/lib/moped/operation.rb +3 -0
- data/lib/moped/operation/read.rb +62 -0
- data/lib/moped/operation/write.rb +57 -0
- data/lib/moped/protocol/command.rb +65 -4
- data/lib/moped/protocol/commands/authenticate.rb +1 -2
- data/lib/moped/protocol/delete.rb +16 -0
- data/lib/moped/protocol/get_more.rb +102 -31
- data/lib/moped/protocol/insert.rb +17 -0
- data/lib/moped/protocol/message.rb +44 -46
- data/lib/moped/protocol/query.rb +175 -92
- data/lib/moped/protocol/reply.rb +19 -8
- data/lib/moped/protocol/update.rb +18 -0
- data/lib/moped/query.rb +43 -17
- data/lib/moped/read_preference.rb +49 -0
- data/lib/moped/read_preference/nearest.rb +55 -0
- data/lib/moped/read_preference/primary.rb +60 -0
- data/lib/moped/read_preference/primary_preferred.rb +55 -0
- data/lib/moped/read_preference/secondary.rb +50 -0
- data/lib/moped/read_preference/secondary_preferred.rb +53 -0
- data/lib/moped/read_preference/selectable.rb +79 -0
- data/lib/moped/readable.rb +55 -0
- data/lib/moped/session.rb +122 -70
- data/lib/moped/{mongo_uri.rb → uri.rb} +75 -31
- data/lib/moped/version.rb +1 -1
- data/lib/moped/write_concern.rb +33 -0
- data/lib/moped/write_concern/propagate.rb +38 -0
- data/lib/moped/write_concern/unverified.rb +28 -0
- metadata +79 -44
- data/lib/moped/bson.rb +0 -45
- data/lib/moped/bson/binary.rb +0 -137
- data/lib/moped/bson/code.rb +0 -112
- data/lib/moped/bson/document.rb +0 -41
- data/lib/moped/bson/extensions.rb +0 -91
- data/lib/moped/bson/extensions/array.rb +0 -37
- data/lib/moped/bson/extensions/boolean.rb +0 -16
- data/lib/moped/bson/extensions/false_class.rb +0 -19
- data/lib/moped/bson/extensions/float.rb +0 -22
- data/lib/moped/bson/extensions/hash.rb +0 -39
- data/lib/moped/bson/extensions/integer.rb +0 -36
- data/lib/moped/bson/extensions/nil_class.rb +0 -19
- data/lib/moped/bson/extensions/object.rb +0 -11
- data/lib/moped/bson/extensions/regexp.rb +0 -38
- data/lib/moped/bson/extensions/string.rb +0 -45
- data/lib/moped/bson/extensions/symbol.rb +0 -33
- data/lib/moped/bson/extensions/time.rb +0 -23
- data/lib/moped/bson/extensions/true_class.rb +0 -19
- data/lib/moped/bson/max_key.rb +0 -51
- data/lib/moped/bson/min_key.rb +0 -51
- data/lib/moped/bson/object_id.rb +0 -301
- data/lib/moped/bson/timestamp.rb +0 -38
- data/lib/moped/bson/types.rb +0 -67
- data/lib/moped/logging.rb +0 -58
- data/lib/moped/session/context.rb +0 -115
- data/lib/moped/sockets/connectable.rb +0 -167
- data/lib/moped/sockets/ssl.rb +0 -50
- data/lib/moped/sockets/tcp.rb +0 -23
- data/lib/moped/threaded.rb +0 -69
data/lib/moped/bson/timestamp.rb
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
module Moped
|
2
|
-
module BSON
|
3
|
-
|
4
|
-
# A time representation in BSON.
|
5
|
-
class Timestamp < Struct.new(:seconds, :increment)
|
6
|
-
|
7
|
-
# Serialize the time to the stream.
|
8
|
-
#
|
9
|
-
# @example Serialize the time.
|
10
|
-
# time.__bson_dump__("", "created_at")
|
11
|
-
#
|
12
|
-
# @param [ String ] io The raw bytes.
|
13
|
-
# @param [ String ] key The field name.
|
14
|
-
#
|
15
|
-
# @since 1.0.0
|
16
|
-
def __bson_dump__(io, key)
|
17
|
-
io << [17, key, increment, seconds].pack('cZ*l2')
|
18
|
-
end
|
19
|
-
|
20
|
-
class << self
|
21
|
-
|
22
|
-
# Deserialize the timestamp to an object.
|
23
|
-
#
|
24
|
-
# @example Deserialize the time.
|
25
|
-
# Moped::BSON::Timestamp.__bson_load__(string)
|
26
|
-
#
|
27
|
-
# @param [ String ] io The raw bytes.
|
28
|
-
#
|
29
|
-
# @return [ Timestamp ] The time.
|
30
|
-
#
|
31
|
-
# @since 1.0.0
|
32
|
-
def __bson_load__(io)
|
33
|
-
new(*io.read(8).unpack('l2').reverse)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
data/lib/moped/bson/types.rb
DELETED
@@ -1,67 +0,0 @@
|
|
1
|
-
module Moped
|
2
|
-
module BSON
|
3
|
-
|
4
|
-
# Various BSON type behaviour.
|
5
|
-
module Types
|
6
|
-
|
7
|
-
class CodeWithScope
|
8
|
-
|
9
|
-
def self.__bson_load__(io)
|
10
|
-
io.read 4 # swallow the length
|
11
|
-
code = io.read(*io.read(4).unpack(INT32_PACK)).from_utf8_binary.chop!
|
12
|
-
scope = BSON::Document.deserialize(io)
|
13
|
-
Code.new(code, scope)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
class Integer64
|
18
|
-
|
19
|
-
def self.__bson_load__(io)
|
20
|
-
io.read(8).unpack(INT64_PACK)[0]
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
MAP = {}
|
25
|
-
MAP[1] = Float
|
26
|
-
MAP[2] = String
|
27
|
-
MAP[3] = Hash
|
28
|
-
MAP[4] = Array
|
29
|
-
MAP[5] = Binary
|
30
|
-
# MAP[6] = undefined - deprecated
|
31
|
-
MAP[7] = ObjectId
|
32
|
-
MAP[8] = TrueClass
|
33
|
-
MAP[9] = Time
|
34
|
-
MAP[10] = NilClass
|
35
|
-
MAP[11] = Regexp
|
36
|
-
# MAP[12] = db pointer - deprecated
|
37
|
-
MAP[13] = Code
|
38
|
-
MAP[14] = Symbol
|
39
|
-
MAP[15] = CodeWithScope
|
40
|
-
MAP[16] = Integer
|
41
|
-
MAP[17] = Timestamp
|
42
|
-
MAP[18] = Integer64
|
43
|
-
MAP[255] = MinKey
|
44
|
-
MAP[127] = MaxKey
|
45
|
-
|
46
|
-
FLOAT = 1.chr.freeze
|
47
|
-
STRING = 2.chr.freeze
|
48
|
-
HASH = 3.chr.freeze
|
49
|
-
ARRAY = 4.chr.freeze
|
50
|
-
BINARY = 5.chr.freeze
|
51
|
-
OBJECT_ID = 7.chr.freeze
|
52
|
-
BOOLEAN = 8.chr.freeze
|
53
|
-
TIME = 9.chr.freeze
|
54
|
-
NULL = 10.chr.freeze
|
55
|
-
REGEX = 11.chr.freeze
|
56
|
-
CODE = 13.chr.freeze
|
57
|
-
SYMBOL = 14.chr.freeze
|
58
|
-
CODE_WITH_SCOPE = 15.chr.freeze
|
59
|
-
INT32 = 16.chr.freeze
|
60
|
-
INT64 = 18.chr.freeze
|
61
|
-
MAX_KEY = 127.chr.freeze
|
62
|
-
MIN_KEY = 255.chr.freeze
|
63
|
-
|
64
|
-
TRUE = 1.chr.freeze
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
data/lib/moped/logging.rb
DELETED
@@ -1,58 +0,0 @@
|
|
1
|
-
module Moped
|
2
|
-
|
3
|
-
# Contains behaviour for logging.
|
4
|
-
module Logging
|
5
|
-
|
6
|
-
# Get the logger.
|
7
|
-
#
|
8
|
-
# @example Get the logger.
|
9
|
-
# Logging.logger
|
10
|
-
#
|
11
|
-
# @return [ Logger ] The logger.
|
12
|
-
#
|
13
|
-
# @since 1.0.0
|
14
|
-
def logger
|
15
|
-
return @logger if defined?(@logger)
|
16
|
-
@logger = rails_logger || default_logger
|
17
|
-
end
|
18
|
-
|
19
|
-
# Get the rails logger.
|
20
|
-
#
|
21
|
-
# @example Get the rails logger.
|
22
|
-
# Logging.rails_logger
|
23
|
-
#
|
24
|
-
# @return [ Logger ] The Rails logger.
|
25
|
-
#
|
26
|
-
# @since 1.0.0
|
27
|
-
def rails_logger
|
28
|
-
defined?(Rails) && Rails.respond_to?(:logger) && Rails.logger
|
29
|
-
end
|
30
|
-
|
31
|
-
# Get the default logger.
|
32
|
-
#
|
33
|
-
# @example Get the default logger.
|
34
|
-
# Logging.default_logger
|
35
|
-
#
|
36
|
-
# @return [ Logger ] The default logger.
|
37
|
-
#
|
38
|
-
# @since 1.0.0
|
39
|
-
def default_logger
|
40
|
-
logger = Logger.new(STDOUT)
|
41
|
-
logger.level = Logger::INFO
|
42
|
-
logger
|
43
|
-
end
|
44
|
-
|
45
|
-
# Set the logger.
|
46
|
-
#
|
47
|
-
# @example Set the logger.
|
48
|
-
# Logging.logger = logger
|
49
|
-
#
|
50
|
-
# @return [ Logger ] The logger.
|
51
|
-
#
|
52
|
-
# @since 1.0.0
|
53
|
-
def logger=(logger)
|
54
|
-
@logger = logger
|
55
|
-
end
|
56
|
-
end
|
57
|
-
extend Logging
|
58
|
-
end
|
@@ -1,115 +0,0 @@
|
|
1
|
-
module Moped
|
2
|
-
class Session
|
3
|
-
|
4
|
-
# @api private
|
5
|
-
class Context
|
6
|
-
|
7
|
-
attr_reader :session
|
8
|
-
|
9
|
-
def initialize(session)
|
10
|
-
@session = session
|
11
|
-
end
|
12
|
-
|
13
|
-
def safety
|
14
|
-
session.safety
|
15
|
-
end
|
16
|
-
|
17
|
-
def safe?
|
18
|
-
session.safe?
|
19
|
-
end
|
20
|
-
|
21
|
-
def consistency
|
22
|
-
session.consistency
|
23
|
-
end
|
24
|
-
|
25
|
-
def cluster
|
26
|
-
session.cluster
|
27
|
-
end
|
28
|
-
|
29
|
-
def login(database, username, password)
|
30
|
-
cluster.auth[database.to_s] = [username, password]
|
31
|
-
end
|
32
|
-
|
33
|
-
def logout(database)
|
34
|
-
cluster.auth.delete database.to_s
|
35
|
-
end
|
36
|
-
|
37
|
-
def query(database, collection, selector, options = {})
|
38
|
-
if consistency == :eventual
|
39
|
-
options[:flags] ||= []
|
40
|
-
options[:flags] |= [:slave_ok]
|
41
|
-
end
|
42
|
-
|
43
|
-
with_node do |node|
|
44
|
-
node.query(database, collection, selector, options)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def command(database, command)
|
49
|
-
options = consistency == :eventual ? { :flags => [:slave_ok] } : {}
|
50
|
-
with_node do |node|
|
51
|
-
node.command(database, command, options)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def insert(database, collection, documents, options = {})
|
56
|
-
with_node do |node|
|
57
|
-
if safe?
|
58
|
-
node.pipeline do
|
59
|
-
node.insert(database, collection, documents, options)
|
60
|
-
node.command(database, { getlasterror: 1 }.merge(safety))
|
61
|
-
end
|
62
|
-
else
|
63
|
-
node.insert(database, collection, documents, options)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def update(database, collection, selector, change, options = {})
|
69
|
-
with_node do |node|
|
70
|
-
if safe?
|
71
|
-
node.pipeline do
|
72
|
-
node.update(database, collection, selector, change, options)
|
73
|
-
node.command(database, { getlasterror: 1 }.merge(safety))
|
74
|
-
end
|
75
|
-
else
|
76
|
-
node.update(database, collection, selector, change, options)
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def remove(database, collection, selector, options = {})
|
82
|
-
with_node do |node|
|
83
|
-
if safe?
|
84
|
-
node.pipeline do
|
85
|
-
node.remove(database, collection, selector, options)
|
86
|
-
node.command(database, { getlasterror: 1 }.merge(safety))
|
87
|
-
end
|
88
|
-
else
|
89
|
-
node.remove(database, collection, selector, options)
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
def get_more(*args)
|
95
|
-
raise NotImplementedError, "#get_more cannot be called on Context; it must be called directly on a node"
|
96
|
-
end
|
97
|
-
|
98
|
-
def kill_cursors(*args)
|
99
|
-
raise NotImplementedError, "#kill_cursors cannot be called on Context; it must be called directly on a node"
|
100
|
-
end
|
101
|
-
|
102
|
-
def with_node
|
103
|
-
if consistency == :eventual
|
104
|
-
cluster.with_secondary do |node|
|
105
|
-
yield node
|
106
|
-
end
|
107
|
-
else
|
108
|
-
cluster.with_primary do |node|
|
109
|
-
yield node
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
@@ -1,167 +0,0 @@
|
|
1
|
-
module Moped
|
2
|
-
module Sockets
|
3
|
-
module Connectable
|
4
|
-
|
5
|
-
attr_reader :host, :port
|
6
|
-
|
7
|
-
# Is the socket connection alive?
|
8
|
-
#
|
9
|
-
# @example Is the socket alive?
|
10
|
-
# socket.alive?
|
11
|
-
#
|
12
|
-
# @return [ true, false ] If the socket is alive.
|
13
|
-
#
|
14
|
-
# @since 1.0.0
|
15
|
-
def alive?
|
16
|
-
if Kernel::select([ self ], nil, [ self ], 0)
|
17
|
-
!eof? rescue false
|
18
|
-
else
|
19
|
-
true
|
20
|
-
end
|
21
|
-
rescue IOError
|
22
|
-
false
|
23
|
-
end
|
24
|
-
|
25
|
-
# Bring in the class methods when included.
|
26
|
-
#
|
27
|
-
# @example Extend the class methods.
|
28
|
-
# Connectable.included(class)
|
29
|
-
#
|
30
|
-
# @param [ Class ] klass The class including the module.
|
31
|
-
#
|
32
|
-
# @since 1.3.0
|
33
|
-
def self.included(klass)
|
34
|
-
klass.send(:extend, ClassMethods)
|
35
|
-
end
|
36
|
-
|
37
|
-
# Read from the TCP socket.
|
38
|
-
#
|
39
|
-
# @param [ Integer ] length The length to read.
|
40
|
-
#
|
41
|
-
# @return [ Object ] The data.
|
42
|
-
#
|
43
|
-
# @since 1.2.0
|
44
|
-
def read(length)
|
45
|
-
check_if_alive!
|
46
|
-
handle_socket_errors { super }
|
47
|
-
end
|
48
|
-
|
49
|
-
# Write to the socket.
|
50
|
-
#
|
51
|
-
# @example Write to the socket.
|
52
|
-
# socket.write(data)
|
53
|
-
#
|
54
|
-
# @param [ Object ] args The data to write.
|
55
|
-
#
|
56
|
-
# @return [ Integer ] The number of bytes written.
|
57
|
-
#
|
58
|
-
# @since 1.0.0
|
59
|
-
def write(*args)
|
60
|
-
check_if_alive!
|
61
|
-
handle_socket_errors { super }
|
62
|
-
end
|
63
|
-
|
64
|
-
private
|
65
|
-
|
66
|
-
# Before performing a read or write operating, ping the server to check
|
67
|
-
# if it is alive.
|
68
|
-
#
|
69
|
-
# @api private
|
70
|
-
#
|
71
|
-
# @example Check if the connection is alive.
|
72
|
-
# connectable.check_if_alive!
|
73
|
-
#
|
74
|
-
# @raise [ ConnectionFailure ] If the connectable is not alive.
|
75
|
-
#
|
76
|
-
# @since 1.4.0
|
77
|
-
def check_if_alive!
|
78
|
-
unless alive?
|
79
|
-
raise Errors::ConnectionFailure, "Socket connection was closed by remote host"
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
# Generate the message for the connection failure based of the system
|
84
|
-
# call error, with some added information.
|
85
|
-
#
|
86
|
-
# @api private
|
87
|
-
#
|
88
|
-
# @example Generate the error message.
|
89
|
-
# connectable.generate_message(error)
|
90
|
-
#
|
91
|
-
# @param [ SystemCallError ] error The error.
|
92
|
-
#
|
93
|
-
# @return [ String ] The error message.
|
94
|
-
#
|
95
|
-
# @since 1.4.0
|
96
|
-
def generate_message(error)
|
97
|
-
"#{host}:#{port}: #{error.class.name} (#{error.errno}): #{error.message}"
|
98
|
-
end
|
99
|
-
|
100
|
-
# Handle the potential socket errors that can occur.
|
101
|
-
#
|
102
|
-
# @api private
|
103
|
-
#
|
104
|
-
# @example Handle the socket errors while executing the block.
|
105
|
-
# handle_socket_errors do
|
106
|
-
# socket.read(128)
|
107
|
-
# end
|
108
|
-
#
|
109
|
-
# @raise [ Moped::Errors::ConnectionFailure ] If a system call error or
|
110
|
-
# IOError occured which can be retried.
|
111
|
-
# @raise [ Moped::Errors::Unrecoverable ] If a system call error occured
|
112
|
-
# which cannot be retried and should be re-raised.
|
113
|
-
#
|
114
|
-
# @return [ Object ] The result of the yield.
|
115
|
-
#
|
116
|
-
# @since 1.0.0
|
117
|
-
def handle_socket_errors
|
118
|
-
yield
|
119
|
-
rescue Errno::ECONNREFUSED => e
|
120
|
-
raise Errors::ConnectionFailure, generate_message(e)
|
121
|
-
rescue Errno::EHOSTUNREACH => e
|
122
|
-
raise Errors::ConnectionFailure, generate_message(e)
|
123
|
-
rescue Errno::EPIPE => e
|
124
|
-
raise Errors::ConnectionFailure, generate_message(e)
|
125
|
-
rescue Errno::ECONNRESET => e
|
126
|
-
raise Errors::ConnectionFailure, generate_message(e)
|
127
|
-
rescue Errno::ETIMEDOUT => e
|
128
|
-
raise Errors::ConnectionFailure, generate_message(e)
|
129
|
-
rescue IOError
|
130
|
-
raise Errors::ConnectionFailure, "Connection timed out to Mongo on #{host}:#{port}"
|
131
|
-
rescue OpenSSL::SSL::SSLError => e
|
132
|
-
raise Errors::ConnectionFailure, "SSL Error '#{e.to_s}' for connection to Mongo on #{host}:#{port}"
|
133
|
-
end
|
134
|
-
|
135
|
-
module ClassMethods
|
136
|
-
|
137
|
-
# Connect to the tcp server.
|
138
|
-
#
|
139
|
-
# @example Connect to the server.
|
140
|
-
# TCPSocket.connect("127.0.0.1", 27017, 30)
|
141
|
-
#
|
142
|
-
# @param [ String ] host The host to connect to.
|
143
|
-
# @param [ Integer ] post The server port.
|
144
|
-
# @param [ Integer ] timeout The connection timeout.
|
145
|
-
#
|
146
|
-
# @return [ TCPSocket ] The socket.
|
147
|
-
#
|
148
|
-
# @since 1.0.0
|
149
|
-
def connect(host, port, timeout)
|
150
|
-
begin
|
151
|
-
Timeout::timeout(timeout) do
|
152
|
-
sock = new(host, port)
|
153
|
-
sock.set_encoding('binary')
|
154
|
-
timeout_val = [ timeout, 0 ].pack("l_2")
|
155
|
-
sock.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
156
|
-
sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_RCVTIMEO, timeout_val)
|
157
|
-
sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDTIMEO, timeout_val)
|
158
|
-
sock
|
159
|
-
end
|
160
|
-
rescue Timeout::Error
|
161
|
-
raise Errors::ConnectionFailure, "Timed out connection to Mongo on #{host}:#{port}"
|
162
|
-
end
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end
|