mongo 2.4.3 → 2.5.0.beta
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 +3 -2
- data.tar.gz.sig +0 -0
- data/lib/mongo.rb +3 -2
- data/lib/mongo/auth/cr.rb +6 -4
- data/lib/mongo/auth/cr/conversation.rb +33 -17
- data/lib/mongo/auth/ldap.rb +4 -2
- data/lib/mongo/auth/ldap/conversation.rb +19 -9
- data/lib/mongo/auth/scram.rb +7 -4
- data/lib/mongo/auth/scram/conversation.rb +62 -24
- data/lib/mongo/auth/user.rb +10 -0
- data/lib/mongo/auth/user/view.rb +44 -22
- data/lib/mongo/auth/x509.rb +4 -2
- data/lib/mongo/auth/x509/conversation.rb +19 -9
- data/lib/mongo/bulk_write.rb +33 -27
- data/lib/mongo/bulk_write/combineable.rb +5 -0
- data/lib/mongo/bulk_write/transformable.rb +2 -0
- data/lib/mongo/bulk_write/validatable.rb +4 -0
- data/lib/mongo/client.rb +123 -12
- data/lib/mongo/cluster.rb +52 -11
- data/lib/mongo/cluster/app_metadata.rb +8 -2
- data/lib/mongo/cluster/cursor_reaper.rb +0 -1
- data/lib/mongo/cluster/topology.rb +1 -1
- data/lib/mongo/collection.rb +114 -27
- data/lib/mongo/collection/view.rb +8 -2
- data/lib/mongo/collection/view/aggregation.rb +11 -7
- data/lib/mongo/collection/view/builder/aggregation.rb +5 -1
- data/lib/mongo/collection/view/builder/find_command.rb +5 -3
- data/lib/mongo/collection/view/builder/map_reduce.rb +11 -3
- data/lib/mongo/collection/view/builder/op_query.rb +1 -1
- data/lib/mongo/collection/view/change_stream.rb +160 -0
- data/lib/mongo/collection/view/change_stream/retryable.rb +57 -0
- data/lib/mongo/collection/view/iterable.rb +11 -10
- data/lib/mongo/collection/view/map_reduce.rb +22 -18
- data/lib/mongo/collection/view/readable.rb +51 -37
- data/lib/mongo/collection/view/writable.rb +72 -40
- data/lib/mongo/cursor.rb +25 -4
- data/lib/mongo/cursor/builder/get_more_command.rb +4 -2
- data/lib/mongo/database.rb +22 -11
- data/lib/mongo/database/view.rb +16 -12
- data/lib/mongo/error.rb +5 -0
- data/lib/mongo/error/invalid_session.rb +36 -0
- data/lib/mongo/error/missing_resume_token.rb +39 -0
- data/lib/mongo/error/operation_failure.rb +17 -0
- data/lib/mongo/error/parser.rb +3 -2
- data/lib/mongo/error/unknown_payload_type.rb +41 -0
- data/lib/mongo/error/unsupported_array_filters.rb +51 -0
- data/lib/mongo/error/unsupported_message_type.rb +23 -0
- data/lib/mongo/grid/fs_bucket.rb +5 -4
- data/lib/mongo/grid/stream/read.rb +3 -2
- data/lib/mongo/grid/stream/write.rb +2 -2
- data/lib/mongo/index/view.rb +35 -25
- data/lib/mongo/monitoring/event/secure.rb +14 -0
- data/lib/mongo/operation.rb +16 -0
- data/lib/mongo/operation/commands.rb +1 -0
- data/lib/mongo/operation/commands/aggregate.rb +9 -5
- data/lib/mongo/operation/commands/aggregate/result.rb +1 -1
- data/lib/mongo/operation/commands/collections_info.rb +6 -6
- data/lib/mongo/operation/commands/command.rb +2 -1
- data/lib/mongo/operation/commands/create.rb +6 -2
- data/lib/mongo/operation/commands/drop.rb +6 -2
- data/lib/mongo/operation/commands/drop_database.rb +6 -2
- data/lib/mongo/operation/commands/explain.rb +27 -0
- data/lib/mongo/operation/commands/explain/result.rb +52 -0
- data/lib/mongo/operation/commands/indexes.rb +1 -1
- data/lib/mongo/operation/commands/list_collections.rb +1 -1
- data/lib/mongo/operation/commands/list_collections/result.rb +1 -1
- data/lib/mongo/operation/commands/list_indexes.rb +1 -1
- data/lib/mongo/operation/commands/list_indexes/result.rb +1 -1
- data/lib/mongo/operation/commands/map_reduce.rb +8 -4
- data/lib/mongo/operation/commands/map_reduce/result.rb +13 -1
- data/lib/mongo/operation/commands/user_query.rb +1 -1
- data/lib/mongo/operation/commands/users_info.rb +6 -2
- data/lib/mongo/operation/executable.rb +4 -1
- data/lib/mongo/operation/read_preference.rb +10 -5
- data/lib/mongo/operation/result.rb +26 -2
- data/lib/mongo/operation/specifiable.rb +13 -1
- data/lib/mongo/operation/uses_command_op_msg.rb +47 -0
- data/lib/mongo/operation/write/bulk/bulkable.rb +4 -1
- data/lib/mongo/operation/write/bulk/insert/result.rb +4 -4
- data/lib/mongo/operation/write/command/create_index.rb +6 -1
- data/lib/mongo/operation/write/command/delete.rb +28 -4
- data/lib/mongo/operation/write/command/drop_index.rb +6 -1
- data/lib/mongo/operation/write/command/insert.rb +22 -18
- data/lib/mongo/operation/write/command/update.rb +24 -9
- data/lib/mongo/operation/write/command/writable.rb +14 -1
- data/lib/mongo/operation/write/insert.rb +4 -1
- data/lib/mongo/operation/write/insert/result.rb +2 -2
- data/lib/mongo/operation/write/update.rb +7 -1
- data/lib/mongo/operation/write/write_command_enabled.rb +20 -3
- data/lib/mongo/protocol.rb +3 -0
- data/lib/mongo/protocol/bit_vector.rb +2 -2
- data/lib/mongo/protocol/compressed.rb +135 -0
- data/lib/mongo/protocol/delete.rb +8 -6
- data/lib/mongo/protocol/get_more.rb +8 -6
- data/lib/mongo/protocol/insert.rb +8 -6
- data/lib/mongo/protocol/kill_cursors.rb +8 -6
- data/lib/mongo/protocol/message.rb +31 -3
- data/lib/mongo/protocol/msg.rb +172 -0
- data/lib/mongo/protocol/query.rb +26 -6
- data/lib/mongo/protocol/registry.rb +76 -0
- data/lib/mongo/protocol/reply.rb +10 -5
- data/lib/mongo/protocol/serializers.rb +224 -0
- data/lib/mongo/protocol/update.rb +8 -6
- data/lib/mongo/retryable.rb +4 -2
- data/lib/mongo/server.rb +6 -3
- data/lib/mongo/server/connectable.rb +1 -1
- data/lib/mongo/server/connection.rb +30 -8
- data/lib/mongo/server/description.rb +25 -1
- data/lib/mongo/server/description/features.rb +4 -1
- data/lib/mongo/server/monitor.rb +5 -0
- data/lib/mongo/server/monitor/connection.rb +50 -2
- data/lib/mongo/server_selector/nearest.rb +10 -4
- data/lib/mongo/server_selector/primary.rb +20 -0
- data/lib/mongo/server_selector/primary_preferred.rb +10 -4
- data/lib/mongo/server_selector/secondary.rb +10 -4
- data/lib/mongo/server_selector/secondary_preferred.rb +24 -4
- data/lib/mongo/session.rb +180 -0
- data/lib/mongo/session/server_session.rb +73 -0
- data/lib/mongo/session/session_pool.rb +161 -0
- data/lib/mongo/uri.rb +11 -0
- data/lib/mongo/version.rb +1 -1
- data/mongo.gemspec +2 -1
- data/spec/mongo/auth/cr_spec.rb +12 -0
- data/spec/mongo/auth/ldap_spec.rb +2 -0
- data/spec/mongo/auth/scram/conversation_spec.rb +6 -6
- data/spec/mongo/auth/scram_spec.rb +25 -1
- data/spec/mongo/auth/user/view_spec.rb +268 -76
- data/spec/mongo/auth/x509_spec.rb +2 -0
- data/spec/mongo/bulk_write_spec.rb +435 -5
- data/spec/mongo/client_spec.rb +356 -39
- data/spec/mongo/cluster/app_metadata_spec.rb +2 -2
- data/spec/mongo/cluster_spec.rb +176 -0
- data/spec/mongo/collection/view/aggregation_spec.rb +33 -12
- data/spec/mongo/collection/view/builder/find_command_spec.rb +46 -6
- data/spec/mongo/collection/view/change_stream_spec.rb +814 -0
- data/spec/mongo/collection/view/map_reduce_spec.rb +94 -17
- data/spec/mongo/collection/view/readable_spec.rb +3 -12
- data/spec/mongo/collection_spec.rb +1048 -42
- data/spec/mongo/cursor/builder/get_more_command_spec.rb +19 -0
- data/spec/mongo/cursor_spec.rb +2 -2
- data/spec/mongo/database_spec.rb +50 -1
- data/spec/mongo/grid/fs_bucket_spec.rb +225 -137
- data/spec/mongo/grid/stream/read_spec.rb +2 -2
- data/spec/mongo/index/view_spec.rb +146 -8
- data/spec/mongo/monitoring/event/secure_spec.rb +42 -0
- data/spec/mongo/operation/read/query_spec.rb +2 -1
- data/spec/mongo/operation/specifiable_spec.rb +2 -2
- data/spec/mongo/operation/write/command/delete_spec.rb +96 -13
- data/spec/mongo/operation/write/command/insert_spec.rb +111 -12
- data/spec/mongo/operation/write/command/update_spec.rb +93 -10
- data/spec/mongo/operation/write/delete_spec.rb +1 -1
- data/spec/mongo/operation/write/insert_spec.rb +1 -1
- data/spec/mongo/operation/write/update_spec.rb +1 -1
- data/spec/mongo/protocol/compressed_spec.rb +66 -0
- data/spec/mongo/protocol/delete_spec.rb +14 -0
- data/spec/mongo/protocol/get_more_spec.rb +14 -0
- data/spec/mongo/protocol/insert_spec.rb +14 -0
- data/spec/mongo/protocol/kill_cursors_spec.rb +14 -0
- data/spec/mongo/protocol/msg_spec.rb +499 -0
- data/spec/mongo/protocol/query_spec.rb +45 -0
- data/spec/mongo/protocol/registry_spec.rb +31 -0
- data/spec/mongo/protocol/reply_spec.rb +14 -0
- data/spec/mongo/protocol/update_spec.rb +14 -0
- data/spec/mongo/retryable_spec.rb +6 -2
- data/spec/mongo/sdam_spec.rb +4 -0
- data/spec/mongo/server/connection_spec.rb +4 -2
- data/spec/mongo/server/description_spec.rb +28 -1
- data/spec/mongo/session/server_session_spec.rb +16 -0
- data/spec/mongo/session/session_pool_spec.rb +194 -0
- data/spec/mongo/uri_spec.rb +31 -2
- data/spec/spec_helper.rb +104 -0
- data/spec/support/authorization.rb +6 -1
- data/spec/support/crud.rb +3 -1
- data/spec/support/crud/write.rb +6 -1
- data/spec/support/crud_tests/write/findOneAndUpdate-arrayFilters.yml +69 -0
- data/spec/support/crud_tests/write/updateMany-arrayFilters.yml +63 -0
- data/spec/support/crud_tests/write/updateOne-arrayFilters.yml +109 -0
- data/spec/support/sdam/rs/discover_arbiters.yml +1 -1
- data/spec/support/sdam/rs/discover_passives.yml +2 -2
- data/spec/support/sdam/rs/discover_primary.yml +1 -1
- data/spec/support/sdam/rs/discover_secondary.yml +1 -1
- data/spec/support/sdam/rs/discovery.yml +4 -4
- data/spec/support/sdam/rs/equal_electionids.yml +1 -0
- data/spec/support/sdam/rs/ghost_discovered.yml +1 -1
- data/spec/support/sdam/rs/hosts_differ_from_seeds.yml +1 -1
- data/spec/support/sdam/rs/ls_timeout.yml +88 -0
- data/spec/support/sdam/rs/member_reconfig.yml +2 -2
- data/spec/support/sdam/rs/member_standalone.yml +2 -2
- data/spec/support/sdam/rs/new_primary.yml +2 -2
- data/spec/support/sdam/rs/new_primary_new_electionid.yml +3 -0
- data/spec/support/sdam/rs/new_primary_new_setversion.yml +3 -0
- data/spec/support/sdam/rs/new_primary_wrong_set_name.yml +2 -2
- data/spec/support/sdam/rs/non_rs_member.yml +1 -1
- data/spec/support/sdam/rs/normalize_case.yml +1 -1
- data/spec/support/sdam/rs/null_election_id.yml +4 -0
- data/spec/support/sdam/rs/primary_becomes_standalone.yml +2 -2
- data/spec/support/sdam/rs/primary_changes_set_name.yml +2 -2
- data/spec/support/sdam/rs/primary_disconnect.yml +2 -2
- data/spec/support/sdam/rs/primary_disconnect_electionid.yml +5 -0
- data/spec/support/sdam/rs/primary_disconnect_setversion.yml +5 -0
- data/spec/support/sdam/rs/primary_hint_from_secondary_with_mismatched_me.yml +58 -0
- data/spec/support/sdam/rs/primary_reports_new_member.yml +4 -4
- data/spec/support/sdam/rs/primary_to_no_primary_mismatched_me.yml +2 -2
- data/spec/support/sdam/rs/primary_wrong_set_name.yml +1 -1
- data/spec/support/sdam/rs/response_from_removed.yml +2 -2
- data/spec/support/sdam/rs/rsother_discovered.yml +1 -1
- data/spec/support/sdam/rs/sec_not_auth.yml +1 -1
- data/spec/support/sdam/rs/secondary_wrong_set_name.yml +1 -1
- data/spec/support/sdam/rs/secondary_wrong_set_name_with_primary.yml +2 -2
- data/spec/support/sdam/rs/setversion_without_electionid.yml +2 -0
- data/spec/support/sdam/rs/stepdown_change_set_name.yml +2 -2
- data/spec/support/sdam/rs/unexpected_mongos.yml +1 -1
- data/spec/support/sdam/rs/use_setversion_without_electionid.yml +3 -0
- data/spec/support/sdam/rs/wrong_set_name.yml +1 -1
- data/spec/support/sdam/sharded/ls_timeout_mongos.yml +97 -0
- data/spec/support/sdam/sharded/mongos_disconnect.yml +3 -3
- data/spec/support/sdam/sharded/multiple_mongoses.yml +1 -1
- data/spec/support/sdam/sharded/non_mongos_removed.yml +1 -1
- data/spec/support/sdam/sharded/normalize_uri_case.yml +1 -1
- data/spec/support/sdam/single/direct_connection_external_ip.yml +1 -1
- data/spec/support/sdam/single/direct_connection_mongos.yml +1 -1
- data/spec/support/sdam/single/direct_connection_rsarbiter.yml +1 -1
- data/spec/support/sdam/single/direct_connection_rsprimary.yml +1 -1
- data/spec/support/sdam/single/direct_connection_rssecondary.yml +1 -1
- data/spec/support/sdam/single/direct_connection_slave.yml +1 -1
- data/spec/support/sdam/single/direct_connection_standalone.yml +1 -1
- data/spec/support/sdam/single/ls_timeout_standalone.yml +35 -0
- data/spec/support/sdam/single/not_ok_response.yml +1 -1
- data/spec/support/sdam/single/standalone_removed.yml +1 -1
- data/spec/support/sdam/single/unavailable_seed.yml +1 -1
- data/spec/support/server_discovery_and_monitoring.rb +4 -0
- data/spec/support/shared/session.rb +236 -0
- metadata +53 -15
- metadata.gz.sig +0 -0
data/lib/mongo/auth/x509.rb
CHANGED
@@ -50,12 +50,14 @@ module Mongo
|
|
50
50
|
# @param [ Mongo::Connection ] connection The connection to log into.
|
51
51
|
# on.
|
52
52
|
#
|
53
|
-
# @return [ Protocol::
|
53
|
+
# @return [ Protocol::Message ] The authentication response.
|
54
54
|
#
|
55
55
|
# @since 2.0.0
|
56
56
|
def login(connection)
|
57
57
|
conversation = Conversation.new(user)
|
58
|
-
|
58
|
+
reply = connection.dispatch([ conversation.start(connection) ])
|
59
|
+
connection.update_cluster_time(Operation::Result.new(reply))
|
60
|
+
conversation.finalize(reply)
|
59
61
|
end
|
60
62
|
end
|
61
63
|
end
|
@@ -27,7 +27,7 @@ module Mongo
|
|
27
27
|
# @since 2.0.0
|
28
28
|
LOGIN = { authenticate: 1 }.freeze
|
29
29
|
|
30
|
-
# @return [ Protocol::
|
30
|
+
# @return [ Protocol::Message ] reply The current reply in the
|
31
31
|
# conversation.
|
32
32
|
attr_reader :reply
|
33
33
|
|
@@ -40,7 +40,7 @@ module Mongo
|
|
40
40
|
# @example Finalize the conversation.
|
41
41
|
# conversation.finalize(reply)
|
42
42
|
#
|
43
|
-
# @param [ Protocol::
|
43
|
+
# @param [ Protocol::Message ] reply The reply of the previous
|
44
44
|
# message.
|
45
45
|
#
|
46
46
|
# @return [ Protocol::Query ] The next message to send.
|
@@ -56,18 +56,28 @@ module Mongo
|
|
56
56
|
# @example Start the conversation.
|
57
57
|
# conversation.start
|
58
58
|
#
|
59
|
+
# @param [ Mongo::Server::Connection ] connection The connection being authenticated.
|
60
|
+
#
|
59
61
|
# @return [ Protocol::Query ] The first x.509 conversation message.
|
60
62
|
#
|
61
63
|
# @since 2.0.0
|
62
|
-
def start
|
64
|
+
def start(connection = nil)
|
63
65
|
login = LOGIN.merge(mechanism: X509::MECHANISM)
|
64
66
|
login[:user] = user.name if user.name
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
67
|
+
if connection && connection.features.op_msg_enabled?
|
68
|
+
selector = login
|
69
|
+
selector[Protocol::Msg::DATABASE_IDENTIFIER] = user.auth_source
|
70
|
+
cluster_time = connection.mongos? && connection.cluster_time
|
71
|
+
selector[Operation::CLUSTER_TIME] = cluster_time if cluster_time
|
72
|
+
Protocol::Msg.new([:none], {}, selector)
|
73
|
+
else
|
74
|
+
Protocol::Query.new(
|
75
|
+
Auth::EXTERNAL,
|
76
|
+
Database::COMMAND,
|
77
|
+
login,
|
78
|
+
limit: -1
|
79
|
+
)
|
80
|
+
end
|
71
81
|
end
|
72
82
|
|
73
83
|
# Create the new conversation.
|
data/lib/mongo/bulk_write.rb
CHANGED
@@ -53,18 +53,23 @@ module Mongo
|
|
53
53
|
def execute
|
54
54
|
operation_id = Monitoring.next_operation_id
|
55
55
|
result_combiner = ResultCombiner.new
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
56
|
+
|
57
|
+
client.send(:with_session, @options) do |session|
|
58
|
+
write_with_retry(session, Proc.new { next_primary }) do |server|
|
59
|
+
operations = op_combiner.combine
|
60
|
+
raise Error::UnsupportedCollation.new if op_combiner.has_collation && !server.features.collation_enabled?
|
61
|
+
raise Error::UnsupportedArrayFilters.new if op_combiner.has_array_filters && !server.features.array_filters_enabled?
|
62
|
+
|
63
|
+
operations.each do |operation|
|
64
|
+
execute_operation(
|
65
|
+
operation.keys.first,
|
66
|
+
operation.values.first,
|
67
|
+
server,
|
68
|
+
operation_id,
|
69
|
+
result_combiner,
|
70
|
+
session
|
71
|
+
)
|
72
|
+
end
|
68
73
|
end
|
69
74
|
end
|
70
75
|
result_combiner.result
|
@@ -132,7 +137,7 @@ module Mongo
|
|
132
137
|
|
133
138
|
private
|
134
139
|
|
135
|
-
def base_spec(operation_id)
|
140
|
+
def base_spec(operation_id, session)
|
136
141
|
{
|
137
142
|
:db_name => database.name,
|
138
143
|
:coll_name => collection.name,
|
@@ -141,20 +146,21 @@ module Mongo
|
|
141
146
|
:operation_id => operation_id,
|
142
147
|
:bypass_document_validation => !!options[:bypass_document_validation],
|
143
148
|
:options => options,
|
144
|
-
:id_generator => client.options[:id_generator]
|
149
|
+
:id_generator => client.options[:id_generator],
|
150
|
+
:session => session
|
145
151
|
}
|
146
152
|
end
|
147
153
|
|
148
|
-
def execute_operation(name, values, server, operation_id, combiner)
|
154
|
+
def execute_operation(name, values, server, operation_id, combiner, session)
|
149
155
|
begin
|
150
156
|
if values.size > server.max_write_batch_size
|
151
|
-
split_execute(name, values, server, operation_id, combiner)
|
157
|
+
split_execute(name, values, server, operation_id, combiner, session)
|
152
158
|
else
|
153
|
-
combiner.combine!(send(name, values, server, operation_id), values.size)
|
159
|
+
combiner.combine!(send(name, values, server, operation_id, session), values.size)
|
154
160
|
end
|
155
161
|
rescue Error::MaxBSONSize, Error::MaxMessageSize => e
|
156
162
|
raise e if values.size <= 1
|
157
|
-
split_execute(name, values, server, operation_id, combiner)
|
163
|
+
split_execute(name, values, server, operation_id, combiner, session)
|
158
164
|
end
|
159
165
|
end
|
160
166
|
|
@@ -162,29 +168,29 @@ module Mongo
|
|
162
168
|
@op_combiner ||= ordered? ? OrderedCombiner.new(requests) : UnorderedCombiner.new(requests)
|
163
169
|
end
|
164
170
|
|
165
|
-
def split_execute(name, values, server, operation_id, combiner)
|
166
|
-
execute_operation(name, values.shift(values.size / 2), server, operation_id, combiner)
|
167
|
-
execute_operation(name, values, server, operation_id, combiner)
|
171
|
+
def split_execute(name, values, server, operation_id, combiner, session)
|
172
|
+
execute_operation(name, values.shift(values.size / 2), server, operation_id, combiner, session)
|
173
|
+
execute_operation(name, values, server, operation_id, combiner, session)
|
168
174
|
end
|
169
175
|
|
170
|
-
def delete(documents, server, operation_id)
|
176
|
+
def delete(documents, server, operation_id, session)
|
171
177
|
Operation::Write::Bulk::Delete.new(
|
172
|
-
base_spec(operation_id).merge(:deletes => documents)
|
178
|
+
base_spec(operation_id, session).merge(:deletes => documents)
|
173
179
|
).execute(server)
|
174
180
|
end
|
175
181
|
|
176
182
|
alias :delete_one :delete
|
177
183
|
alias :delete_many :delete
|
178
184
|
|
179
|
-
def insert_one(documents, server, operation_id)
|
185
|
+
def insert_one(documents, server, operation_id, session)
|
180
186
|
Operation::Write::Bulk::Insert.new(
|
181
|
-
base_spec(operation_id).merge(:documents => documents)
|
187
|
+
base_spec(operation_id, session).merge(:documents => documents)
|
182
188
|
).execute(server)
|
183
189
|
end
|
184
190
|
|
185
|
-
def update(documents, server, operation_id)
|
191
|
+
def update(documents, server, operation_id, session)
|
186
192
|
Operation::Write::Bulk::Update.new(
|
187
|
-
base_spec(operation_id).merge(:updates => documents)
|
193
|
+
base_spec(operation_id, session).merge(:updates => documents)
|
188
194
|
).execute(server)
|
189
195
|
end
|
190
196
|
|
@@ -28,6 +28,10 @@ module Mongo
|
|
28
28
|
# @return [ true, false ] has_collation Whether one or more operations has a collation defined.
|
29
29
|
attr_reader :has_collation
|
30
30
|
|
31
|
+
# @return [ true, false ] has_array_filters Whether one or more operations specifies an array
|
32
|
+
# filters option.
|
33
|
+
attr_reader :has_array_filters
|
34
|
+
|
31
35
|
# Create the ordered combiner.
|
32
36
|
#
|
33
37
|
# @api private
|
@@ -41,6 +45,7 @@ module Mongo
|
|
41
45
|
def initialize(requests)
|
42
46
|
@requests = requests
|
43
47
|
@has_collation = false
|
48
|
+
@has_array_filters = false
|
44
49
|
end
|
45
50
|
|
46
51
|
private
|
@@ -104,6 +104,7 @@ module Mongo
|
|
104
104
|
Operation::UPSERT => doc.fetch(:upsert, false)
|
105
105
|
}.tap do |d|
|
106
106
|
d[Operation::COLLATION] = doc[:collation] if doc[:collation]
|
107
|
+
d[Operation::ARRAY_FILTERS] = doc[:array_filters] if doc[:array_filters]
|
107
108
|
end
|
108
109
|
}
|
109
110
|
|
@@ -118,6 +119,7 @@ module Mongo
|
|
118
119
|
Operation::UPSERT => doc.fetch(:upsert, false)
|
119
120
|
}.tap do |d|
|
120
121
|
d[Operation::COLLATION] = doc[:collation] if doc[:collation]
|
122
|
+
d[Operation::ARRAY_FILTERS] = doc[:array_filters] if doc[:array_filters]
|
121
123
|
end
|
122
124
|
}
|
123
125
|
|
@@ -43,6 +43,10 @@ module Mongo
|
|
43
43
|
if document.respond_to?(:keys) && (document[:collation] || document[Operation::COLLATION])
|
44
44
|
@has_collation = true
|
45
45
|
end
|
46
|
+
|
47
|
+
if document.respond_to?(:keys) && document[:array_filters]
|
48
|
+
@has_array_filters = true
|
49
|
+
end
|
46
50
|
end
|
47
51
|
|
48
52
|
private
|
data/lib/mongo/client.rb
CHANGED
@@ -38,6 +38,7 @@ module Mongo
|
|
38
38
|
:auth_source,
|
39
39
|
:connect,
|
40
40
|
:connect_timeout,
|
41
|
+
:compressors,
|
41
42
|
:database,
|
42
43
|
:heartbeat_frequency,
|
43
44
|
:id_generator,
|
@@ -69,9 +70,15 @@ module Mongo
|
|
69
70
|
:truncate_logs,
|
70
71
|
:user,
|
71
72
|
:wait_queue_timeout,
|
72
|
-
:write
|
73
|
+
:write,
|
74
|
+
:zlib_compression_level
|
73
75
|
].freeze
|
74
76
|
|
77
|
+
# The compression algorithms supported by the driver.
|
78
|
+
#
|
79
|
+
# @since 2.5.0
|
80
|
+
VALID_COMPRESSORS = [ Mongo::Protocol::Compressed::ZLIB ].freeze
|
81
|
+
|
75
82
|
# @return [ Mongo::Cluster ] cluster The cluster of servers for the client.
|
76
83
|
attr_reader :cluster
|
77
84
|
|
@@ -87,6 +94,8 @@ module Mongo
|
|
87
94
|
# Delegate subscription to monitoring.
|
88
95
|
def_delegators :@monitoring, :subscribe, :unsubscribe
|
89
96
|
|
97
|
+
def_delegators :@cluster, :logical_session_timeout
|
98
|
+
|
90
99
|
# Determine if this client is equivalent to another object.
|
91
100
|
#
|
92
101
|
# @example Check client equality.
|
@@ -165,6 +174,8 @@ module Mongo
|
|
165
174
|
# seconds, in the connection pool for a connection to be checked in.
|
166
175
|
# @option options [ Float ] :connect_timeout The timeout, in seconds, to
|
167
176
|
# attempt a connection.
|
177
|
+
# @option options [ Array<String> ] :compressors The compressor to use. Currently the driver
|
178
|
+
# only supports zlib.
|
168
179
|
# @option options [ Hash ] :read The read preference options. They consist of a
|
169
180
|
# mode specified as a symbol, an array of hashes known as tag_sets,
|
170
181
|
# and local_threshold.
|
@@ -229,14 +240,32 @@ module Mongo
|
|
229
240
|
# @since 2.0.0
|
230
241
|
def initialize(addresses_or_uri, options = Options::Redacted.new)
|
231
242
|
@monitoring = Monitoring.new(options)
|
243
|
+
Session::SessionPool.create(self)
|
232
244
|
if addresses_or_uri.is_a?(::String)
|
233
245
|
create_from_uri(addresses_or_uri, validate_options!(options))
|
234
246
|
else
|
235
247
|
create_from_addresses(addresses_or_uri, validate_options!(options))
|
236
248
|
end
|
249
|
+
ObjectSpace.define_finalizer(self, self.class.finalize(@session_pool))
|
237
250
|
yield(self) if block_given?
|
238
251
|
end
|
239
252
|
|
253
|
+
# Finalize the client for garbage collection. Ends all sessions in the session pool.
|
254
|
+
#
|
255
|
+
# @example Finalize the client.
|
256
|
+
# Client.finalize(session_pool)
|
257
|
+
#
|
258
|
+
# @param [ Session::SessionPool ] session_pool The session pool.
|
259
|
+
#
|
260
|
+
# @return [ Proc ] The Finalizer.
|
261
|
+
#
|
262
|
+
# @since 2.5.0
|
263
|
+
def self.finalize(session_pool)
|
264
|
+
proc do
|
265
|
+
begin; session_pool.end_sessions; rescue; end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
240
269
|
# Get an inspection of the client as a string.
|
241
270
|
#
|
242
271
|
# @example Inspect the client.
|
@@ -249,17 +278,30 @@ module Mongo
|
|
249
278
|
"#<Mongo::Client:0x#{object_id} cluster=#{cluster.addresses.join(', ')}>"
|
250
279
|
end
|
251
280
|
|
281
|
+
# Get the server selector. It either uses the read preference defined in the client options
|
282
|
+
# or defaults to a Primary server selector.
|
283
|
+
#
|
284
|
+
# @example Get the server selector.
|
285
|
+
# client.server_selector
|
286
|
+
#
|
287
|
+
# @return [ Mongo::ServerSelector ] The server selector using the user-defined read preference
|
288
|
+
# or a Primary server selector default.
|
289
|
+
#
|
290
|
+
# @since 2.5.0
|
291
|
+
def server_selector
|
292
|
+
@server_selector ||= ServerSelector.get(read_preference || ServerSelector::PRIMARY)
|
293
|
+
end
|
294
|
+
|
252
295
|
# Get the read preference from the options passed to the client.
|
253
296
|
#
|
254
297
|
# @example Get the read preference.
|
255
298
|
# client.read_preference
|
256
299
|
#
|
257
|
-
# @return [
|
258
|
-
# was provided to the client.
|
300
|
+
# @return [ BSON::Document ] The user-defined read preference.
|
259
301
|
#
|
260
302
|
# @since 2.0.0
|
261
303
|
def read_preference
|
262
|
-
@read_preference ||=
|
304
|
+
@read_preference ||= options[:read]
|
263
305
|
end
|
264
306
|
|
265
307
|
# Use the database with the provided name. This will switch the current
|
@@ -294,6 +336,7 @@ module Mongo
|
|
294
336
|
opts = validate_options!(new_options)
|
295
337
|
client.options.update(opts)
|
296
338
|
Database.create(client)
|
339
|
+
Session::SessionPool.create(client)
|
297
340
|
# We can't use the same cluster if some options that would affect it
|
298
341
|
# have changed.
|
299
342
|
if cluster_modifying?(opts)
|
@@ -363,8 +406,58 @@ module Mongo
|
|
363
406
|
use(Database::ADMIN).command(listDatabases: 1).first[Database::DATABASES]
|
364
407
|
end
|
365
408
|
|
409
|
+
# Start a session.
|
410
|
+
#
|
411
|
+
# @example Start a session.
|
412
|
+
# client.start_session
|
413
|
+
#
|
414
|
+
# @param [ Hash ] options The session options.
|
415
|
+
#
|
416
|
+
# @note A Session cannot be used by multiple threads at once; session objects are not
|
417
|
+
# thread-safe.
|
418
|
+
#
|
419
|
+
# @return [ Session ] The session.
|
420
|
+
#
|
421
|
+
# @since 2.5.0
|
422
|
+
def start_session(options = {})
|
423
|
+
if !sessions_supported?
|
424
|
+
raise Error::InvalidSession.new(Session::SESSIONS_NOT_SUPPORTED)
|
425
|
+
end
|
426
|
+
Session.new(@session_pool.checkout, self, options)
|
427
|
+
end
|
428
|
+
|
366
429
|
private
|
367
430
|
|
431
|
+
def get_session(options = {})
|
432
|
+
if options[:session]
|
433
|
+
options[:session].validate!(self)
|
434
|
+
options[:session]
|
435
|
+
elsif sessions_supported?
|
436
|
+
Session.new(@session_pool.checkout, self, options.merge(implicit: true))
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
440
|
+
def with_session(options = {})
|
441
|
+
if options[:session]
|
442
|
+
options[:session].validate!(self)
|
443
|
+
yield(options[:session])
|
444
|
+
elsif sessions_supported?
|
445
|
+
@session_pool.with_session do |server_session|
|
446
|
+
yield(Session.new(server_session, self, options))
|
447
|
+
end
|
448
|
+
else
|
449
|
+
yield
|
450
|
+
end
|
451
|
+
end
|
452
|
+
|
453
|
+
def sessions_supported?
|
454
|
+
if cluster.servers.empty?
|
455
|
+
ServerSelector.get(mode: :primary_preferred).select_server(cluster)
|
456
|
+
end
|
457
|
+
!!logical_session_timeout
|
458
|
+
rescue Error::NoServerAvailable
|
459
|
+
end
|
460
|
+
|
368
461
|
def create_from_addresses(addresses, opts = Options::Redacted.new)
|
369
462
|
@options = Database::DEFAULT_OPTIONS.merge(opts).freeze
|
370
463
|
@cluster = Cluster.new(addresses, @monitoring, options)
|
@@ -373,8 +466,7 @@ module Mongo
|
|
373
466
|
|
374
467
|
def create_from_uri(connection_string, opts = Options::Redacted.new)
|
375
468
|
uri = URI.new(connection_string, opts)
|
376
|
-
@options = Database::DEFAULT_OPTIONS.merge(uri.client_options.merge(opts)).freeze
|
377
|
-
validate_options!(@options)
|
469
|
+
@options = validate_options!(Database::DEFAULT_OPTIONS.merge(uri.client_options.merge(opts))).freeze
|
378
470
|
@cluster = Cluster.new(uri.servers, @monitoring, options)
|
379
471
|
@database = Database.new(self, options[:database], options)
|
380
472
|
end
|
@@ -398,18 +490,37 @@ module Mongo
|
|
398
490
|
|
399
491
|
def validate_options!(opts = Options::Redacted.new)
|
400
492
|
return Options::Redacted.new unless opts
|
401
|
-
Options::Redacted.new
|
402
|
-
|
403
|
-
|
493
|
+
opts.each.inject(Options::Redacted.new) do |_options, (k, v)|
|
494
|
+
key = k.to_sym
|
495
|
+
if VALID_OPTIONS.include?(key)
|
496
|
+
validate_max_min_pool_size!(key, opts)
|
497
|
+
if key == :compressors
|
498
|
+
compressors = valid_compressors(v)
|
499
|
+
_options[key] = compressors unless compressors.empty?
|
500
|
+
else
|
501
|
+
_options[key] = v
|
502
|
+
end
|
404
503
|
else
|
405
|
-
log_warn("Unsupported client option '#{
|
504
|
+
log_warn("Unsupported client option '#{k}'. It will be ignored.")
|
505
|
+
end
|
506
|
+
_options
|
507
|
+
end
|
508
|
+
end
|
509
|
+
|
510
|
+
def valid_compressors(compressors)
|
511
|
+
compressors.select do |compressor|
|
512
|
+
if !VALID_COMPRESSORS.include?(compressor)
|
513
|
+
log_warn("Unsupported compressor '#{compressor}' in list '#{compressors}'. " +
|
514
|
+
"This compressor will not be used.")
|
406
515
|
false
|
516
|
+
else
|
517
|
+
true
|
407
518
|
end
|
408
|
-
end
|
519
|
+
end
|
409
520
|
end
|
410
521
|
|
411
522
|
def validate_max_min_pool_size!(option, opts)
|
412
|
-
if option == :min_pool_size
|
523
|
+
if option == :min_pool_size && opts[:min_pool_size]
|
413
524
|
max = opts[:max_pool_size] || Server::ConnectionPool::Queue::MAX_SIZE
|
414
525
|
raise Error::InvalidMinPoolSize.new(opts[:min_pool_size], max) unless opts[:min_pool_size] <= max
|
415
526
|
end
|