mongo 2.20.1 → 2.21.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|