mongo 2.20.1 → 2.21.0
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
- data/README.md +3 -0
- data/Rakefile +2 -2
- data/lib/mongo/address.rb +22 -3
- data/lib/mongo/auth/aws/credentials_retriever.rb +70 -17
- data/lib/mongo/auth/base.rb +1 -1
- data/lib/mongo/bulk_write.rb +35 -2
- data/lib/mongo/client.rb +38 -6
- data/lib/mongo/client_encryption.rb +6 -3
- data/lib/mongo/cluster/reapers/cursor_reaper.rb +6 -1
- data/lib/mongo/cluster/sdam_flow.rb +20 -7
- data/lib/mongo/cluster.rb +14 -4
- data/lib/mongo/collection/helpers.rb +1 -1
- data/lib/mongo/collection/view/aggregation/behavior.rb +131 -0
- data/lib/mongo/collection/view/aggregation.rb +33 -99
- data/lib/mongo/collection/view/builder/aggregation.rb +1 -7
- data/lib/mongo/collection/view/change_stream.rb +80 -27
- data/lib/mongo/collection/view/iterable.rb +76 -60
- data/lib/mongo/collection/view/map_reduce.rb +25 -8
- data/lib/mongo/collection/view/readable.rb +79 -30
- data/lib/mongo/collection/view/writable.rb +109 -48
- data/lib/mongo/collection/view.rb +43 -3
- data/lib/mongo/collection.rb +158 -23
- data/lib/mongo/crypt/auto_encrypter.rb +4 -6
- data/lib/mongo/crypt/binding.rb +4 -4
- data/lib/mongo/crypt/context.rb +20 -14
- data/lib/mongo/crypt/encryption_io.rb +56 -26
- data/lib/mongo/crypt/explicit_encrypter.rb +49 -20
- data/lib/mongo/crypt/explicit_encryption_context.rb +17 -11
- data/lib/mongo/crypt/kms/azure/credentials_retriever.rb +22 -6
- data/lib/mongo/crypt/kms/gcp/credentials_retriever.rb +29 -4
- data/lib/mongo/csot_timeout_holder.rb +119 -0
- data/lib/mongo/cursor/kill_spec.rb +5 -2
- data/lib/mongo/cursor/nontailable.rb +27 -0
- data/lib/mongo/cursor.rb +86 -24
- data/lib/mongo/cursor_host.rb +82 -0
- data/lib/mongo/database/view.rb +81 -14
- data/lib/mongo/database.rb +88 -18
- data/lib/mongo/error/operation_failure.rb +209 -204
- data/lib/mongo/error/server_timeout_error.rb +12 -0
- data/lib/mongo/error/socket_timeout_error.rb +3 -1
- data/lib/mongo/error/timeout_error.rb +23 -0
- data/lib/mongo/error.rb +2 -0
- data/lib/mongo/grid/fs_bucket.rb +45 -12
- data/lib/mongo/grid/stream/read.rb +15 -1
- data/lib/mongo/grid/stream/write.rb +21 -4
- data/lib/mongo/index/view.rb +77 -16
- data/lib/mongo/operation/context.rb +40 -2
- data/lib/mongo/operation/create_search_indexes/op_msg.rb +2 -2
- data/lib/mongo/operation/delete/op_msg.rb +2 -1
- data/lib/mongo/operation/drop_search_index/op_msg.rb +2 -2
- data/lib/mongo/operation/find/op_msg.rb +45 -0
- data/lib/mongo/operation/get_more/op_msg.rb +33 -0
- data/lib/mongo/operation/insert/op_msg.rb +3 -2
- data/lib/mongo/operation/insert/result.rb +4 -2
- data/lib/mongo/operation/list_collections/result.rb +1 -1
- data/lib/mongo/operation/map_reduce/result.rb +1 -1
- data/lib/mongo/operation/op_msg_base.rb +3 -1
- data/lib/mongo/operation/result.rb +26 -5
- data/lib/mongo/operation/shared/executable.rb +12 -1
- data/lib/mongo/operation/shared/op_msg_executable.rb +4 -1
- data/lib/mongo/operation/shared/response_handling.rb +3 -3
- data/lib/mongo/operation/shared/sessions_supported.rb +1 -1
- data/lib/mongo/operation/shared/timed.rb +52 -0
- data/lib/mongo/operation/shared/write.rb +4 -1
- data/lib/mongo/operation/update/op_msg.rb +2 -1
- data/lib/mongo/operation/update_search_index/op_msg.rb +2 -2
- data/lib/mongo/operation.rb +1 -0
- data/lib/mongo/protocol/message.rb +1 -4
- data/lib/mongo/protocol/msg.rb +2 -2
- data/lib/mongo/retryable/read_worker.rb +69 -29
- data/lib/mongo/retryable/write_worker.rb +49 -18
- data/lib/mongo/retryable.rb +8 -2
- data/lib/mongo/server/connection.rb +11 -5
- data/lib/mongo/server/connection_base.rb +22 -2
- data/lib/mongo/server/connection_pool.rb +32 -14
- data/lib/mongo/server/description/features.rb +1 -1
- data/lib/mongo/server/description.rb +18 -5
- data/lib/mongo/server/monitor.rb +7 -4
- data/lib/mongo/server/pending_connection.rb +7 -3
- data/lib/mongo/server/{round_trip_time_averager.rb → round_trip_time_calculator.rb} +25 -7
- data/lib/mongo/server.rb +11 -6
- data/lib/mongo/server_selector/base.rb +25 -9
- data/lib/mongo/session.rb +78 -9
- data/lib/mongo/socket/ssl.rb +109 -17
- data/lib/mongo/socket/tcp.rb +40 -6
- data/lib/mongo/socket.rb +154 -25
- data/lib/mongo/uri/options_mapper.rb +1 -0
- data/lib/mongo/version.rb +1 -1
- data/lib/mongo.rb +1 -0
- data/spec/atlas/atlas_connectivity_spec.rb +4 -0
- data/spec/atlas/operations_spec.rb +4 -0
- data/spec/integration/client_side_encryption/auto_encryption_mongocryptd_spawn_spec.rb +2 -1
- data/spec/integration/client_side_encryption/auto_encryption_spec.rb +494 -487
- data/spec/integration/client_side_encryption/on_demand_aws_credentials_spec.rb +1 -1
- data/spec/integration/client_side_encryption/range_explicit_encryption_prose_spec.rb +66 -22
- data/spec/integration/client_side_operations_timeout/encryption_prose_spec.rb +131 -0
- data/spec/integration/connection_pool_populator_spec.rb +2 -0
- data/spec/integration/cursor_pinning_spec.rb +15 -60
- data/spec/integration/cursor_reaping_spec.rb +1 -1
- data/spec/integration/docs_examples_spec.rb +1 -1
- data/spec/integration/operation_failure_code_spec.rb +1 -1
- data/spec/integration/operation_failure_message_spec.rb +3 -3
- data/spec/integration/retryable_errors_spec.rb +2 -2
- data/spec/integration/sdam_error_handling_spec.rb +2 -1
- data/spec/integration/search_indexes_prose_spec.rb +4 -0
- data/spec/integration/server_spec.rb +4 -3
- data/spec/integration/transactions_api_examples_spec.rb +2 -0
- data/spec/kerberos/kerberos_spec.rb +4 -0
- data/spec/lite_spec_helper.rb +3 -1
- data/spec/mongo/auth/user/view_spec.rb +1 -1
- data/spec/mongo/caching_cursor_spec.rb +1 -1
- data/spec/mongo/client_encryption_spec.rb +1 -0
- data/spec/mongo/client_spec.rb +158 -4
- data/spec/mongo/collection/view/aggregation_spec.rb +14 -39
- data/spec/mongo/collection/view/change_stream_spec.rb +3 -3
- data/spec/mongo/collection_spec.rb +5 -6
- data/spec/mongo/crypt/auto_encrypter_spec.rb +14 -12
- data/spec/mongo/crypt/data_key_context_spec.rb +3 -1
- data/spec/mongo/crypt/explicit_encryption_context_spec.rb +2 -2
- data/spec/mongo/crypt/handle_spec.rb +1 -1
- data/spec/mongo/cursor_spec.rb +26 -9
- data/spec/mongo/error/operation_failure_heavy_spec.rb +2 -2
- data/spec/mongo/operation/context_spec.rb +79 -0
- data/spec/mongo/operation/create/op_msg_spec.rb +106 -110
- data/spec/mongo/operation/delete/op_msg_spec.rb +6 -5
- data/spec/mongo/operation/find/op_msg_spec.rb +66 -0
- data/spec/mongo/operation/get_more/op_msg_spec.rb +65 -0
- data/spec/mongo/operation/insert/op_msg_spec.rb +128 -131
- data/spec/mongo/operation/shared/csot/examples.rb +113 -0
- data/spec/mongo/query_cache_spec.rb +243 -225
- data/spec/mongo/retryable_spec.rb +1 -0
- data/spec/mongo/server/round_trip_time_calculator_spec.rb +120 -0
- data/spec/mongo/socket/ssl_spec.rb +0 -10
- data/spec/runners/change_streams/test.rb +2 -2
- data/spec/runners/crud/operation.rb +1 -1
- data/spec/runners/crud/verifier.rb +3 -1
- data/spec/runners/transactions/operation.rb +4 -6
- data/spec/runners/unified/ambiguous_operations.rb +13 -0
- data/spec/runners/unified/assertions.rb +4 -0
- data/spec/runners/unified/change_stream_operations.rb +14 -24
- data/spec/runners/unified/crud_operations.rb +82 -59
- data/spec/runners/unified/ddl_operations.rb +38 -7
- data/spec/runners/unified/grid_fs_operations.rb +37 -2
- data/spec/runners/unified/support_operations.rb +43 -4
- data/spec/runners/unified/test.rb +22 -10
- data/spec/runners/unified.rb +1 -1
- data/spec/solo/clean_exit_spec.rb +2 -0
- data/spec/spec_tests/client_side_operations_timeout_spec.rb +15 -0
- data/spec/spec_tests/data/change_streams_unified/change-streams-clusterTime.yml +3 -1
- data/spec/spec_tests/data/change_streams_unified/change-streams-disambiguatedPaths.yml +3 -1
- data/spec/spec_tests/data/change_streams_unified/change-streams-errors.yml +3 -1
- data/spec/spec_tests/data/change_streams_unified/change-streams-pre_and_post_images.yml +1 -1
- data/spec/spec_tests/data/change_streams_unified/change-streams-resume-allowlist.yml +1 -1
- data/spec/spec_tests/data/change_streams_unified/change-streams-resume-errorLabels.yml +1 -1
- data/spec/spec_tests/data/change_streams_unified/change-streams-showExpandedEvents.yml +1 -1
- data/spec/spec_tests/data/client_side_encryption/badQueries.yml +2 -1
- data/spec/spec_tests/data/client_side_encryption/timeoutMS.yml +67 -0
- data/spec/spec_tests/data/client_side_operations_timeout/bulkWrite.yml +87 -0
- data/spec/spec_tests/data/client_side_operations_timeout/change-streams.yml +358 -0
- data/spec/spec_tests/data/client_side_operations_timeout/close-cursors.yml +129 -0
- data/spec/spec_tests/data/client_side_operations_timeout/command-execution.yml +250 -0
- data/spec/spec_tests/data/client_side_operations_timeout/convenient-transactions.yml +113 -0
- data/spec/spec_tests/data/client_side_operations_timeout/cursors.yml +70 -0
- data/spec/spec_tests/data/client_side_operations_timeout/deprecated-options.yml +3982 -0
- data/spec/spec_tests/data/client_side_operations_timeout/error-transformations.yml +96 -0
- data/spec/spec_tests/data/client_side_operations_timeout/global-timeoutMS.yml +3236 -0
- data/spec/spec_tests/data/client_side_operations_timeout/gridfs-advanced.yml +207 -0
- data/spec/spec_tests/data/client_side_operations_timeout/gridfs-delete.yml +152 -0
- data/spec/spec_tests/data/client_side_operations_timeout/gridfs-download.yml +182 -0
- data/spec/spec_tests/data/client_side_operations_timeout/gridfs-find.yml +100 -0
- data/spec/spec_tests/data/client_side_operations_timeout/gridfs-upload.yml +249 -0
- data/spec/spec_tests/data/client_side_operations_timeout/legacy-timeouts.yml +204 -0
- data/spec/spec_tests/data/client_side_operations_timeout/non-tailable-cursors.yml +307 -0
- data/spec/spec_tests/data/client_side_operations_timeout/override-collection-timeoutMS.yml +1877 -0
- data/spec/spec_tests/data/client_side_operations_timeout/override-operation-timeoutMS.yml +1918 -0
- data/spec/spec_tests/data/client_side_operations_timeout/retryability-legacy-timeouts.yml +1676 -0
- data/spec/spec_tests/data/client_side_operations_timeout/retryability-timeoutMS.yml +2824 -0
- data/spec/spec_tests/data/client_side_operations_timeout/sessions-inherit-timeoutMS.yml +168 -0
- data/spec/spec_tests/data/client_side_operations_timeout/sessions-override-operation-timeoutMS.yml +171 -0
- data/spec/spec_tests/data/client_side_operations_timeout/sessions-override-timeoutMS.yml +168 -0
- data/spec/spec_tests/data/client_side_operations_timeout/tailable-awaitData.yml +247 -0
- data/spec/spec_tests/data/client_side_operations_timeout/tailable-non-awaitData.yml +181 -0
- data/spec/spec_tests/data/crud_unified/aggregate-write-readPreference.yml +4 -0
- data/spec/spec_tests/data/crud_unified/db-aggregate-write-readPreference.yml +4 -0
- data/spec/spec_tests/data/crud_unified/find-test-all-options.yml +29 -0
- data/spec/spec_tests/server_selection_rtt_spec.rb +6 -6
- data/spec/support/certificates/atlas-ocsp-ca.crt +81 -83
- data/spec/support/certificates/atlas-ocsp.crt +107 -107
- data/spec/support/cluster_tools.rb +3 -3
- data/spec/support/common_shortcuts.rb +2 -2
- data/spec/support/crypt/encrypted_fields/range-encryptedFields-Date.json +1 -1
- data/spec/support/crypt/encrypted_fields/range-encryptedFields-DecimalNoPrecision.json +1 -1
- data/spec/support/crypt/encrypted_fields/range-encryptedFields-DecimalPrecision.json +1 -1
- data/spec/support/crypt/encrypted_fields/range-encryptedFields-DoubleNoPrecision.json +1 -1
- data/spec/support/crypt/encrypted_fields/range-encryptedFields-DoublePrecision.json +1 -1
- data/spec/support/crypt/encrypted_fields/range-encryptedFields-Int.json +1 -1
- data/spec/support/crypt/encrypted_fields/range-encryptedFields-Long.json +1 -1
- data/spec/support/shared/session.rb +2 -2
- data/spec/support/spec_setup.rb +2 -2
- data/spec/support/utils.rb +3 -1
- metadata +78 -91
- data/spec/mongo/server/round_trip_time_averager_spec.rb +0 -48
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Aggregate.yml +0 -242
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Correctness.yml +0 -423
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Delete.yml +0 -183
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-FindOneAndUpdate.yml +0 -240
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-InsertFind.yml +0 -236
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Update.yml +0 -253
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Aggregate.yml +0 -1688
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Correctness.yml +0 -294
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Delete.yml +0 -906
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-FindOneAndUpdate.yml +0 -1685
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-InsertFind.yml +0 -1681
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Update.yml +0 -1698
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Aggregate.yml +0 -330
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Correctness.yml +0 -425
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Delete.yml +0 -227
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-FindOneAndUpdate.yml +0 -328
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-InsertFind.yml +0 -320
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Update.yml +0 -337
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Aggregate.yml +0 -914
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Correctness.yml +0 -293
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Delete.yml +0 -519
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-FindOneAndUpdate.yml +0 -912
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-InsertFind.yml +0 -908
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Update.yml +0 -925
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Aggregate.yml +0 -326
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Correctness.yml +0 -425
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Delete.yml +0 -225
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-FindOneAndUpdate.yml +0 -324
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-InsertFind.yml +0 -320
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Update.yml +0 -339
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Aggregate.yml +0 -242
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Correctness.yml +0 -424
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Delete.yml +0 -183
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-FindOneAndUpdate.yml +0 -240
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-InsertFind.yml +0 -236
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Update.yml +0 -255
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Aggregate.yml +0 -242
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Correctness.yml +0 -423
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Delete.yml +0 -183
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-FindOneAndUpdate.yml +0 -240
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-InsertFind.yml +0 -236
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Update.yml +0 -255
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-WrongType.yml +0 -44
@@ -15,6 +15,8 @@
|
|
15
15
|
# See the License for the specific language governing permissions and
|
16
16
|
# limitations under the License.
|
17
17
|
|
18
|
+
require 'mongo/cursor_host'
|
19
|
+
|
18
20
|
module Mongo
|
19
21
|
class Collection
|
20
22
|
class View
|
@@ -24,13 +26,7 @@ module Mongo
|
|
24
26
|
#
|
25
27
|
# @since 2.0.0
|
26
28
|
module Iterable
|
27
|
-
|
28
|
-
# Returns the cursor associated with this view, if any.
|
29
|
-
#
|
30
|
-
# @return [ nil | Cursor ] The cursor, if any.
|
31
|
-
#
|
32
|
-
# @api private
|
33
|
-
attr_reader :cursor
|
29
|
+
include Mongo::CursorHost
|
34
30
|
|
35
31
|
# Iterate through documents returned by a query with this +View+.
|
36
32
|
#
|
@@ -45,48 +41,21 @@ module Mongo
|
|
45
41
|
#
|
46
42
|
# @yieldparam [ Hash ] Each matching document.
|
47
43
|
def each
|
48
|
-
|
49
|
-
|
50
|
-
# we have no way of completing that iteration.
|
51
|
-
# Therefore, discard that cursor and start iteration again.
|
52
|
-
# The case of the caching cursor not being closed and not having
|
53
|
-
# been fully iterated isn't tested - see RUBY-2773.
|
54
|
-
@cursor = if use_query_cache? && cached_cursor && (
|
55
|
-
cached_cursor.fully_iterated? || !cached_cursor.closed?
|
56
|
-
)
|
57
|
-
cached_cursor
|
58
|
-
else
|
59
|
-
session = client.send(:get_session, @options)
|
60
|
-
select_cursor(session).tap do |cursor|
|
61
|
-
if use_query_cache?
|
62
|
-
# No need to store the cursor in the query cache if there is
|
63
|
-
# already a cached cursor stored at this key.
|
64
|
-
QueryCache.set(cursor, **cache_options)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
44
|
+
@cursor = prefer_cached_cursor? ? cached_cursor : new_cursor_for_iteration
|
45
|
+
return @cursor.to_enum unless block_given?
|
68
46
|
|
69
|
-
|
70
|
-
# If a query with a limit is performed, the query cache will
|
71
|
-
# re-use results from an earlier query with the same or larger
|
72
|
-
# limit, and then impose the lower limit during iteration.
|
73
|
-
limit_for_cached_query = respond_to?(:limit) ? QueryCache.normalized_limit(limit) : nil
|
74
|
-
end
|
47
|
+
limit_for_cached_query = compute_limit_for_cached_query
|
75
48
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
@cursor.to_a[0...limit_for_cached_query]
|
81
|
-
else
|
82
|
-
@cursor
|
83
|
-
end
|
84
|
-
|
85
|
-
cursor_to_iterate.each do |doc|
|
86
|
-
yield doc
|
87
|
-
end
|
49
|
+
# Ruby versions 2.5 and older do not support arr[0..nil] syntax, so
|
50
|
+
# this must be a separate conditional.
|
51
|
+
cursor_to_iterate = if limit_for_cached_query
|
52
|
+
@cursor.to_a[0...limit_for_cached_query]
|
88
53
|
else
|
89
|
-
@cursor
|
54
|
+
@cursor
|
55
|
+
end
|
56
|
+
|
57
|
+
cursor_to_iterate.each do |doc|
|
58
|
+
yield doc
|
90
59
|
end
|
91
60
|
end
|
92
61
|
|
@@ -100,7 +69,7 @@ module Mongo
|
|
100
69
|
#
|
101
70
|
# @return [ nil ] Always nil.
|
102
71
|
#
|
103
|
-
# @raise [ Error::OperationFailure ] If the server cursor close fails.
|
72
|
+
# @raise [ Error::OperationFailure::Family ] If the server cursor close fails.
|
104
73
|
#
|
105
74
|
# @since 2.1.0
|
106
75
|
def close_query
|
@@ -113,18 +82,25 @@ module Mongo
|
|
113
82
|
private
|
114
83
|
|
115
84
|
def select_cursor(session)
|
85
|
+
context = Operation::Context.new(
|
86
|
+
client: client,
|
87
|
+
session: session,
|
88
|
+
operation_timeouts: operation_timeouts,
|
89
|
+
view: self
|
90
|
+
)
|
91
|
+
|
116
92
|
if respond_to?(:write?, true) && write?
|
117
93
|
server = server_selector.select_server(cluster, nil, session, write_aggregation: true)
|
118
|
-
result = send_initial_query(server,
|
94
|
+
result = send_initial_query(server, context)
|
119
95
|
|
120
96
|
if use_query_cache?
|
121
|
-
CachingCursor.new(view, result, server, session: session)
|
97
|
+
CachingCursor.new(view, result, server, session: session, context: context)
|
122
98
|
else
|
123
|
-
Cursor.new(view, result, server, session: session)
|
99
|
+
Cursor.new(view, result, server, session: session, context: context)
|
124
100
|
end
|
125
101
|
else
|
126
|
-
read_with_retry_cursor(session, server_selector, view) do |server|
|
127
|
-
send_initial_query(server,
|
102
|
+
read_with_retry_cursor(session, server_selector, view, context: context) do |server|
|
103
|
+
send_initial_query(server, context)
|
128
104
|
end
|
129
105
|
end
|
130
106
|
end
|
@@ -168,18 +144,13 @@ module Mongo
|
|
168
144
|
batch_size: batch_size,
|
169
145
|
hint: options[:hint],
|
170
146
|
max_scan: options[:max_scan],
|
171
|
-
max_time_ms: options[:max_time_ms],
|
172
147
|
max_value: options[:max_value],
|
173
148
|
min_value: options[:min_value],
|
174
149
|
no_cursor_timeout: options[:no_cursor_timeout],
|
175
150
|
return_key: options[:return_key],
|
176
151
|
show_disk_loc: options[:show_disk_loc],
|
177
152
|
comment: options[:comment],
|
178
|
-
oplog_replay:
|
179
|
-
collection.options[:oplog_replay]
|
180
|
-
else
|
181
|
-
v
|
182
|
-
end,
|
153
|
+
oplog_replay: oplog_replay
|
183
154
|
}
|
184
155
|
|
185
156
|
if spec[:oplog_replay]
|
@@ -196,14 +167,52 @@ module Mongo
|
|
196
167
|
end
|
197
168
|
end
|
198
169
|
|
199
|
-
def send_initial_query(server,
|
200
|
-
initial_query_op(
|
170
|
+
def send_initial_query(server, context)
|
171
|
+
operation = initial_query_op(context.session)
|
172
|
+
if server.load_balancer?
|
173
|
+
# Connection will be checked in when cursor is drained.
|
174
|
+
connection = server.pool.check_out(context: context)
|
175
|
+
operation.execute_with_connection(connection, context: context)
|
176
|
+
else
|
177
|
+
operation.execute(server, context: context)
|
178
|
+
end
|
201
179
|
end
|
202
180
|
|
203
181
|
def use_query_cache?
|
204
182
|
QueryCache.enabled? && !collection.system_collection?
|
205
183
|
end
|
206
184
|
|
185
|
+
# If the caching cursor is closed and was not fully iterated,
|
186
|
+
# the documents we have in it are not the complete result set and
|
187
|
+
# we have no way of completing that iteration.
|
188
|
+
# Therefore, discard that cursor and start iteration again.
|
189
|
+
def prefer_cached_cursor?
|
190
|
+
use_query_cache? &&
|
191
|
+
cached_cursor &&
|
192
|
+
(cached_cursor.fully_iterated? || !cached_cursor.closed?)
|
193
|
+
end
|
194
|
+
|
195
|
+
# Start a new cursor for use when iterating (via #each).
|
196
|
+
def new_cursor_for_iteration
|
197
|
+
session = client.get_session(@options)
|
198
|
+
select_cursor(session).tap do |cursor|
|
199
|
+
if use_query_cache?
|
200
|
+
# No need to store the cursor in the query cache if there is
|
201
|
+
# already a cached cursor stored at this key.
|
202
|
+
QueryCache.set(cursor, **cache_options)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def compute_limit_for_cached_query
|
208
|
+
return nil unless use_query_cache? && respond_to?(:limit)
|
209
|
+
|
210
|
+
# If a query with a limit is performed, the query cache will
|
211
|
+
# re-use results from an earlier query with the same or larger
|
212
|
+
# limit, and then impose the lower limit during iteration.
|
213
|
+
return QueryCache.normalized_limit(limit)
|
214
|
+
end
|
215
|
+
|
207
216
|
# Add tailable cusror options to the command specifiction if needed.
|
208
217
|
#
|
209
218
|
# @param [ Hash ] spec The command specification.
|
@@ -216,6 +225,13 @@ module Mongo
|
|
216
225
|
spec[:await_data] = true
|
217
226
|
end
|
218
227
|
end
|
228
|
+
|
229
|
+
# @return [ true | false | nil ] options[:oplog_replay], if
|
230
|
+
# set, otherwise the same option from the collection.
|
231
|
+
def oplog_replay
|
232
|
+
v = options[:oplog_replay]
|
233
|
+
v.nil? ? collection.options[:oplog_replay] : v
|
234
|
+
end
|
219
235
|
end
|
220
236
|
end
|
221
237
|
end
|
@@ -51,7 +51,7 @@ module Mongo
|
|
51
51
|
attr_reader :reduce_function
|
52
52
|
|
53
53
|
# Delegate necessary operations to the view.
|
54
|
-
def_delegators :view, :collection, :read, :cluster
|
54
|
+
def_delegators :view, :collection, :read, :cluster, :timeout_ms
|
55
55
|
|
56
56
|
# Delegate necessary operations to the collection.
|
57
57
|
def_delegators :collection, :database, :client
|
@@ -70,10 +70,18 @@ module Mongo
|
|
70
70
|
# @yieldparam [ Hash ] Each matching document.
|
71
71
|
def each
|
72
72
|
@cursor = nil
|
73
|
-
session = client.
|
73
|
+
session = client.get_session(@options)
|
74
74
|
server = cluster.next_primary(nil, session)
|
75
|
-
|
76
|
-
|
75
|
+
context = Operation::Context.new(client: client, session: session, operation_timeouts: view.operation_timeouts)
|
76
|
+
if server.load_balancer?
|
77
|
+
# Connection will be checked in when cursor is drained.
|
78
|
+
connection = server.pool.check_out(context: context)
|
79
|
+
result = send_initial_query_with_connection(connection, context.session, context: context)
|
80
|
+
result = send_fetch_query_with_connection(connection, session) unless inline?
|
81
|
+
else
|
82
|
+
result = send_initial_query(server, context)
|
83
|
+
result = send_fetch_query(server, session) unless inline?
|
84
|
+
end
|
77
85
|
@cursor = Cursor.new(view, result, server, session: session)
|
78
86
|
if block_given?
|
79
87
|
@cursor.each do |doc|
|
@@ -279,9 +287,9 @@ module Mongo
|
|
279
287
|
out.respond_to?(:keys) && out.keys.first.to_s.downcase == INLINE
|
280
288
|
end
|
281
289
|
|
282
|
-
def send_initial_query(server,
|
290
|
+
def send_initial_query(server, context)
|
283
291
|
server.with_connection do |connection|
|
284
|
-
send_initial_query_with_connection(connection, session, context: context)
|
292
|
+
send_initial_query_with_connection(connection, context.session, context: context)
|
285
293
|
end
|
286
294
|
end
|
287
295
|
|
@@ -305,7 +313,7 @@ module Mongo
|
|
305
313
|
Builder::MapReduce.new(map_function, reduce_function, view, options.merge(session: session)).command_specification
|
306
314
|
end
|
307
315
|
|
308
|
-
def fetch_query_op(
|
316
|
+
def fetch_query_op(session)
|
309
317
|
spec = {
|
310
318
|
coll_name: out_collection_name,
|
311
319
|
db_name: out_database_name,
|
@@ -319,7 +327,16 @@ module Mongo
|
|
319
327
|
end
|
320
328
|
|
321
329
|
def send_fetch_query(server, session)
|
322
|
-
fetch_query_op(
|
330
|
+
fetch_query_op(session).execute(server, context: Operation::Context.new(client: client, session: session))
|
331
|
+
end
|
332
|
+
|
333
|
+
def send_fetch_query_with_connection(connection, session)
|
334
|
+
fetch_query_op(
|
335
|
+
session
|
336
|
+
).execute_with_connection(
|
337
|
+
connection,
|
338
|
+
context: Operation::Context.new(client: client, session: session)
|
339
|
+
)
|
323
340
|
end
|
324
341
|
end
|
325
342
|
end
|
@@ -47,12 +47,13 @@ module Mongo
|
|
47
47
|
# @option options [ Hash ] :let Mapping of variables to use in the pipeline.
|
48
48
|
# See the server documentation for details.
|
49
49
|
# @option options [ Integer ] :max_time_ms The maximum amount of time in
|
50
|
-
# milliseconds to allow the aggregation to run.
|
51
|
-
#
|
52
|
-
# will request that the server provide results using a cursor. Note that
|
53
|
-
# as of server version 3.6, aggregations always provide results using a
|
54
|
-
# cursor and this option is therefore not valid.
|
50
|
+
# milliseconds to allow the aggregation to run. This option is deprecated, use
|
51
|
+
# :timeout_ms instead.
|
55
52
|
# @option options [ Session ] :session The session to use.
|
53
|
+
# @option options [ Integer ] :timeout_ms The operation timeout in milliseconds.
|
54
|
+
# Must be a non-negative integer. An explicit value of 0 means infinite.
|
55
|
+
# The default value is unset which means the value is inherited from
|
56
|
+
# the collection or the database or the client.
|
56
57
|
#
|
57
58
|
# @return [ Aggregation ] The aggregation object.
|
58
59
|
#
|
@@ -157,6 +158,10 @@ module Mongo
|
|
157
158
|
# @option opts [ Mongo::Session ] :session The session to use for the operation.
|
158
159
|
# @option opts [ Object ] :comment A user-provided
|
159
160
|
# comment to attach to this command.
|
161
|
+
# @option options [ Integer ] :timeout_ms The operation timeout in milliseconds.
|
162
|
+
# Must be a non-negative integer. An explicit value of 0 means infinite.
|
163
|
+
# The default value is unset which means the value is inherited from
|
164
|
+
# the collection or the database or the client.
|
160
165
|
#
|
161
166
|
# @return [ Integer ] The document count.
|
162
167
|
#
|
@@ -182,7 +187,12 @@ module Mongo
|
|
182
187
|
read_pref = opts[:read] || read_preference
|
183
188
|
selector = ServerSelector.get(read_pref || server_selector)
|
184
189
|
with_session(opts) do |session|
|
185
|
-
|
190
|
+
context = Operation::Context.new(
|
191
|
+
client: client,
|
192
|
+
session: session,
|
193
|
+
operation_timeouts: operation_timeouts(opts)
|
194
|
+
)
|
195
|
+
read_with_retry(session, selector, context) do |server|
|
186
196
|
Operation::Count.new(
|
187
197
|
selector: cmd,
|
188
198
|
db_name: database.name,
|
@@ -193,7 +203,10 @@ module Mongo
|
|
193
203
|
# string key. Note that this isn't documented as valid usage.
|
194
204
|
collation: opts[:collation] || opts['collation'] || collation,
|
195
205
|
comment: opts[:comment],
|
196
|
-
).execute(
|
206
|
+
).execute(
|
207
|
+
server,
|
208
|
+
context: context
|
209
|
+
)
|
197
210
|
end.n.to_i
|
198
211
|
end
|
199
212
|
end
|
@@ -210,12 +223,17 @@ module Mongo
|
|
210
223
|
# MongoDB to use a specific index for the query. Requires server version 3.6+.
|
211
224
|
# @option opts :limit [ Integer ] Max number of docs to count.
|
212
225
|
# @option opts :max_time_ms [ Integer ] The maximum amount of time to allow the
|
213
|
-
# command to run.
|
226
|
+
# command to run. This option is deprecated, use
|
227
|
+
# :timeout_ms instead.
|
214
228
|
# @option opts [ Hash ] :read The read preference options.
|
215
229
|
# @option opts [ Hash ] :collation The collation to use.
|
216
230
|
# @option opts [ Mongo::Session ] :session The session to use for the operation.
|
217
231
|
# @option ops [ Object ] :comment A user-provided
|
218
232
|
# comment to attach to this command.
|
233
|
+
# @option options [ Integer ] :timeout_ms The operation timeout in milliseconds.
|
234
|
+
# Must be a non-negative integer. An explicit value of 0 means infinite.
|
235
|
+
# The default value is unset which means the value is inherited from
|
236
|
+
# the collection or the database or the client.
|
219
237
|
#
|
220
238
|
# @return [ Integer ] The document count.
|
221
239
|
#
|
@@ -227,7 +245,7 @@ module Mongo
|
|
227
245
|
pipeline << { :'$limit' => opts[:limit] } if opts[:limit]
|
228
246
|
pipeline << { :'$group' => { _id: 1, n: { :'$sum' => 1 } } }
|
229
247
|
|
230
|
-
opts = opts.slice(:hint, :max_time_ms, :read, :collation, :session, :comment)
|
248
|
+
opts = opts.slice(:hint, :max_time_ms, :read, :collation, :session, :comment, :timeout_ms)
|
231
249
|
opts[:collation] ||= collation
|
232
250
|
|
233
251
|
first = aggregate(pipeline, opts).first
|
@@ -247,6 +265,10 @@ module Mongo
|
|
247
265
|
# @option opts [ Hash ] :read The read preference options.
|
248
266
|
# @option opts [ Object ] :comment A user-provided
|
249
267
|
# comment to attach to this command.
|
268
|
+
# @option options [ Integer ] :timeout_ms The operation timeout in milliseconds.
|
269
|
+
# Must be a non-negative integer. An explicit value of 0 means infinite.
|
270
|
+
# The default value is unset which means the value is inherited from
|
271
|
+
# the collection or the database or the client.
|
250
272
|
#
|
251
273
|
# @return [ Integer ] The document count.
|
252
274
|
#
|
@@ -267,8 +289,12 @@ module Mongo
|
|
267
289
|
read_pref = opts[:read] || read_preference
|
268
290
|
selector = ServerSelector.get(read_pref || server_selector)
|
269
291
|
with_session(opts) do |session|
|
270
|
-
|
271
|
-
|
292
|
+
context = Operation::Context.new(
|
293
|
+
client: client,
|
294
|
+
session: session,
|
295
|
+
operation_timeouts: operation_timeouts(opts)
|
296
|
+
)
|
297
|
+
read_with_retry(session, selector, context) do |server|
|
272
298
|
cmd = { count: collection.name }
|
273
299
|
cmd[:maxTimeMS] = opts[:max_time_ms] if opts[:max_time_ms]
|
274
300
|
if read_concern
|
@@ -284,7 +310,7 @@ module Mongo
|
|
284
310
|
result.n.to_i
|
285
311
|
end
|
286
312
|
end
|
287
|
-
rescue Error::OperationFailure => exc
|
313
|
+
rescue Error::OperationFailure::Family => exc
|
288
314
|
if exc.code == 26
|
289
315
|
# NamespaceNotFound
|
290
316
|
# This should only happen with the aggregation pipeline path
|
@@ -331,7 +357,12 @@ module Mongo
|
|
331
357
|
read_pref = opts[:read] || read_preference
|
332
358
|
selector = ServerSelector.get(read_pref || server_selector)
|
333
359
|
with_session(opts) do |session|
|
334
|
-
|
360
|
+
context = Operation::Context.new(
|
361
|
+
client: client,
|
362
|
+
session: session,
|
363
|
+
operation_timeouts: operation_timeouts(opts)
|
364
|
+
)
|
365
|
+
read_with_retry(session, selector, context) do |server|
|
335
366
|
Operation::Distinct.new(
|
336
367
|
selector: cmd,
|
337
368
|
db_name: database.name,
|
@@ -342,7 +373,10 @@ module Mongo
|
|
342
373
|
# For some reason collation was historically accepted as a
|
343
374
|
# string key. Note that this isn't documented as valid usage.
|
344
375
|
collation: opts[:collation] || opts['collation'] || collation,
|
345
|
-
).execute(
|
376
|
+
).execute(
|
377
|
+
server,
|
378
|
+
context: context
|
379
|
+
)
|
346
380
|
end.first['values']
|
347
381
|
end
|
348
382
|
end
|
@@ -627,6 +661,15 @@ module Mongo
|
|
627
661
|
configure(:cursor_type, type)
|
628
662
|
end
|
629
663
|
|
664
|
+
# The per-operation timeout in milliseconds. Must a positive integer.
|
665
|
+
#
|
666
|
+
# @param [ Integer ] timeout_ms Timeout value.
|
667
|
+
#
|
668
|
+
# @return [ Integer, View ] Either the timeout_ms value or a new +View+.
|
669
|
+
def timeout_ms(timeout_ms = nil)
|
670
|
+
configure(:timeout_ms, timeout_ms)
|
671
|
+
end
|
672
|
+
|
630
673
|
# @api private
|
631
674
|
def read_concern
|
632
675
|
if options[:session] && options[:session].in_transaction?
|
@@ -656,24 +699,10 @@ module Mongo
|
|
656
699
|
end
|
657
700
|
end
|
658
701
|
|
659
|
-
private
|
660
|
-
|
661
|
-
def collation(doc = nil)
|
662
|
-
configure(:collation, doc)
|
663
|
-
end
|
664
|
-
|
665
|
-
def server_selector
|
666
|
-
@server_selector ||= if options[:session] && options[:session].in_transaction?
|
667
|
-
ServerSelector.get(read_preference || client.server_selector)
|
668
|
-
else
|
669
|
-
ServerSelector.get(read_preference || collection.server_selector)
|
670
|
-
end
|
671
|
-
end
|
672
|
-
|
673
702
|
def parallel_scan(cursor_count, options = {})
|
674
703
|
if options[:session]
|
675
704
|
# The session would be overwritten by the one in +options+ later.
|
676
|
-
session = client.
|
705
|
+
session = client.get_session(@options)
|
677
706
|
else
|
678
707
|
session = nil
|
679
708
|
end
|
@@ -707,11 +736,31 @@ module Mongo
|
|
707
736
|
session: session,
|
708
737
|
connection_global_id: result.connection_global_id,
|
709
738
|
)
|
710
|
-
result =
|
739
|
+
result = if server.load_balancer?
|
740
|
+
# Connection will be checked in when cursor is drained.
|
741
|
+
connection = server.pool.check_out(context: context)
|
742
|
+
op.execute_with_connection(connection, context: context)
|
743
|
+
else
|
744
|
+
op.execute(server, context: context)
|
745
|
+
end
|
711
746
|
Cursor.new(self, result, server, session: session)
|
712
747
|
end
|
713
748
|
end
|
714
749
|
|
750
|
+
private
|
751
|
+
|
752
|
+
def collation(doc = nil)
|
753
|
+
configure(:collation, doc)
|
754
|
+
end
|
755
|
+
|
756
|
+
def server_selector
|
757
|
+
@server_selector ||= if options[:session] && options[:session].in_transaction?
|
758
|
+
ServerSelector.get(read_preference || client.server_selector)
|
759
|
+
else
|
760
|
+
ServerSelector.get(read_preference || collection.server_selector)
|
761
|
+
end
|
762
|
+
end
|
763
|
+
|
715
764
|
def validate_doc!(doc)
|
716
765
|
raise Error::InvalidDocument.new unless doc.respond_to?(:keys)
|
717
766
|
end
|