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.

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
@@ -67,8 +67,8 @@ module Moped
67
67
  #
68
68
  # @since 1.2.10
69
69
  def command_failure?
70
- result = documents[0]
71
- result["ok"] != 1 || error_message(result)
70
+ result = documents.first
71
+ (result["ok"] != 1.0 && result["ok"] != true) || error?
72
72
  end
73
73
 
74
74
  # Was the provided cursor id not found on the server?
@@ -83,17 +83,29 @@ module Moped
83
83
  flags.include?(:cursor_not_found)
84
84
  end
85
85
 
86
+ # Check if the first returned document in the reply is an error result.
87
+ #
88
+ # @example Is the first document in the reply an error?
89
+ # reply.error?
90
+ #
91
+ # @return [ true, false ] If the first document is an error.
92
+ #
93
+ # @since 2.0.0
94
+ def error?
95
+ result = documents.first
96
+ result && error_message(result)
97
+ end
98
+
86
99
  # Did the query fail on the server?
87
100
  #
88
101
  # @example Did the query fail?
89
- # reply.query_failed?
102
+ # reply.query_failure?
90
103
  #
91
104
  # @return [ true, false ] If the query failed.
92
105
  #
93
106
  # @since 1.2.0
94
- def query_failed?
95
- result = documents[0]
96
- flags.include?(:query_failure) || (result && (result["err"] || result["errmsg"] || result["$err"]))
107
+ def query_failure?
108
+ flags.include?(:query_failure) || error?
97
109
  end
98
110
 
99
111
  # Is the reply an error message that we are not authorized for the query
@@ -144,7 +156,7 @@ module Moped
144
156
  def deserialize_documents(buffer)
145
157
  documents = []
146
158
  count.times do
147
- documents << BSON::Document.deserialize(buffer)
159
+ documents << BSON::Document.from_bson(buffer)
148
160
  end
149
161
  @documents = documents
150
162
  end
@@ -152,7 +164,6 @@ module Moped
152
164
  def error_message(result)
153
165
  result["err"] || result["errmsg"] || result["$err"]
154
166
  end
155
-
156
167
  end
157
168
  end
158
169
  end
@@ -105,6 +105,24 @@ module Moped
105
105
  update.inspect,
106
106
  flags.inspect]
107
107
  end
108
+
109
+ private
110
+
111
+ # Duplicate the attributes in the update that need to be.
112
+ #
113
+ # @api private
114
+ #
115
+ # @example Clone the update.
116
+ # update.clone
117
+ #
118
+ # @param [ Update ] The update that was cloned from.
119
+ #
120
+ # @since 2.0.0
121
+ def initialize_copy(_)
122
+ @selector = selector.dup
123
+ @update = update.dup
124
+ @flags = flags.dup
125
+ end
108
126
  end
109
127
  end
110
128
  end
data/lib/moped/query.rb CHANGED
@@ -1,3 +1,6 @@
1
+ # encoding: utf-8
2
+ require "moped/cursor"
3
+
1
4
  module Moped
2
5
 
3
6
  # The +Query+ class encapsulates all of the logic related to building
@@ -112,15 +115,19 @@ module Moped
112
115
  #
113
116
  # @since 1.0.0
114
117
  def first
115
- reply = session.context.query(
116
- operation.database,
117
- operation.collection,
118
- operation.selector,
119
- fields: operation.fields,
120
- flags: operation.flags,
121
- skip: operation.skip,
122
- limit: -1
123
- )
118
+ reply = read_preference.with_node(cluster) do |node|
119
+ node.query(
120
+ operation.database,
121
+ operation.collection,
122
+ operation.selector,
123
+ query_options(
124
+ fields: operation.fields,
125
+ flags: operation.flags,
126
+ skip: operation.skip,
127
+ limit: -1
128
+ )
129
+ )
130
+ end
124
131
  reply.documents.first
125
132
  end
126
133
  alias :one :first
@@ -252,7 +259,7 @@ module Moped
252
259
  command[:fields] = operation.fields if operation.fields
253
260
  command[:update] = change unless options[:remove]
254
261
 
255
- result = session.with(consistency: :strong) do |sess|
262
+ result = session.with(read: :primary) do |sess|
256
263
  sess.command(command)["value"]
257
264
  end
258
265
 
@@ -269,11 +276,12 @@ module Moped
269
276
  #
270
277
  # @since 1.0.0
271
278
  def remove
272
- session.with(consistency: :strong) do |session|
273
- session.context.remove(
279
+ cluster.with_primary do |node|
280
+ node.remove(
274
281
  operation.database,
275
282
  operation.collection,
276
283
  operation.basic_selector,
284
+ write_concern,
277
285
  flags: [ :remove_first ]
278
286
  )
279
287
  end
@@ -288,11 +296,12 @@ module Moped
288
296
  #
289
297
  # @since 1.0.0
290
298
  def remove_all
291
- session.with(consistency: :strong) do |session|
292
- session.context.remove(
299
+ cluster.with_primary do |node|
300
+ node.remove(
293
301
  operation.database,
294
302
  operation.collection,
295
- operation.basic_selector
303
+ operation.basic_selector,
304
+ write_concern
296
305
  )
297
306
  end
298
307
  end
@@ -369,12 +378,13 @@ module Moped
369
378
  #
370
379
  # @since 1.0.0
371
380
  def update(change, flags = nil)
372
- session.with(consistency: :strong) do |session|
373
- session.context.update(
381
+ cluster.with_primary do |node|
382
+ node.update(
374
383
  operation.database,
375
384
  operation.collection,
376
385
  operation.selector["$query"] || operation.selector,
377
386
  change,
387
+ write_concern,
378
388
  flags: flags
379
389
  )
380
390
  end
@@ -412,6 +422,22 @@ module Moped
412
422
  update(change, [ :upsert ])
413
423
  end
414
424
 
425
+ def write_concern
426
+ session.write_concern
427
+ end
428
+
429
+ def read_preference
430
+ session.read_preference
431
+ end
432
+
433
+ def cluster
434
+ session.cluster
435
+ end
436
+
437
+ def query_options(options)
438
+ read_preference.query_options(options)
439
+ end
440
+
415
441
  private
416
442
 
417
443
  def initialize_copy(other)
@@ -0,0 +1,49 @@
1
+ # encoding: utf-8
2
+ require "moped/read_preference/selectable"
3
+ require "moped/read_preference/nearest"
4
+ require "moped/read_preference/primary"
5
+ require "moped/read_preference/primary_preferred"
6
+ require "moped/read_preference/secondary"
7
+ require "moped/read_preference/secondary_preferred"
8
+
9
+ module Moped
10
+
11
+ # Provides behaviour around getting various read preference implementations.
12
+ #
13
+ # @since 2.0.0
14
+ module ReadPreference
15
+ extend self
16
+
17
+ # Hash lookup for the read preference classes based off the symbols
18
+ # provided in configuration.
19
+ #
20
+ # @since 2.0.0
21
+ PREFERENCES = {
22
+ nearest: Nearest,
23
+ primary: Primary,
24
+ primary_preferred: PrimaryPreferred,
25
+ secondary: Secondary,
26
+ secondary_preferred: SecondaryPreferred
27
+ }.freeze
28
+
29
+ # Get a read preference for the provided name. Valid names are:
30
+ # - :nearest
31
+ # - :primary
32
+ # - :primary_preferred
33
+ # - :secondary
34
+ # - :secondary_preferred
35
+ #
36
+ # @example Get the primary read preference.
37
+ # Moped::ReadPreference.get(:primary)
38
+ #
39
+ # @param [ Symbol ] name The name of the preference.
40
+ # @param [ Array<Hash> ] tags The tag sets to match the node on.
41
+ #
42
+ # @return [ Object ] The appropriate read preference.
43
+ #
44
+ # @since 2.0.0
45
+ def get(name, tags = nil)
46
+ PREFERENCES.fetch(name.to_sym).new(tags)
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,55 @@
1
+ # encoding: utf-8
2
+ module Moped
3
+ module ReadPreference
4
+
5
+ # Encapsulates behaviour around a nearest read preference.
6
+ #
7
+ # @since 2.0.0
8
+ class Nearest
9
+ include Selectable
10
+
11
+ # Get the name for the read preference on the server side.
12
+ #
13
+ # @example Get the name of the read preference.
14
+ # nearest.name
15
+ #
16
+ # @return [ Symbol ] :nearest.
17
+ #
18
+ # @since 2.0.0
19
+ def name
20
+ :nearest
21
+ end
22
+
23
+ # Execute the provided block on the node with the lowest latency,
24
+ # allowing either primary or secondary.
25
+ #
26
+ # @example Read from the nearest node in the cluster.
27
+ # preference.with_node(cluster) do |node|
28
+ # node.command(ismaster: 1)
29
+ # end
30
+ #
31
+ # @note If tag sets are provided then selection will need to
32
+ # match the provided tags.
33
+ #
34
+ # @param [ Cluster ] cluster The cluster of nodes to select from.
35
+ # @param [ Proc ] block The block to execute on the node.
36
+ #
37
+ # @raise [ Errors::ConnectionFailure ] If no node was available in the
38
+ # cluster.
39
+ #
40
+ # @return [ Object ] The result of the block.
41
+ #
42
+ # @since 2.0.0
43
+ def with_node(cluster, &block)
44
+ with_retry(cluster) do
45
+ nearest = cluster.nodes.sort_by(&:latency).first
46
+ if nearest
47
+ block.call(nearest)
48
+ else
49
+ raise Errors::ConnectionFailure, "No nodes available to select in the cluster"
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,60 @@
1
+ # encoding: utf-8
2
+ module Moped
3
+ module ReadPreference
4
+
5
+ # Encapsulates behaviour around a primary read preference.
6
+ #
7
+ # @since 2.0.0
8
+ class Primary
9
+ include Selectable
10
+
11
+ # Get the name for the read preference on the server side.
12
+ #
13
+ # @example Get the name of the read preference.
14
+ # primary.name
15
+ #
16
+ # @return [ Symbol ] :primary.
17
+ #
18
+ # @since 2.0.0
19
+ def name
20
+ :primary
21
+ end
22
+
23
+ # Get the provided options as query options for this read preference.
24
+ #
25
+ # @example Get the query options.
26
+ # preference.query_options({})
27
+ #
28
+ # @param [ Hash ] options The existing options for the query.
29
+ #
30
+ # @return [ Hash ] The options plus additional query options.
31
+ #
32
+ # @since 2.0.0
33
+ def query_options(options)
34
+ options
35
+ end
36
+
37
+ # Select a primary node from the cluster. If no primary node is available
38
+ # then an exception will be raised.
39
+ #
40
+ # @example Select a primary node from the cluster.
41
+ # preference.with_node(cluster) do |node|
42
+ # node.command(ismaster: 1)
43
+ # end
44
+ #
45
+ # @param [ Cluster ] cluster The cluster of nodes to select from.
46
+ # @param [ Proc ] block The block to execute on the node.
47
+ #
48
+ # @raise [ Errors::ConnectionFailure ] If no primary node was available in the cluster.
49
+ #
50
+ # @return [ Object ] The result of the block.
51
+ #
52
+ # @since 2.0.0
53
+ def with_node(cluster, &block)
54
+ with_retry(cluster) do
55
+ cluster.with_primary(&block)
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,55 @@
1
+ # encoding: utf-8
2
+ module Moped
3
+ module ReadPreference
4
+
5
+ # Encapsulates behaviour around a primary preferred read preference.
6
+ #
7
+ # @since 2.0.0
8
+ class PrimaryPreferred
9
+ include Selectable
10
+
11
+ # Get the name for the read preference on the server side.
12
+ #
13
+ # @example Get the name of the read preference.
14
+ # primary_preferred.name
15
+ #
16
+ # @return [ Symbol ] :primaryPreferred.
17
+ #
18
+ # @since 2.0.0
19
+ def name
20
+ :primaryPreferred
21
+ end
22
+
23
+ # Select a primary node from the cluster. If no primary node is available
24
+ # then attempt to select a secondary. If no secondary is available then
25
+ # an exception will be raised.
26
+ #
27
+ # @example Prefer to with_node a primary node from the cluster.
28
+ # preference.with_node(cluster) do |node|
29
+ # node.command(ismaster: 1)
30
+ # end
31
+ #
32
+ # @note If tag sets are provided then secondary with_nodeion will need to
33
+ # match the provided tags.
34
+ #
35
+ # @param [ Cluster ] cluster The cluster of nodes to select from.
36
+ # @param [ Proc ] block The block to execute on the node.
37
+ #
38
+ # @raise [ Errors::ConnectionFailure ] If no primary or secondary node was
39
+ # available in the cluster.
40
+ #
41
+ # @return [ Object ] The result of the block.
42
+ #
43
+ # @since 2.0.0
44
+ def with_node(cluster, &block)
45
+ with_retry(cluster) do
46
+ begin
47
+ cluster.with_primary(&block)
48
+ rescue Errors::ConnectionFailure
49
+ cluster.with_secondary(&block)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,50 @@
1
+ # encoding: utf-8
2
+ module Moped
3
+ module ReadPreference
4
+
5
+ # Encapsulates behaviour around a secondary read preference.
6
+ #
7
+ # @since 2.0.0
8
+ class Secondary
9
+ include Selectable
10
+
11
+ # Get the name for the read preference on the server side.
12
+ #
13
+ # @example Get the name of the read preference.
14
+ # secondary.name
15
+ #
16
+ # @return [ Symbol ] :secondary.
17
+ #
18
+ # @since 2.0.0
19
+ def name
20
+ :secondary
21
+ end
22
+
23
+ # Select a secondary node from the cluster. If no secondary is available then
24
+ # an exception will be raised.
25
+ #
26
+ # @example Read from a secondary node from the cluster.
27
+ # preference.with_node(cluster) do |node|
28
+ # node.command(ismaster: 1)
29
+ # end
30
+ #
31
+ # @note If tag sets are provided then secondary selection will need to
32
+ # match the provided tags.
33
+ #
34
+ # @param [ Cluster ] cluster The cluster of nodes to select from.
35
+ # @param [ Proc ] block The block to execute on the node.
36
+ #
37
+ # @raise [ Errors::ConnectionFailure ] If no secondary node was available
38
+ # in the cluster.
39
+ #
40
+ # @return [ Object ] The result of the block.
41
+ #
42
+ # @since 2.0.0
43
+ def with_node(cluster, &block)
44
+ with_retry(cluster) do
45
+ cluster.with_secondary(&block)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end