mongo 2.4.3 → 2.5.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.
- 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
|