mongo 2.5.0.beta → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/lib/mongo/address.rb +1 -1
- data/lib/mongo/address/unix.rb +1 -1
- data/lib/mongo/auth/user.rb +0 -5
- data/lib/mongo/auth/user/view.rb +4 -4
- data/lib/mongo/bulk_write.rb +60 -32
- data/lib/mongo/client.rb +44 -8
- data/lib/mongo/cluster.rb +14 -12
- data/lib/mongo/cluster/periodic_executor.rb +106 -0
- data/lib/mongo/cluster/{cursor_reaper.rb → reapers/cursor_reaper.rb} +5 -37
- data/lib/mongo/cluster/reapers/socket_reaper.rb +59 -0
- data/lib/mongo/collection.rb +9 -6
- data/lib/mongo/collection/view.rb +2 -2
- data/lib/mongo/collection/view/builder/aggregation.rb +2 -1
- data/lib/mongo/collection/view/builder/find_command.rb +1 -1
- data/lib/mongo/collection/view/change_stream.rb +14 -1
- data/lib/mongo/collection/view/map_reduce.rb +30 -13
- data/lib/mongo/collection/view/readable.rb +5 -5
- data/lib/mongo/collection/view/writable.rb +98 -51
- data/lib/mongo/error.rb +3 -0
- data/lib/mongo/error/invalid_txt_record.rb +27 -0
- data/lib/mongo/error/invalid_uri.rb +7 -6
- data/lib/mongo/error/mismatched_domain.rb +27 -0
- data/lib/mongo/error/no_srv_records.rb +26 -0
- data/lib/mongo/error/unsupported_features.rb +0 -18
- data/lib/mongo/index/view.rb +2 -2
- data/lib/mongo/operation.rb +1 -0
- data/lib/mongo/operation/causally_consistent.rb +33 -0
- data/lib/mongo/operation/commands.rb +2 -1
- data/lib/mongo/operation/commands/aggregate.rb +2 -7
- data/lib/mongo/operation/commands/count.rb +27 -0
- data/lib/mongo/operation/commands/distinct.rb +27 -0
- data/lib/mongo/operation/commands/find.rb +3 -1
- data/lib/mongo/operation/commands/map_reduce.rb +1 -0
- data/lib/mongo/operation/commands/parallel_scan.rb +1 -0
- data/lib/mongo/operation/specifiable.rb +12 -0
- data/lib/mongo/operation/uses_command_op_msg.rb +36 -5
- data/lib/mongo/operation/write.rb +0 -5
- data/lib/mongo/operation/write/bulk/bulkable.rb +4 -8
- data/lib/mongo/operation/write/bulk/mergable.rb +2 -0
- data/lib/mongo/operation/write/command/create_index.rb +19 -0
- data/lib/mongo/operation/write/command/create_user.rb +19 -0
- data/lib/mongo/operation/write/command/delete.rb +1 -2
- data/lib/mongo/operation/write/command/drop_index.rb +19 -0
- data/lib/mongo/operation/write/command/insert.rb +1 -2
- data/lib/mongo/operation/write/command/remove_user.rb +19 -0
- data/lib/mongo/operation/write/command/update.rb +1 -2
- data/lib/mongo/operation/write/command/update_user.rb +19 -0
- data/lib/mongo/operation/write/write_command_enabled.rb +1 -3
- data/lib/mongo/protocol/compressed.rb +2 -1
- data/lib/mongo/protocol/serializers.rb +6 -6
- data/lib/mongo/retryable.rb +48 -5
- data/lib/mongo/server.rb +15 -0
- data/lib/mongo/server/connection.rb +21 -1
- data/lib/mongo/server/connection_pool.rb +3 -0
- data/lib/mongo/server/connection_pool/queue.rb +50 -5
- data/lib/mongo/server/description.rb +11 -3
- data/lib/mongo/server/description/features.rb +26 -7
- data/lib/mongo/session.rb +133 -6
- data/lib/mongo/session/server_session.rb +30 -0
- data/lib/mongo/session/session_pool.rb +20 -20
- data/lib/mongo/uri.rb +88 -44
- data/lib/mongo/uri/srv_protocol.rb +158 -0
- data/lib/mongo/version.rb +1 -1
- data/lib/mongo/write_concern/normalizable.rb +12 -0
- data/mongo.gemspec +1 -2
- data/spec/mongo/address_spec.rb +12 -0
- data/spec/mongo/auth/user/view_spec.rb +1 -5
- data/spec/mongo/bulk_write_spec.rb +232 -401
- data/spec/mongo/change_stream_examples_spec.rb +150 -0
- data/spec/mongo/client_spec.rb +142 -2
- data/spec/mongo/cluster/cursor_reaper_spec.rb +0 -70
- data/spec/mongo/cluster/socket_reaper_spec.rb +32 -0
- data/spec/mongo/cluster_spec.rb +11 -7
- data/spec/mongo/collection/view/aggregation_spec.rb +46 -1
- data/spec/mongo/collection/view/builder/find_command_spec.rb +15 -0
- data/spec/mongo/collection/view/change_stream_spec.rb +79 -12
- data/spec/mongo/collection/view/map_reduce_spec.rb +120 -4
- data/spec/mongo/collection/view/readable_spec.rb +23 -5
- data/spec/mongo/collection_spec.rb +292 -102
- data/spec/mongo/command_monitoring_spec.rb +26 -32
- data/spec/mongo/crud_spec.rb +1 -1
- data/spec/mongo/cursor_spec.rb +2 -3
- data/spec/mongo/database_spec.rb +30 -14
- data/spec/mongo/dns_seedlist_discovery_spec.rb +94 -0
- data/spec/mongo/grid/fs_bucket_spec.rb +1 -1
- data/spec/mongo/grid/stream/write_spec.rb +1 -1
- data/spec/mongo/index/view_spec.rb +8 -46
- data/spec/mongo/operation/write/bulk/delete_spec.rb +2 -2
- data/spec/mongo/operation/write/bulk/insert_spec.rb +2 -10
- data/spec/mongo/operation/write/{create_index_spec.rb → command/create_index_spec.rb} +2 -6
- data/spec/mongo/operation/write/command/delete_spec.rb +35 -7
- data/spec/mongo/operation/write/{drop_index_spec.rb → command/drop_index_spec.rb} +1 -1
- data/spec/mongo/operation/write/command/insert_spec.rb +37 -6
- data/spec/mongo/operation/write/{remove_user_spec.rb → command/remove_user_spec.rb} +2 -6
- data/spec/mongo/operation/write/command/update_spec.rb +34 -7
- data/spec/mongo/operation/write/{update_user_spec.rb → command/update_user_spec.rb} +1 -1
- data/spec/mongo/operation/write/create_user_spec.rb +1 -1
- data/spec/mongo/operation/write/delete_spec.rb +1 -1
- data/spec/mongo/operation/write/insert_spec.rb +2 -10
- data/spec/mongo/operation/write/update_spec.rb +3 -15
- data/spec/mongo/retryable_spec.rb +1 -1
- data/spec/mongo/retryable_writes_spec.rb +815 -0
- data/spec/mongo/server/connection_pool/queue_spec.rb +35 -2
- data/spec/mongo/server/connection_pool_spec.rb +234 -1
- data/spec/mongo/server/connection_spec.rb +10 -6
- data/spec/mongo/server/description/features_spec.rb +51 -37
- data/spec/mongo/server/description_spec.rb +6 -3
- data/spec/mongo/server_spec.rb +87 -0
- data/spec/mongo/session/server_session_spec.rb +43 -0
- data/spec/mongo/session/session_pool_spec.rb +63 -27
- data/spec/mongo/session_spec.rb +247 -0
- data/spec/mongo/shell_examples_spec.rb +2 -2
- data/spec/mongo/uri/srv_protocol_spec.rb +933 -0
- data/spec/mongo/uri_spec.rb +42 -3
- data/spec/mongo/write_concern/acknowledged_spec.rb +11 -0
- data/spec/mongo/write_concern/unacknowledged_spec.rb +11 -0
- data/spec/spec_helper.rb +11 -25
- data/spec/support/authorization.rb +2 -1
- data/spec/support/connection_string.rb +8 -4
- data/spec/support/crud.rb +38 -24
- data/spec/support/crud/write.rb +30 -3
- data/spec/support/crud_tests/read/aggregate-out.yml +21 -0
- data/spec/support/crud_tests/write/bulkWrite-arrayFilters.yml +44 -0
- data/spec/support/crud_tests/write/findOneAndUpdate-arrayFilters.yml +1 -1
- data/spec/support/crud_tests/write/insertMany.yml +1 -3
- data/spec/support/crud_tests/write/replaceOne.yml +1 -1
- data/spec/support/crud_tests/write/updateMany-arrayFilters.yml +1 -1
- data/spec/support/crud_tests/write/updateOne-arrayFilters.yml +1 -1
- data/spec/support/dns_seedlist_discovery_tests/longer-parent-in-return.yml +11 -0
- data/spec/support/dns_seedlist_discovery_tests/misformatted-option.yml +5 -0
- data/spec/support/dns_seedlist_discovery_tests/no-results.yml +5 -0
- data/spec/support/dns_seedlist_discovery_tests/not-enough-parts.yml +5 -0
- data/spec/support/dns_seedlist_discovery_tests/one-result-default-port.yml +10 -0
- data/spec/support/dns_seedlist_discovery_tests/one-txt-record-multiple-strings.yml +10 -0
- data/spec/support/dns_seedlist_discovery_tests/one-txt-record.yml +11 -0
- data/spec/support/dns_seedlist_discovery_tests/parent-part-mismatch1.yml +5 -0
- data/spec/support/dns_seedlist_discovery_tests/parent-part-mismatch2.yml +5 -0
- data/spec/support/dns_seedlist_discovery_tests/parent-part-mismatch3.yml +5 -0
- data/spec/support/dns_seedlist_discovery_tests/parent-part-mismatch4.yml +5 -0
- data/spec/support/dns_seedlist_discovery_tests/parent-part-mismatch5.yml +5 -0
- data/spec/support/dns_seedlist_discovery_tests/returned-parent-too-short.yml +5 -0
- data/spec/support/dns_seedlist_discovery_tests/returned-parent-wrong.yml +5 -0
- data/spec/support/dns_seedlist_discovery_tests/two-results-default-port.yml +11 -0
- data/spec/support/dns_seedlist_discovery_tests/two-results-nonstandard-port.yml +11 -0
- data/spec/support/dns_seedlist_discovery_tests/two-txt-records.yml +5 -0
- data/spec/support/dns_seedlist_discovery_tests/txt-record-not-allowed-option.yml +5 -0
- data/spec/support/dns_seedlist_discovery_tests/txt-record-with-overridden-ssl-option.yml +11 -0
- data/spec/support/dns_seedlist_discovery_tests/txt-record-with-overridden-uri-option.yml +11 -0
- data/spec/support/dns_seedlist_discovery_tests/txt-record-with-unallowed-option.yml +5 -0
- data/spec/support/dns_seedlist_discovery_tests/uri-with-port.yml +5 -0
- data/spec/support/dns_seedlist_discovery_tests/uri-with-two-hosts.yml +5 -0
- data/spec/support/retryable_writes_tests/bulkWrite.yml +305 -0
- data/spec/support/retryable_writes_tests/deleteOne.yml +51 -0
- data/spec/support/retryable_writes_tests/findOneAndDelete.yml +52 -0
- data/spec/support/retryable_writes_tests/findOneAndReplace.yml +57 -0
- data/spec/support/retryable_writes_tests/findOneAndUpdate.yml +56 -0
- data/spec/support/retryable_writes_tests/insertMany.yml +72 -0
- data/spec/support/retryable_writes_tests/insertOne.yml +55 -0
- data/spec/support/retryable_writes_tests/replaceOne.yml +60 -0
- data/spec/support/retryable_writes_tests/updateOne.yml +120 -0
- data/spec/support/shared/session.rb +525 -24
- metadata +437 -350
- metadata.gz.sig +0 -0
- data/lib/mongo/operation/commands/user_query.rb +0 -72
- data/lib/mongo/operation/write/create_index.rb +0 -67
- data/lib/mongo/operation/write/create_user.rb +0 -50
- data/lib/mongo/operation/write/drop_index.rb +0 -63
- data/lib/mongo/operation/write/remove_user.rb +0 -48
- data/lib/mongo/operation/write/update_user.rb +0 -50
@@ -124,6 +124,11 @@ module Mongo
|
|
124
124
|
# @since 2.0.0
|
125
125
|
PRIMARY = 'ismaster'.freeze
|
126
126
|
|
127
|
+
# Constant for reading primary host field from config.
|
128
|
+
#
|
129
|
+
# @since 2.5.0
|
130
|
+
PRIMARY_HOST = 'primary'.freeze
|
131
|
+
|
127
132
|
# Constant for reading secondary info from config.
|
128
133
|
#
|
129
134
|
# @since 2.0.0
|
@@ -169,7 +174,8 @@ module Mongo
|
|
169
174
|
# @since 2.0.6
|
170
175
|
EXCLUDE_FOR_COMPARISON = [ LOCAL_TIME,
|
171
176
|
LAST_WRITE,
|
172
|
-
OPERATION_TIME
|
177
|
+
OPERATION_TIME,
|
178
|
+
Operation::CLUSTER_TIME ].freeze
|
173
179
|
|
174
180
|
# @return [ Address ] address The server's address.
|
175
181
|
attr_reader :address
|
@@ -258,7 +264,7 @@ module Mongo
|
|
258
264
|
def initialize(address, config = {}, average_round_trip_time = 0)
|
259
265
|
@address = address
|
260
266
|
@config = config
|
261
|
-
@features = Features.new(wire_versions)
|
267
|
+
@features = Features.new(wire_versions, me)
|
262
268
|
@average_round_trip_time = average_round_trip_time
|
263
269
|
end
|
264
270
|
|
@@ -464,7 +470,9 @@ module Mongo
|
|
464
470
|
#
|
465
471
|
# @since 2.0.0
|
466
472
|
def primary?
|
467
|
-
!!config[PRIMARY] &&
|
473
|
+
!!config[PRIMARY] &&
|
474
|
+
(config[PRIMARY_HOST].nil? || config[PRIMARY_HOST] == address.to_s) &&
|
475
|
+
!replica_set_name.nil?
|
468
476
|
end
|
469
477
|
|
470
478
|
# Get the name of the replica set the server belongs to, returns nil if
|
@@ -38,10 +38,22 @@ module Mongo
|
|
38
38
|
:users_info => 2
|
39
39
|
}.freeze
|
40
40
|
|
41
|
+
# Error message if the server is too old for this version of the driver.
|
42
|
+
#
|
43
|
+
# @since 2.5.0
|
44
|
+
SERVER_TOO_OLD = "Server at (%s) reports wire version (%s), but this version of the Ruby driver " +
|
45
|
+
"requires at least (%s)."
|
46
|
+
|
47
|
+
# Error message if the driver is too old for the version of the server.
|
48
|
+
#
|
49
|
+
# @since 2.5.0
|
50
|
+
DRIVER_TOO_OLD = "Server at (%s) requires wire version (%s), but this version of the Ruby driver " +
|
51
|
+
"only supports up to (%s)."
|
52
|
+
|
41
53
|
# The wire protocol versions that this version of the driver supports.
|
42
54
|
#
|
43
55
|
# @since 2.0.0
|
44
|
-
DRIVER_WIRE_VERSIONS = (
|
56
|
+
DRIVER_WIRE_VERSIONS = (2..6).freeze
|
45
57
|
|
46
58
|
# Create the methods for each mapping to tell if they are supported.
|
47
59
|
#
|
@@ -74,17 +86,24 @@ module Mongo
|
|
74
86
|
# versions.
|
75
87
|
#
|
76
88
|
# @since 2.0.0
|
77
|
-
def initialize(server_wire_versions)
|
89
|
+
def initialize(server_wire_versions, address = nil)
|
78
90
|
@server_wire_versions = server_wire_versions
|
79
|
-
check_driver_support!
|
91
|
+
check_driver_support!(address) unless server_wire_versions == ZERO_RANGE
|
80
92
|
end
|
81
93
|
|
82
94
|
private
|
83
95
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
96
|
+
ZERO_RANGE = (0..0).freeze
|
97
|
+
|
98
|
+
def check_driver_support!(address)
|
99
|
+
if DRIVER_WIRE_VERSIONS.min > server_wire_versions.max
|
100
|
+
raise Error::UnsupportedFeatures.new(SERVER_TOO_OLD % [address,
|
101
|
+
server_wire_versions.max,
|
102
|
+
DRIVER_WIRE_VERSIONS.min])
|
103
|
+
elsif DRIVER_WIRE_VERSIONS.max < server_wire_versions.min
|
104
|
+
raise Error::UnsupportedFeatures.new(DRIVER_TOO_OLD % [address,
|
105
|
+
server_wire_versions.min,
|
106
|
+
DRIVER_WIRE_VERSIONS.max])
|
88
107
|
end
|
89
108
|
end
|
90
109
|
end
|
data/lib/mongo/session.rb
CHANGED
@@ -34,13 +34,23 @@ module Mongo
|
|
34
34
|
# @since 2.5.0
|
35
35
|
attr_reader :client
|
36
36
|
|
37
|
-
|
37
|
+
# The cluster time for this session.
|
38
|
+
#
|
39
|
+
# @since 2.5.0
|
40
|
+
attr_reader :cluster_time
|
41
|
+
|
42
|
+
# The latest seen operation time for this session.
|
43
|
+
#
|
44
|
+
# @since 2.5.0
|
45
|
+
attr_reader :operation_time
|
46
|
+
|
47
|
+
def_delegators :client, :cluster
|
38
48
|
|
39
49
|
# Error message describing that the session was attempted to be used by a client different from the
|
40
50
|
# one it was originally associated with.
|
41
51
|
#
|
42
52
|
# @since 2.5.0
|
43
|
-
|
53
|
+
MISMATCHED_CLUSTER_ERROR_MSG = 'The client used to create this session does not match that of client ' +
|
44
54
|
'initiating this operation. Please only use this session for operations through its parent client.'.freeze
|
45
55
|
|
46
56
|
# Error message describing that the session cannot be used because it has already been ended.
|
@@ -66,7 +76,20 @@ module Mongo
|
|
66
76
|
def initialize(server_session, client, options = {})
|
67
77
|
@server_session = server_session
|
68
78
|
@client = client
|
69
|
-
@options = options
|
79
|
+
@options = options.dup.freeze
|
80
|
+
@cluster_time = nil
|
81
|
+
end
|
82
|
+
|
83
|
+
# Get a formatted string for use in inspection.
|
84
|
+
#
|
85
|
+
# @example Inspect the session object.
|
86
|
+
# session.inspect
|
87
|
+
#
|
88
|
+
# @return [ String ] The session inspection.
|
89
|
+
#
|
90
|
+
# @since 2.5.0
|
91
|
+
def inspect
|
92
|
+
"#<Mongo::Session:0x#{object_id} session_id=#{session_id} options=#{@options}>"
|
70
93
|
end
|
71
94
|
|
72
95
|
# End this session.
|
@@ -144,19 +167,113 @@ module Mongo
|
|
144
167
|
# @example Process a response from the server.
|
145
168
|
# session.process(result)
|
146
169
|
#
|
147
|
-
# @param [ Operation::Result ] The result from the operation.
|
170
|
+
# @param [ Operation::Result ] result The result from the operation.
|
148
171
|
#
|
149
172
|
# @return [ Operation::Result ] The result.
|
150
173
|
#
|
151
174
|
# @since 2.5.0
|
152
175
|
def process(result)
|
153
|
-
|
176
|
+
unless implicit_session?
|
177
|
+
set_operation_time(result)
|
178
|
+
set_cluster_time(result)
|
179
|
+
end
|
154
180
|
@server_session.set_last_use!
|
155
181
|
result
|
156
182
|
end
|
157
183
|
|
184
|
+
# Advance the cached cluster time document for this session.
|
185
|
+
#
|
186
|
+
# @example Advance the cluster time.
|
187
|
+
# session.advance_cluster_time(doc)
|
188
|
+
#
|
189
|
+
# @param [ BSON::Document, Hash ] new_cluster_time The new cluster time.
|
190
|
+
#
|
191
|
+
# @return [ BSON::Document, Hash ] The new cluster time.
|
192
|
+
#
|
193
|
+
# @since 2.5.0
|
194
|
+
def advance_cluster_time(new_cluster_time)
|
195
|
+
if @cluster_time
|
196
|
+
@cluster_time = [ @cluster_time, new_cluster_time ].max_by { |doc| doc[Cluster::CLUSTER_TIME] }
|
197
|
+
else
|
198
|
+
@cluster_time = new_cluster_time
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
# Advance the cached operation time for this session.
|
203
|
+
#
|
204
|
+
# @example Advance the operation time.
|
205
|
+
# session.advance_operation_time(timestamp)
|
206
|
+
#
|
207
|
+
# @param [ BSON::Timestamp ] new_operation_time The new operation time.
|
208
|
+
#
|
209
|
+
# @return [ BSON::Timestamp ] The max operation time, considering the current and new times.
|
210
|
+
#
|
211
|
+
# @since 2.5.0
|
212
|
+
def advance_operation_time(new_operation_time)
|
213
|
+
if @operation_time
|
214
|
+
@operation_time = [ @operation_time, new_operation_time ].max
|
215
|
+
else
|
216
|
+
@operation_time = new_operation_time
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
# Will writes executed with this session be retried.
|
221
|
+
#
|
222
|
+
# @example Will writes be retried.
|
223
|
+
# session.retry_writes?
|
224
|
+
#
|
225
|
+
# @return [ true, false ] If writes will be retried.
|
226
|
+
#
|
227
|
+
# @note Retryable writes are only available on server versions at least 3.6 and with
|
228
|
+
# sharded clusters or replica sets.
|
229
|
+
#
|
230
|
+
# @since 2.5.0
|
231
|
+
def retry_writes?
|
232
|
+
!!client.options[:retry_writes] && (cluster.replica_set? || cluster.sharded?)
|
233
|
+
end
|
234
|
+
|
235
|
+
# Get the session id.
|
236
|
+
#
|
237
|
+
# @example Get the session id.
|
238
|
+
# session.session_id
|
239
|
+
#
|
240
|
+
# @return [ BSON::Document ] The session id.
|
241
|
+
#
|
242
|
+
# @since 2.5.0
|
243
|
+
def session_id
|
244
|
+
@server_session.session_id if @server_session
|
245
|
+
end
|
246
|
+
|
247
|
+
# Increment and return the next transaction number.
|
248
|
+
#
|
249
|
+
# @example Get the next transaction number.
|
250
|
+
# server_session.next_txn_num
|
251
|
+
#
|
252
|
+
# @return [ Integer ] The next transaction number.
|
253
|
+
#
|
254
|
+
# @since 2.5.0
|
255
|
+
def next_txn_num
|
256
|
+
@server_session.next_txn_num if @server_session
|
257
|
+
end
|
258
|
+
|
158
259
|
private
|
159
260
|
|
261
|
+
def causal_consistency_doc(read_concern)
|
262
|
+
if operation_time && causal_consistency?
|
263
|
+
(read_concern || {}).merge(:afterClusterTime => operation_time)
|
264
|
+
else
|
265
|
+
read_concern
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
def causal_consistency?
|
270
|
+
@causal_consistency ||= (if @options.key?(:causal_consistency)
|
271
|
+
@options[:causal_consistency] == true
|
272
|
+
else
|
273
|
+
true
|
274
|
+
end)
|
275
|
+
end
|
276
|
+
|
160
277
|
def implicit_session?
|
161
278
|
@implicit_session ||= !!(@options.key?(:implicit) && @options[:implicit] == true)
|
162
279
|
end
|
@@ -167,13 +284,23 @@ module Mongo
|
|
167
284
|
end
|
168
285
|
end
|
169
286
|
|
287
|
+
def set_cluster_time(result)
|
288
|
+
if cluster_time_doc = result.cluster_time
|
289
|
+
if @cluster_time.nil?
|
290
|
+
@cluster_time = cluster_time_doc
|
291
|
+
elsif cluster_time_doc[Cluster::CLUSTER_TIME] > @cluster_time[Cluster::CLUSTER_TIME]
|
292
|
+
@cluster_time = cluster_time_doc
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
170
297
|
def check_if_ended!
|
171
298
|
raise Mongo::Error::InvalidSession.new(SESSION_ENDED_ERROR_MSG) if ended?
|
172
299
|
end
|
173
300
|
|
174
301
|
def check_matching_client!(client)
|
175
302
|
if @client != client
|
176
|
-
raise Mongo::Error::InvalidSession.new(
|
303
|
+
raise Mongo::Error::InvalidSession.new(MISMATCHED_CLUSTER_ERROR_MSG)
|
177
304
|
end
|
178
305
|
end
|
179
306
|
end
|
@@ -46,6 +46,8 @@ module Mongo
|
|
46
46
|
# @since 2.5.0
|
47
47
|
def initialize
|
48
48
|
set_last_use!
|
49
|
+
session_id
|
50
|
+
@txn_num = -1
|
49
51
|
end
|
50
52
|
|
51
53
|
# Update the last_use attribute of the server session to now.
|
@@ -53,6 +55,8 @@ module Mongo
|
|
53
55
|
# @example Set the last use field to now.
|
54
56
|
# server_session.set_last_use!
|
55
57
|
#
|
58
|
+
# @return [ Time ] The last time the session was used.
|
59
|
+
#
|
56
60
|
# @since 2.5.0
|
57
61
|
def set_last_use!
|
58
62
|
@last_use = Time.now
|
@@ -63,11 +67,37 @@ module Mongo
|
|
63
67
|
# @example Get the session id.
|
64
68
|
# server_session.session_id
|
65
69
|
#
|
70
|
+
# @return [ BSON::Document ] The session id.
|
71
|
+
#
|
66
72
|
# @since 2.5.0
|
67
73
|
def session_id
|
68
74
|
@session_id ||= (bytes = [SecureRandom.uuid.gsub(DASH_REGEX, '')].pack(UUID_PACK)
|
69
75
|
BSON::Document.new(id: BSON::Binary.new(bytes, :uuid)))
|
70
76
|
end
|
77
|
+
|
78
|
+
# Increment and return the next transaction number.
|
79
|
+
#
|
80
|
+
# @example Get the next transaction number.
|
81
|
+
# server_session.next_txn_num
|
82
|
+
#
|
83
|
+
# @return [ Integer ] The next transaction number.
|
84
|
+
#
|
85
|
+
# @since 2.5.0
|
86
|
+
def next_txn_num
|
87
|
+
@txn_num += 1
|
88
|
+
end
|
89
|
+
|
90
|
+
# Get a formatted string for use in inspection.
|
91
|
+
#
|
92
|
+
# @example Inspect the session object.
|
93
|
+
# session.inspect
|
94
|
+
#
|
95
|
+
# @return [ String ] The session inspection.
|
96
|
+
#
|
97
|
+
# @since 2.5.0
|
98
|
+
def inspect
|
99
|
+
"#<Mongo::Session::ServerSession:0x#{object_id} session_id=#{session_id} last_use=#{@last_use}>"
|
100
|
+
end
|
71
101
|
end
|
72
102
|
end
|
73
103
|
end
|
@@ -23,11 +23,6 @@ module Mongo
|
|
23
23
|
# @since 2.5.0
|
24
24
|
class SessionPool
|
25
25
|
|
26
|
-
# The command sent to the server to end a session.
|
27
|
-
#
|
28
|
-
# @since 2.5.0
|
29
|
-
END_SESSION = { :endSessions => 1 }.freeze
|
30
|
-
|
31
26
|
# Create a SessionPool.
|
32
27
|
#
|
33
28
|
# @example
|
@@ -57,6 +52,18 @@ module Mongo
|
|
57
52
|
@client = client
|
58
53
|
end
|
59
54
|
|
55
|
+
# Get a formatted string for use in inspection.
|
56
|
+
#
|
57
|
+
# @example Inspect the session pool object.
|
58
|
+
# session_pool.inspect
|
59
|
+
#
|
60
|
+
# @return [ String ] The session pool inspection.
|
61
|
+
#
|
62
|
+
# @since 2.5.0
|
63
|
+
def inspect
|
64
|
+
"#<Mongo::Session::SessionPool:0x#{object_id} current_size=#{@queue.size}>"
|
65
|
+
end
|
66
|
+
|
60
67
|
# Checkout a session to be used in the context of a block and return the session back to
|
61
68
|
# the pool after the block completes.
|
62
69
|
#
|
@@ -70,8 +77,7 @@ module Mongo
|
|
70
77
|
# @since 2.5.0
|
71
78
|
def with_session
|
72
79
|
server_session = checkout
|
73
|
-
|
74
|
-
result
|
80
|
+
yield(server_session)
|
75
81
|
ensure
|
76
82
|
begin; checkin(server_session) if server_session; rescue; end
|
77
83
|
end
|
@@ -104,7 +110,7 @@ module Mongo
|
|
104
110
|
# @example Checkin a session.
|
105
111
|
# pool.checkin(session)
|
106
112
|
#
|
107
|
-
# @param [ Session::ServerSession ] The session to checkin.
|
113
|
+
# @param [ Session::ServerSession ] session The session to checkin.
|
108
114
|
#
|
109
115
|
# @since 2.5.0
|
110
116
|
def checkin(session)
|
@@ -123,19 +129,13 @@ module Mongo
|
|
123
129
|
#
|
124
130
|
# @since 2.5.0
|
125
131
|
def end_sessions
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
Operation::Commands::Command.new({
|
132
|
-
:selector => END_SESSION.merge(ids: ids.shift(10_000)),
|
133
|
-
:db_name => Database::ADMIN
|
134
|
-
}).execute(@client.cluster.next_primary)
|
135
|
-
rescue
|
136
|
-
end
|
137
|
-
end
|
132
|
+
while !@queue.empty?
|
133
|
+
server = ServerSelector.get(mode: :primary_preferred).select_server(@client.cluster)
|
134
|
+
Operation::Commands::Command.new(
|
135
|
+
:selector => {endSessions: @queue.shift(10_000).collect { |s| s.session_id }},
|
136
|
+
:db_name => Database::ADMIN).execute(server)
|
138
137
|
end
|
138
|
+
rescue
|
139
139
|
end
|
140
140
|
|
141
141
|
private
|
data/lib/mongo/uri.rb
CHANGED
@@ -22,8 +22,8 @@ module Mongo
|
|
22
22
|
# http://docs.mongodb.org/manual/reference/connection-string/
|
23
23
|
#
|
24
24
|
# @example Use the uri string to make a client connection.
|
25
|
-
# uri = URI.new('mongodb://localhost:27017')
|
26
|
-
# client = Client.new(uri.
|
25
|
+
# uri = Mongo::URI.new('mongodb://localhost:27017')
|
26
|
+
# client = Mongo::Client.new(uri.servers, uri.options)
|
27
27
|
# client.login(uri.credentials)
|
28
28
|
# client[uri.database]
|
29
29
|
#
|
@@ -46,6 +46,39 @@ module Mongo
|
|
46
46
|
# @since 2.0.0
|
47
47
|
attr_reader :servers
|
48
48
|
|
49
|
+
# The mongodb connection string scheme.
|
50
|
+
#
|
51
|
+
# @deprecated Will be removed in 3.0.
|
52
|
+
#
|
53
|
+
# @since 2.0.0
|
54
|
+
SCHEME = 'mongodb://'.freeze
|
55
|
+
|
56
|
+
# The mongodb connection string scheme root.
|
57
|
+
#
|
58
|
+
# @since 2.5.0
|
59
|
+
MONGODB_SCHEME = 'mongodb'.freeze
|
60
|
+
|
61
|
+
# The mongodb srv protocol connection string scheme root.
|
62
|
+
#
|
63
|
+
# @since 2.5.0
|
64
|
+
MONGODB_SRV_SCHEME = 'mongodb+srv'.freeze
|
65
|
+
|
66
|
+
# Error details for an invalid scheme.
|
67
|
+
#
|
68
|
+
# @since 2.1.0
|
69
|
+
INVALID_SCHEME = "Invalid scheme. Scheme must be '#{MONGODB_SCHEME}' or '#{MONGODB_SRV_SCHEME}'".freeze
|
70
|
+
|
71
|
+
# MongoDB URI format specification.
|
72
|
+
#
|
73
|
+
# @since 2.0.0
|
74
|
+
FORMAT = 'mongodb://[username:password@]host1[:port1][,host2[:port2]' +
|
75
|
+
',...[,hostN[:portN]]][/[database][?options]]'.freeze
|
76
|
+
|
77
|
+
# MongoDB URI (connection string) documentation url
|
78
|
+
#
|
79
|
+
# @since 2.0.0
|
80
|
+
HELP = 'http://docs.mongodb.org/manual/reference/connection-string/'.freeze
|
81
|
+
|
49
82
|
# Unsafe characters that must be urlencoded.
|
50
83
|
#
|
51
84
|
# @since 2.1.0
|
@@ -56,11 +89,6 @@ module Mongo
|
|
56
89
|
# @since 2.1.0
|
57
90
|
UNIX_SOCKET = /.sock/
|
58
91
|
|
59
|
-
# The mongodb connection string scheme.
|
60
|
-
#
|
61
|
-
# @since 2.0.0
|
62
|
-
SCHEME = 'mongodb://'.freeze
|
63
|
-
|
64
92
|
# The character delimiting hosts.
|
65
93
|
#
|
66
94
|
# @since 2.1.0
|
@@ -101,10 +129,10 @@ module Mongo
|
|
101
129
|
# @since 2.1.0
|
102
130
|
AUTH_DELIM = '@'.freeze
|
103
131
|
|
104
|
-
#
|
132
|
+
# Scheme delimiter.
|
105
133
|
#
|
106
|
-
# @since 2.
|
107
|
-
|
134
|
+
# @since 2.5.0
|
135
|
+
SCHEME_DELIM = '://'.freeze
|
108
136
|
|
109
137
|
# Error details for an invalid options format.
|
110
138
|
#
|
@@ -142,17 +170,6 @@ module Mongo
|
|
142
170
|
# @since 2.1.0
|
143
171
|
INVALID_PORT = "Invalid port. Port must be an integer greater than 0 and less than 65536".freeze
|
144
172
|
|
145
|
-
# MongoDB URI format specification.
|
146
|
-
#
|
147
|
-
# @since 2.0.0
|
148
|
-
FORMAT = 'mongodb://[username:password@]host1[:port1][,host2[:port2]' +
|
149
|
-
',...[,hostN[:portN]]][/[database][?options]]'.freeze
|
150
|
-
|
151
|
-
# MongoDB URI (connection string) documentation url
|
152
|
-
#
|
153
|
-
# @since 2.0.0
|
154
|
-
HELP = 'http://docs.mongodb.org/manual/reference/connection-string/'.freeze
|
155
|
-
|
156
173
|
# Map of URI read preference modes to ruby driver read preference modes
|
157
174
|
#
|
158
175
|
# @since 2.0.0
|
@@ -180,23 +197,24 @@ module Mongo
|
|
180
197
|
# @since 2.1.0
|
181
198
|
REPEATABLE_OPTIONS = [ :tag_sets ]
|
182
199
|
|
183
|
-
#
|
200
|
+
# Get either a URI object or a SRVProtocol URI object.
|
184
201
|
#
|
185
|
-
# @example
|
186
|
-
# URI.
|
202
|
+
# @example Get the uri object.
|
203
|
+
# URI.get(string)
|
187
204
|
#
|
188
|
-
# @
|
189
|
-
# @param [ Hash ] options The options.
|
190
|
-
#
|
191
|
-
# @raise [ Error::InvalidURI ] If the uri does not match the spec.
|
205
|
+
# @return [URI, URI::SRVProtocol] The uri object.
|
192
206
|
#
|
193
|
-
# @since 2.
|
194
|
-
def
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
207
|
+
# @since 2.5.0
|
208
|
+
def self.get(string, opts = {})
|
209
|
+
scheme, _, remaining = string.partition(SCHEME_DELIM)
|
210
|
+
case scheme
|
211
|
+
when MONGODB_SCHEME
|
212
|
+
URI.new(string, opts)
|
213
|
+
when MONGODB_SRV_SCHEME
|
214
|
+
SRVProtocol.new(string, opts)
|
215
|
+
else
|
216
|
+
raise Error::InvalidURI.new(string, INVALID_SCHEME)
|
217
|
+
end
|
200
218
|
end
|
201
219
|
|
202
220
|
# Gets the options hash that needs to be passed to a Mongo::Client on
|
@@ -214,6 +232,25 @@ module Mongo
|
|
214
232
|
@user ? opts.merge(credentials) : opts
|
215
233
|
end
|
216
234
|
|
235
|
+
# Create the new uri from the provided string.
|
236
|
+
#
|
237
|
+
# @example Create the new URI.
|
238
|
+
# URI.new('mongodb://localhost:27017')
|
239
|
+
#
|
240
|
+
# @param [ String ] string The uri string.
|
241
|
+
# @param [ Hash ] options The options.
|
242
|
+
#
|
243
|
+
# @raise [ Error::InvalidURI ] If the uri does not match the spec.
|
244
|
+
#
|
245
|
+
# @since 2.0.0
|
246
|
+
def initialize(string, options = {})
|
247
|
+
@string = string
|
248
|
+
@options = options
|
249
|
+
parsed_scheme, _, remaining = string.partition(SCHEME_DELIM)
|
250
|
+
raise_invalid_error!(INVALID_SCHEME) unless parsed_scheme == scheme
|
251
|
+
parse!(remaining)
|
252
|
+
end
|
253
|
+
|
217
254
|
# Get the credentials provided in the URI.
|
218
255
|
#
|
219
256
|
# @example Get the credentials.
|
@@ -242,7 +279,18 @@ module Mongo
|
|
242
279
|
|
243
280
|
private
|
244
281
|
|
245
|
-
def
|
282
|
+
def scheme
|
283
|
+
MONGODB_SCHEME
|
284
|
+
end
|
285
|
+
|
286
|
+
def parse_creds_hosts!(string)
|
287
|
+
hosts, creds = split_creds_hosts(string)
|
288
|
+
@servers = parse_servers!(hosts)
|
289
|
+
@user = parse_user!(creds)
|
290
|
+
@password = parse_password!(creds)
|
291
|
+
end
|
292
|
+
|
293
|
+
def parse!(remaining)
|
246
294
|
creds_hosts, db_opts = extract_db_opts!(remaining)
|
247
295
|
parse_creds_hosts!(creds_hosts)
|
248
296
|
parse_db_opts!(db_opts)
|
@@ -257,13 +305,6 @@ module Mongo
|
|
257
305
|
[ creds_hosts, db_opts ].map { |s| s.reverse }
|
258
306
|
end
|
259
307
|
|
260
|
-
def parse_creds_hosts!(string)
|
261
|
-
hosts, creds = split_creds_hosts(string)
|
262
|
-
@servers = parse_servers!(hosts)
|
263
|
-
@user = parse_user!(creds)
|
264
|
-
@password = parse_password!(creds)
|
265
|
-
end
|
266
|
-
|
267
308
|
def split_creds_hosts(string)
|
268
309
|
hosts, _, creds = string.reverse.partition(AUTH_DELIM)
|
269
310
|
hosts, creds = creds, hosts if hosts.empty?
|
@@ -330,13 +371,14 @@ module Mongo
|
|
330
371
|
validate_port_string!(p)
|
331
372
|
elsif host =~ UNIX_SOCKET
|
332
373
|
raise_invalid_error!(UNESCAPED_UNIX_SOCKET) if host =~ UNSAFE
|
374
|
+
host = decode(host)
|
333
375
|
end
|
334
376
|
servers << host
|
335
377
|
end
|
336
378
|
end
|
337
379
|
|
338
380
|
def raise_invalid_error!(details)
|
339
|
-
raise Error::InvalidURI.new(@string, details)
|
381
|
+
raise Error::InvalidURI.new(@string, details, FORMAT)
|
340
382
|
end
|
341
383
|
|
342
384
|
def decode(value)
|
@@ -585,3 +627,5 @@ module Mongo
|
|
585
627
|
end
|
586
628
|
end
|
587
629
|
end
|
630
|
+
|
631
|
+
require 'mongo/uri/srv_protocol'
|