moped 1.5.3 → 2.0.0.beta

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.

Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +42 -5
  3. data/README.md +1 -1
  4. data/lib/moped.rb +10 -13
  5. data/lib/moped/address.rb +56 -0
  6. data/lib/moped/authenticatable.rb +89 -0
  7. data/lib/moped/cluster.rb +169 -136
  8. data/lib/moped/collection.rb +53 -19
  9. data/lib/moped/connection.rb +69 -10
  10. data/lib/moped/connection/manager.rb +49 -0
  11. data/lib/moped/connection/pool.rb +198 -0
  12. data/lib/moped/connection/queue.rb +93 -0
  13. data/lib/moped/connection/reaper.rb +52 -0
  14. data/lib/moped/connection/socket.rb +4 -0
  15. data/lib/moped/connection/socket/connectable.rb +169 -0
  16. data/lib/moped/connection/socket/ssl.rb +52 -0
  17. data/lib/moped/connection/socket/tcp.rb +25 -0
  18. data/lib/moped/connection/sockets.rb +4 -0
  19. data/lib/moped/cursor.rb +3 -5
  20. data/lib/moped/database.rb +18 -24
  21. data/lib/moped/errors.rb +35 -6
  22. data/lib/moped/executable.rb +96 -0
  23. data/lib/moped/failover.rb +41 -0
  24. data/lib/moped/failover/disconnect.rb +31 -0
  25. data/lib/moped/failover/ignore.rb +29 -0
  26. data/lib/moped/failover/reconfigure.rb +34 -0
  27. data/lib/moped/failover/retry.rb +37 -0
  28. data/lib/moped/indexes.rb +4 -1
  29. data/lib/moped/instrumentable.rb +39 -0
  30. data/lib/moped/instrumentable/log.rb +43 -0
  31. data/lib/moped/instrumentable/noop.rb +31 -0
  32. data/lib/moped/loggable.rb +110 -0
  33. data/lib/moped/node.rb +316 -297
  34. data/lib/moped/operation.rb +3 -0
  35. data/lib/moped/operation/read.rb +62 -0
  36. data/lib/moped/operation/write.rb +57 -0
  37. data/lib/moped/protocol/command.rb +65 -4
  38. data/lib/moped/protocol/commands/authenticate.rb +1 -2
  39. data/lib/moped/protocol/delete.rb +16 -0
  40. data/lib/moped/protocol/get_more.rb +102 -31
  41. data/lib/moped/protocol/insert.rb +17 -0
  42. data/lib/moped/protocol/message.rb +44 -46
  43. data/lib/moped/protocol/query.rb +175 -92
  44. data/lib/moped/protocol/reply.rb +19 -8
  45. data/lib/moped/protocol/update.rb +18 -0
  46. data/lib/moped/query.rb +43 -17
  47. data/lib/moped/read_preference.rb +49 -0
  48. data/lib/moped/read_preference/nearest.rb +55 -0
  49. data/lib/moped/read_preference/primary.rb +60 -0
  50. data/lib/moped/read_preference/primary_preferred.rb +55 -0
  51. data/lib/moped/read_preference/secondary.rb +50 -0
  52. data/lib/moped/read_preference/secondary_preferred.rb +53 -0
  53. data/lib/moped/read_preference/selectable.rb +79 -0
  54. data/lib/moped/readable.rb +55 -0
  55. data/lib/moped/session.rb +122 -70
  56. data/lib/moped/{mongo_uri.rb → uri.rb} +75 -31
  57. data/lib/moped/version.rb +1 -1
  58. data/lib/moped/write_concern.rb +33 -0
  59. data/lib/moped/write_concern/propagate.rb +38 -0
  60. data/lib/moped/write_concern/unverified.rb +28 -0
  61. metadata +79 -44
  62. data/lib/moped/bson.rb +0 -45
  63. data/lib/moped/bson/binary.rb +0 -137
  64. data/lib/moped/bson/code.rb +0 -112
  65. data/lib/moped/bson/document.rb +0 -41
  66. data/lib/moped/bson/extensions.rb +0 -91
  67. data/lib/moped/bson/extensions/array.rb +0 -37
  68. data/lib/moped/bson/extensions/boolean.rb +0 -16
  69. data/lib/moped/bson/extensions/false_class.rb +0 -19
  70. data/lib/moped/bson/extensions/float.rb +0 -22
  71. data/lib/moped/bson/extensions/hash.rb +0 -39
  72. data/lib/moped/bson/extensions/integer.rb +0 -36
  73. data/lib/moped/bson/extensions/nil_class.rb +0 -19
  74. data/lib/moped/bson/extensions/object.rb +0 -11
  75. data/lib/moped/bson/extensions/regexp.rb +0 -38
  76. data/lib/moped/bson/extensions/string.rb +0 -45
  77. data/lib/moped/bson/extensions/symbol.rb +0 -33
  78. data/lib/moped/bson/extensions/time.rb +0 -23
  79. data/lib/moped/bson/extensions/true_class.rb +0 -19
  80. data/lib/moped/bson/max_key.rb +0 -51
  81. data/lib/moped/bson/min_key.rb +0 -51
  82. data/lib/moped/bson/object_id.rb +0 -301
  83. data/lib/moped/bson/timestamp.rb +0 -38
  84. data/lib/moped/bson/types.rb +0 -67
  85. data/lib/moped/logging.rb +0 -58
  86. data/lib/moped/session/context.rb +0 -115
  87. data/lib/moped/sockets/connectable.rb +0 -167
  88. data/lib/moped/sockets/ssl.rb +0 -50
  89. data/lib/moped/sockets/tcp.rb +0 -23
  90. data/lib/moped/threaded.rb +0 -69
@@ -0,0 +1,3 @@
1
+ # encoding: utf-8
2
+ require "moped/operation/read"
3
+ require "moped/operation/write"
@@ -0,0 +1,62 @@
1
+ # encoding: utf-8
2
+ module Moped
3
+ module Operation
4
+
5
+ # Represents a read from the database that is executed on a specific node
6
+ # determined by a read preference.
7
+ #
8
+ # @since 2.0.0
9
+ class Read
10
+
11
+ # @!attribute database
12
+ # @return [ String ] The database the read is from.
13
+ # @!attribute operation
14
+ # @return [ Protocol::Query, Protocol::GetMore, Protocol::Command ]
15
+ # The read operation.
16
+ attr_reader :database, :operation
17
+
18
+ # Instantiate the read operation.
19
+ #
20
+ # @example Instantiate the read.
21
+ # Read.new(get_more)
22
+ #
23
+ # @param [ Protocol::Query, Protocol::GetMore, Protocol::Command ] operation
24
+ # The read operation.
25
+ #
26
+ # @since 2.0.0
27
+ def initialize(operation)
28
+ @operation = operation
29
+ @database = operation.database
30
+ end
31
+
32
+ # Execute the read operation on the provided node. If the query failed, we
33
+ # will check if the failure was due to authorization and attempt the
34
+ # operation again. This could sometimes happen in the case of a step down
35
+ # or reconfiguration on the server side.
36
+ #
37
+ # @example Execute the operation.
38
+ # read.execute(node)
39
+ #
40
+ # @param [ Node ] node The node to execute the read on.
41
+ #
42
+ # @raise [ Failure ] If the read operation failed.
43
+ #
44
+ # @return [ Protocol::Reply ] The reply from the database.
45
+ #
46
+ # @since 2.0.0
47
+ def execute(node)
48
+ node.process(operation) do |reply|
49
+ if operation.failure?(reply)
50
+ if reply.unauthorized? && node.credentials.has_key?(database)
51
+ node.login(database, *node.credentials[database])
52
+ return execute(node)
53
+ else
54
+ raise operation.failure_exception(reply)
55
+ end
56
+ end
57
+ operation.results(reply)
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,57 @@
1
+ # encoding: utf-8
2
+ module Moped
3
+ module Operation
4
+
5
+ # Encapsulates behaviour for write operations.
6
+ #
7
+ # @since 2.0.0
8
+ class Write
9
+
10
+ # @!attribute concern
11
+ # @return [ Object ] The configured write concern.
12
+ # @!attribute database
13
+ # @return [ String ] The database the read is from.
14
+ # @!attribute operation
15
+ # @return [ Protocol::Insert, Protocol::Update, Protocol::Delete ]
16
+ # The write operation.
17
+ attr_reader :concern, :database, :operation
18
+
19
+ # Instantiate the write operation.
20
+ #
21
+ # @example Instantiate the write.
22
+ # Write.new(insert)
23
+ #
24
+ # @param [ Protocol::Insert, Protocol::Update, Protocol::Delete ] operation
25
+ # The write operation.
26
+ #
27
+ # @since 2.0.0
28
+ def initialize(operation, concern)
29
+ @operation = operation
30
+ @database = operation.database
31
+ @concern = concern
32
+ end
33
+
34
+ # Execute the write operation on the provided node. If the write concern
35
+ # is propagating, then the gle command will be piggybacked onto the
36
+ # initial write operation.
37
+ #
38
+ # @example Execute the operation.
39
+ # write.execute(node)
40
+ #
41
+ # @param [ Node ] node The node to execute the write on.
42
+ #
43
+ # @since 2.0.0
44
+ def execute(node)
45
+ propagate = concern.operation
46
+ if propagate
47
+ node.pipeline do
48
+ node.process(operation)
49
+ node.command(database, propagate)
50
+ end
51
+ else
52
+ node.process(operation)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -7,19 +7,80 @@ module Moped
7
7
  # @example
8
8
  # command = Moped::Protocol::Command.new :moped, ismaster: 1
9
9
  # socket.write command.serialize
10
+ #
11
+ # @since 1.0.0
10
12
  class Command < Query
11
13
 
12
- # @param [String, Symbol] database the database to run this command on
13
- # @param [Hash] command the command to run
14
- # @param [Hash] additional query options
14
+ # Determine if the provided reply message is a failure with respect to a
15
+ # command.
16
+ #
17
+ # @example Is the reply a command failure?
18
+ # command.failure?(reply)
19
+ #
20
+ # @param [ Reply ] reply The reply to the command.
21
+ #
22
+ # @return [ true, false ] If the reply is a failure.
23
+ #
24
+ # @since 2.0.0
25
+ def failure?(reply)
26
+ reply.command_failure?
27
+ end
28
+
29
+ # Get the exception specific to a failure of this particular operation.
30
+ #
31
+ # @example Get the failure exception.
32
+ # command.failure_exception(document)
33
+ #
34
+ # @param [ Moped::Protocol::Reply ] reply The reply from the database.
35
+ #
36
+ # @return [ Moped::Errors::OperationFailure ] The failure exception.
37
+ #
38
+ # @since 2.0.0
39
+ def failure_exception(reply)
40
+ Errors::OperationFailure.new(self, reply.documents.first)
41
+ end
42
+
43
+ # Instantiate the new command.
44
+ #
45
+ # @example Instantiate the new command.
46
+ # Moped::Protocol::Command.new(:moped_test, ismaster: 1)
47
+ #
48
+ # @param [ String, Symbol ] database The database to run the command on.
49
+ # @param [ Hash ] command The command to run.
50
+ # @param [ Hash ] options And additional query options.
51
+ #
52
+ # @since 1.0.0
15
53
  def initialize(database, command, options = {})
16
- super database, '$cmd', command, options.merge(limit: -1)
54
+ super(database, '$cmd', command, options.merge(limit: -1))
17
55
  end
18
56
 
57
+ # Provide the value that will be logged when the command runs.
58
+ #
59
+ # @example Provide the log inspection.
60
+ # command.log_inspect
61
+ #
62
+ # @return [ String ] The string value for logging.
63
+ #
64
+ # @since 1.0.0
19
65
  def log_inspect
20
66
  type = "COMMAND"
21
67
  "%-12s database=%s command=%s" % [type, database, selector.inspect]
22
68
  end
69
+
70
+ # Take the provided reply and return the expected results to api
71
+ # consumers. In the case of the command it's the first document.
72
+ #
73
+ # @example Get the expected results of the reply.
74
+ # command.results(reply)
75
+ #
76
+ # @param [ Moped::Protocol::Reply ] reply The reply from the database.
77
+ #
78
+ # @return [ Hash ] The first document in the reply.
79
+ #
80
+ # @since 2.0.0
81
+ def results(reply)
82
+ reply.documents.first
83
+ end
23
84
  end
24
85
  end
25
86
  end
@@ -22,7 +22,7 @@ module Moped
22
22
  # @param [String] nonce the nonce returned from running the getnonce
23
23
  # command.
24
24
  def initialize(database, username, password, nonce)
25
- super database, build_auth_command(username, password, nonce)
25
+ super(database, build_auth_command(username, password, nonce))
26
26
  end
27
27
 
28
28
  # @param [String] username
@@ -47,7 +47,6 @@ module Moped
47
47
  key: digest(username, password, nonce)
48
48
  }
49
49
  end
50
-
51
50
  end
52
51
  end
53
52
  end
@@ -90,6 +90,22 @@ module Moped
90
90
  "%-12s database=%s collection=%s selector=%s flags=%s" % [type, database, collection, selector.inspect, flags.inspect]
91
91
  end
92
92
 
93
+ private
94
+
95
+ # Duplicate the attributes in the delete that need to be.
96
+ #
97
+ # @api private
98
+ #
99
+ # @example Clone the delete.
100
+ # delete.clone
101
+ #
102
+ # @param [ Delete ] The delete that was cloned from.
103
+ #
104
+ # @since 2.0.0
105
+ def initialize_copy(_)
106
+ @selector = selector.dup
107
+ @flags = flags.dup
108
+ end
93
109
  end
94
110
  end
95
111
  end
@@ -3,15 +3,7 @@ module Moped
3
3
 
4
4
  # The Protocol class for retrieving more documents from a cursor.
5
5
  #
6
- # @example Get more results using database default limit
7
- # insert = GetMore.new "moped", "people", 29301021, 0
8
- #
9
- # @example Get more results using custom limit
10
- # insert = Insert.new "moped", "people", 29301021, 10
11
- #
12
- # @example Setting the request id
13
- # insert = Insert.new "moped", "people", 29301021, 10,
14
- # request_id: 123
6
+ # @since 1.0.0
15
7
  class GetMore
16
8
  include Message
17
9
 
@@ -29,54 +21,118 @@ module Moped
29
21
  # @return [Number] the operation code of this message
30
22
  int32 :op_code
31
23
 
32
- int32 :reserved # reserved for future use
24
+ int32 :reserved # reserved for future use
33
25
 
34
26
  # @attribute
35
27
  # @return [String] the namespaced collection name
36
- cstring :full_collection_name
28
+ cstring :full_collection_name
37
29
 
38
30
  # @attribute
39
31
  # @return [Number] the number of documents to return
40
- int32 :limit
32
+ int32 :limit
41
33
 
42
34
  # @attribute
43
35
  # @return [Number] the id of the cursor to get more documents from
44
- int64 :cursor_id
36
+ int64 :cursor_id
45
37
 
46
38
  finalize
47
39
 
48
- undef op_code
49
- # @return [Number] OP_GETMORE operation code (2005)
50
- def op_code
51
- 2005
52
- end
40
+ # @!attribute collection
41
+ # @return [ String ] The collection to query.
42
+ # @!attribute database
43
+ # @return [ String ] The database to query
44
+ attr_reader :collection, :database
53
45
 
54
- # @return [String, Symbol] the database this insert targets
55
- attr_reader :database
46
+ # Determine if the provided reply message is a failure with respect to a
47
+ # get more operation.
48
+ #
49
+ # @example Is the reply a query failure?
50
+ # get_more.failure?(reply)
51
+ #
52
+ # @param [ Reply ] reply The reply to the get more.
53
+ #
54
+ # @return [ true, false ] If the reply is a failure.
55
+ #
56
+ # @since 2.0.0
57
+ def failure?(reply)
58
+ reply.cursor_not_found? || reply.query_failure?
59
+ end
56
60
 
57
- # @return [String, Symbol] the collection this insert targets
58
- attr_reader :collection
61
+ # Get the exception specific to a failure of this particular operation.
62
+ #
63
+ # @example Get the failure exception.
64
+ # get_more.failure_exception(document)
65
+ #
66
+ # @param [ Moped::Protocol::Reply ] reply The reply from the database.
67
+ #
68
+ # @return [ Moped::Errors::CursorNotFound ] The failure exception.
69
+ #
70
+ # @since 2.0.0
71
+ def failure_exception(reply)
72
+ if reply.cursor_not_found?
73
+ Errors::CursorNotFound.new(self, cursor_id)
74
+ else
75
+ Errors::QueryFailure.new(self, reply.documents.first)
76
+ end
77
+ end
59
78
 
60
- # Create a new +GetMore+ command. The +database+ and +collection+ arguments
61
- # are joined together to set the +full_collection_name+.
79
+ # Create a new GetMore command. The database and collection arguments
80
+ # are joined together to set the full_collection_name.
81
+ #
82
+ # @example Get more results using database default limit.
83
+ # GetMore.new("moped", "people", 29301021, 0)
62
84
  #
63
- # @example
64
- # GetMore.new "moped", "users", 29301021, 10, request_id: 123
85
+ # @example Get more results using custom limit.
86
+ # GetMore.new("moped", "people", 29301021, 10)
87
+ #
88
+ # @example Get more with a request id.
89
+ # GetMore.new("moped", "people", 29301021, 10, request_id: 123)
90
+ #
91
+ # @param [ String ] database The database name.
92
+ # @param [ String ] collection The collection name.
93
+ # @param [ Integer ] cursor_id The id of the cursor.
94
+ # @param [ Integer ] limit The number of documents to limit.
95
+ # @param [ Hash ] options The get more options.
96
+ #
97
+ # @option options [ Integer ] :request_id The operation's request id.
98
+ #
99
+ # @since 1.0.0
65
100
  def initialize(database, collection, cursor_id, limit, options = {})
66
- @database = database
101
+ @database = database
67
102
  @collection = collection
68
-
69
103
  @full_collection_name = "#{database}.#{collection}"
70
- @cursor_id = cursor_id
71
- @limit = limit
72
- @request_id = options[:request_id]
104
+ @cursor_id = cursor_id
105
+ @limit = limit
106
+ @request_id = options[:request_id]
73
107
  end
74
108
 
109
+ # Provide the value that will be logged when the get more runs.
110
+ #
111
+ # @example Provide the log inspection.
112
+ # get_more.log_inspect
113
+ #
114
+ # @return [ String ] The string value for logging.
115
+ #
116
+ # @since 1.0.0
75
117
  def log_inspect
76
118
  type = "GET_MORE"
77
119
  "%-12s database=%s collection=%s limit=%s cursor_id=%s" % [type, database, collection, limit, cursor_id]
78
120
  end
79
121
 
122
+ undef op_code
123
+
124
+ # Get the code for a get more operation.
125
+ #
126
+ # @example Get the operation code.
127
+ # get_more.op_code
128
+ #
129
+ # @return [ Integer ] OP_GETMORE operation code (2005).
130
+ #
131
+ # @since 1.0.0
132
+ def op_code
133
+ 2005
134
+ end
135
+
80
136
  # Receive replies to the message.
81
137
  #
82
138
  # @example Receive replies.
@@ -90,6 +146,21 @@ module Moped
90
146
  def receive_replies(connection)
91
147
  connection.read
92
148
  end
149
+
150
+ # Take the provided reply and return the expected results to api
151
+ # consumers.
152
+ #
153
+ # @example Get the expected results of the reply.
154
+ # get_more.results(reply)
155
+ #
156
+ # @param [ Moped::Protocol::Reply ] reply The reply from the database.
157
+ #
158
+ # @return [ Moped::Protocol::Reply ] The reply.
159
+ #
160
+ # @since 2.0.0
161
+ def results(reply)
162
+ reply
163
+ end
93
164
  end
94
165
  end
95
166
  end
@@ -90,6 +90,23 @@ module Moped
90
90
 
91
91
  "%-12s database=%s collection=%s documents=%s flags=%s" % [type, database, collection, documents.inspect, flags.inspect]
92
92
  end
93
+
94
+ private
95
+
96
+ # Duplicate the attributes in the insert that need to be.
97
+ #
98
+ # @api private
99
+ #
100
+ # @example Clone the insert.
101
+ # insert.clone
102
+ #
103
+ # @param [ Insert ] The insert that was cloned from.
104
+ #
105
+ # @since 2.0.0
106
+ def initialize_copy(_)
107
+ @documents = documents.dup
108
+ @flags = flags.dup
109
+ end
93
110
  end
94
111
  end
95
112
  end