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
@@ -0,0 +1,119 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (C) 2024 MongoDB Inc.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
module Mongo
|
18
|
+
# This class stores operation timeout and provides corresponding helper methods.
|
19
|
+
#
|
20
|
+
# @api private
|
21
|
+
class CsotTimeoutHolder
|
22
|
+
def initialize(session: nil, operation_timeouts: {})
|
23
|
+
@deadline = calculate_deadline(operation_timeouts, session)
|
24
|
+
@operation_timeouts = operation_timeouts
|
25
|
+
@timeout_sec = (@deadline - Utils.monotonic_time if @deadline)
|
26
|
+
end
|
27
|
+
|
28
|
+
attr_reader :deadline, :timeout_sec, :operation_timeouts
|
29
|
+
|
30
|
+
# @return [ true | false ] Whether CSOT is enabled for the operation
|
31
|
+
def csot?
|
32
|
+
!deadline.nil?
|
33
|
+
end
|
34
|
+
|
35
|
+
# @return [ true | false ] Returns false if CSOT is not enabled, or if
|
36
|
+
# CSOT is set to 0 (means unlimited), otherwise true.
|
37
|
+
def timeout?
|
38
|
+
![ nil, 0 ].include?(@deadline)
|
39
|
+
end
|
40
|
+
|
41
|
+
# @return [ Float | nil ] Returns the remaining seconds of the timeout
|
42
|
+
# set for the operation; if no timeout is set, or the timeout is 0
|
43
|
+
# (means unlimited) returns nil.
|
44
|
+
def remaining_timeout_sec
|
45
|
+
return nil unless timeout?
|
46
|
+
|
47
|
+
deadline - Utils.monotonic_time
|
48
|
+
end
|
49
|
+
|
50
|
+
def remaining_timeout_sec!
|
51
|
+
check_timeout!
|
52
|
+
remaining_timeout_sec
|
53
|
+
end
|
54
|
+
|
55
|
+
# @return [ Integer | nil ] Returns the remaining milliseconds of the timeout
|
56
|
+
# set for the operation; if no timeout is set, or the timeout is 0
|
57
|
+
# (means unlimited) returns nil.
|
58
|
+
def remaining_timeout_ms
|
59
|
+
seconds = remaining_timeout_sec
|
60
|
+
return nil if seconds.nil?
|
61
|
+
|
62
|
+
(seconds * 1_000).to_i
|
63
|
+
end
|
64
|
+
|
65
|
+
def remaining_timeout_ms!
|
66
|
+
check_timeout!
|
67
|
+
remaining_timeout_ms
|
68
|
+
end
|
69
|
+
|
70
|
+
# @return [ true | false ] Whether the timeout for the operation expired.
|
71
|
+
# If no timeout set, this method returns false.
|
72
|
+
def timeout_expired?
|
73
|
+
if timeout?
|
74
|
+
Utils.monotonic_time >= deadline
|
75
|
+
else
|
76
|
+
false
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Check whether the operation timeout expired, and raises an appropriate
|
81
|
+
# error if yes.
|
82
|
+
#
|
83
|
+
# @raise [ Error::TimeoutError ]
|
84
|
+
def check_timeout!
|
85
|
+
return unless timeout_expired?
|
86
|
+
|
87
|
+
raise Error::TimeoutError, "Operation took more than #{timeout_sec} seconds"
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def calculate_deadline(opts = {}, session = nil)
|
93
|
+
check_no_override_inside_transaction!(opts, session)
|
94
|
+
return session&.with_transaction_deadline if session&.with_transaction_deadline
|
95
|
+
|
96
|
+
if (operation_timeout_ms = opts[:operation_timeout_ms])
|
97
|
+
calculate_deadline_from_timeout_ms(operation_timeout_ms)
|
98
|
+
elsif (inherited_timeout_ms = opts[:inherited_timeout_ms])
|
99
|
+
calculate_deadline_from_timeout_ms(inherited_timeout_ms)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def check_no_override_inside_transaction!(opts, session)
|
104
|
+
return unless opts[:operation_timeout_ms] && session&.with_transaction_deadline
|
105
|
+
|
106
|
+
raise ArgumentError, 'Cannot override timeout_ms inside with_transaction block'
|
107
|
+
end
|
108
|
+
|
109
|
+
def calculate_deadline_from_timeout_ms(operation_timeout_ms)
|
110
|
+
if operation_timeout_ms.positive?
|
111
|
+
Utils.monotonic_time + (operation_timeout_ms / 1_000.0)
|
112
|
+
elsif operation_timeout_ms.zero?
|
113
|
+
0
|
114
|
+
elsif operation_timeout_ms.negative?
|
115
|
+
raise ArgumentError, "timeout_ms must be a non-negative integer but #{operation_timeout_ms} given"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -31,7 +31,8 @@ module Mongo
|
|
31
31
|
db_name:,
|
32
32
|
connection_global_id:,
|
33
33
|
server_address:,
|
34
|
-
session
|
34
|
+
session:,
|
35
|
+
connection: nil
|
35
36
|
)
|
36
37
|
@cursor_id = cursor_id
|
37
38
|
@coll_name = coll_name
|
@@ -39,6 +40,7 @@ module Mongo
|
|
39
40
|
@connection_global_id = connection_global_id
|
40
41
|
@server_address = server_address
|
41
42
|
@session = session
|
43
|
+
@connection = connection
|
42
44
|
end
|
43
45
|
|
44
46
|
attr_reader :cursor_id,
|
@@ -46,7 +48,8 @@ module Mongo
|
|
46
48
|
:db_name,
|
47
49
|
:connection_global_id,
|
48
50
|
:server_address,
|
49
|
-
:session
|
51
|
+
:session,
|
52
|
+
:connection
|
50
53
|
|
51
54
|
def ==(other)
|
52
55
|
cursor_id == other.cursor_id &&
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mongo
|
4
|
+
class Cursor
|
5
|
+
# This module is used by cursor-implementing classes to indicate that
|
6
|
+
# the only cursors they generate are non-tailable, and iterable.
|
7
|
+
#
|
8
|
+
# @api private
|
9
|
+
module NonTailable
|
10
|
+
# These views are always non-tailable.
|
11
|
+
#
|
12
|
+
# @return [ nil ] indicating a non-tailable cursor.
|
13
|
+
def cursor_type
|
14
|
+
nil
|
15
|
+
end
|
16
|
+
|
17
|
+
# These views apply timeouts to each iteration of a cursor, as
|
18
|
+
# opposed to the entire lifetime of the cursor.
|
19
|
+
#
|
20
|
+
# @return [ :iterable ] indicating a cursor with a timeout mode of
|
21
|
+
# "iterable".
|
22
|
+
def timeout_mode
|
23
|
+
:iterable
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/mongo/cursor.rb
CHANGED
@@ -49,6 +49,9 @@ module Mongo
|
|
49
49
|
# @api private
|
50
50
|
attr_reader :resume_token
|
51
51
|
|
52
|
+
# @return [ Operation::Context ] context the context for this cursor
|
53
|
+
attr_reader :context
|
54
|
+
|
52
55
|
# Creates a +Cursor+ object.
|
53
56
|
#
|
54
57
|
# @example Instantiate the cursor.
|
@@ -59,6 +62,8 @@ module Mongo
|
|
59
62
|
# @param [ Server ] server The server this cursor is locked to.
|
60
63
|
# @param [ Hash ] options The cursor options.
|
61
64
|
#
|
65
|
+
# @option options [ Operation::Context ] :context The operation context
|
66
|
+
# for this cursor.
|
62
67
|
# @option options [ true, false ] :disable_retry Whether to disable
|
63
68
|
# retrying on error when sending getMore operations (deprecated, getMore
|
64
69
|
# operations are no longer retried)
|
@@ -80,15 +85,25 @@ module Mongo
|
|
80
85
|
if @cursor_id.nil?
|
81
86
|
raise ArgumentError, 'Cursor id must be present in the result'
|
82
87
|
end
|
83
|
-
@connection_global_id = result.connection_global_id
|
84
88
|
@options = options
|
85
89
|
@session = @options[:session]
|
90
|
+
@connection_global_id = result.connection_global_id
|
91
|
+
@context = @options[:context]&.with(connection_global_id: connection_global_id_for_context) || fresh_context
|
86
92
|
@explicitly_closed = false
|
87
93
|
@lock = Mutex.new
|
88
|
-
|
94
|
+
if server.load_balancer?
|
95
|
+
# We need the connection in the cursor only in load balanced topology;
|
96
|
+
# we do not need an additional reference to it otherwise.
|
97
|
+
@connection = @initial_result.connection
|
98
|
+
end
|
99
|
+
if closed?
|
100
|
+
check_in_connection
|
101
|
+
else
|
89
102
|
register
|
90
|
-
ObjectSpace.define_finalizer(
|
91
|
-
|
103
|
+
ObjectSpace.define_finalizer(
|
104
|
+
self,
|
105
|
+
self.class.finalize(kill_spec(@connection_global_id), cluster)
|
106
|
+
)
|
92
107
|
end
|
93
108
|
end
|
94
109
|
|
@@ -98,6 +113,9 @@ module Mongo
|
|
98
113
|
# @api private
|
99
114
|
attr_reader :initial_result
|
100
115
|
|
116
|
+
# @api private
|
117
|
+
attr_reader :connection
|
118
|
+
|
101
119
|
# Finalize the cursor for garbage collection. Schedules this cursor to be included
|
102
120
|
# in a killCursors operation executed by the Cluster's CursorReaper.
|
103
121
|
#
|
@@ -284,9 +302,11 @@ module Mongo
|
|
284
302
|
# the server.
|
285
303
|
#
|
286
304
|
# @return [ nil ] Always nil.
|
287
|
-
def close
|
305
|
+
def close(opts = {})
|
288
306
|
return if closed?
|
289
307
|
|
308
|
+
ctx = context ? context.refresh(timeout_ms: opts[:timeout_ms]) : fresh_context(opts)
|
309
|
+
|
290
310
|
unregister
|
291
311
|
read_with_one_retry do
|
292
312
|
spec = {
|
@@ -295,11 +315,11 @@ module Mongo
|
|
295
315
|
cursor_ids: [id],
|
296
316
|
}
|
297
317
|
op = Operation::KillCursors.new(spec)
|
298
|
-
execute_operation(op)
|
318
|
+
execute_operation(op, context: ctx)
|
299
319
|
end
|
300
320
|
|
301
321
|
nil
|
302
|
-
rescue Error::OperationFailure, Error::SocketError, Error::SocketTimeoutError, Error::ServerNotUsable
|
322
|
+
rescue Error::OperationFailure::Family, Error::SocketError, Error::SocketTimeoutError, Error::ServerNotUsable
|
303
323
|
# Errors are swallowed since there is noting can be done by handling them.
|
304
324
|
ensure
|
305
325
|
end_session
|
@@ -307,6 +327,7 @@ module Mongo
|
|
307
327
|
@lock.synchronize do
|
308
328
|
@explicitly_closed = true
|
309
329
|
end
|
330
|
+
check_in_connection
|
310
331
|
end
|
311
332
|
|
312
333
|
# Get the parsed collection name.
|
@@ -387,6 +408,7 @@ module Mongo
|
|
387
408
|
connection_global_id: connection_global_id,
|
388
409
|
server_address: server.address,
|
389
410
|
session: @session,
|
411
|
+
connection: @connection
|
390
412
|
)
|
391
413
|
end
|
392
414
|
|
@@ -434,15 +456,7 @@ module Mongo
|
|
434
456
|
# 3.2+ servers use batch_size, 3.0- servers use to_return.
|
435
457
|
# TODO should to_return be calculated in the operation layer?
|
436
458
|
batch_size: batch_size_for_get_more,
|
437
|
-
to_return: to_return
|
438
|
-
max_time_ms: if view.respond_to?(:max_await_time_ms) &&
|
439
|
-
view.max_await_time_ms &&
|
440
|
-
view.options[:await_data]
|
441
|
-
then
|
442
|
-
view.max_await_time_ms
|
443
|
-
else
|
444
|
-
nil
|
445
|
-
end,
|
459
|
+
to_return: to_return
|
446
460
|
}
|
447
461
|
if view.respond_to?(:options) && view.options.is_a?(Hash)
|
448
462
|
spec[:comment] = view.options[:comment] unless view.options[:comment].nil?
|
@@ -464,7 +478,10 @@ module Mongo
|
|
464
478
|
# the @cursor_id may be zero (all results fit in the first batch).
|
465
479
|
# Thus we need to check both @cursor_id and the cursor_id of the result
|
466
480
|
# prior to calling unregister here.
|
467
|
-
|
481
|
+
if !closed? && result.cursor_id == 0
|
482
|
+
unregister
|
483
|
+
check_in_connection
|
484
|
+
end
|
468
485
|
@cursor_id = set_cursor_id(result)
|
469
486
|
|
470
487
|
if result.respond_to?(:post_batch_resume_token)
|
@@ -495,13 +512,22 @@ module Mongo
|
|
495
512
|
cluster.unregister_cursor(@cursor_id)
|
496
513
|
end
|
497
514
|
|
498
|
-
def execute_operation(op)
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
515
|
+
def execute_operation(op, context: nil)
|
516
|
+
op_context = context || possibly_refreshed_context
|
517
|
+
if @connection.nil?
|
518
|
+
op.execute(@server, context: op_context)
|
519
|
+
else
|
520
|
+
op.execute_with_connection(@connection, context: op_context)
|
521
|
+
end
|
522
|
+
end
|
523
|
+
|
524
|
+
# Considers the timeout mode and will either return the cursor's
|
525
|
+
# context directly, or will return a new (refreshed) context.
|
526
|
+
#
|
527
|
+
# @return [ Operation::Context ] the (possibly-refreshed) context.
|
528
|
+
def possibly_refreshed_context
|
529
|
+
return context if view.timeout_mode == :cursor_lifetime
|
530
|
+
context.refresh(view: view)
|
505
531
|
end
|
506
532
|
|
507
533
|
# Sets @cursor_id from the operation result.
|
@@ -521,6 +547,42 @@ module Mongo
|
|
521
547
|
end
|
522
548
|
end
|
523
549
|
|
550
|
+
# Returns a newly instantiated operation context based on the
|
551
|
+
# default values from the view.
|
552
|
+
def fresh_context(opts = {})
|
553
|
+
Operation::Context.new(client: view.client,
|
554
|
+
session: @session,
|
555
|
+
connection_global_id: connection_global_id_for_context,
|
556
|
+
operation_timeouts: view.operation_timeouts(opts),
|
557
|
+
view: view)
|
558
|
+
end
|
559
|
+
|
560
|
+
# Because a context must not have a connection_global_id if the session
|
561
|
+
# is already pinned to one, this method checks to see whether or not there's
|
562
|
+
# pinned connection_global_id on the session and returns nil if so.
|
563
|
+
def connection_global_id_for_context
|
564
|
+
if @session&.pinned_connection_global_id
|
565
|
+
nil
|
566
|
+
else
|
567
|
+
@connection_global_id
|
568
|
+
end
|
569
|
+
end
|
570
|
+
|
571
|
+
# Returns the connection that was used to create the cursor back to the
|
572
|
+
# corresponding connection pool.
|
573
|
+
#
|
574
|
+
# In a load balanced topology cursors must use the same connection for the
|
575
|
+
# initial and all subsequent operations. Therefore, the connection is not
|
576
|
+
# checked into the pool after the initial operation is completed, but
|
577
|
+
# only when the cursor is drained.
|
578
|
+
def check_in_connection
|
579
|
+
# Connection nil means the connection has been already checked in.
|
580
|
+
return if @connection.nil?
|
581
|
+
return unless @connection.server.load_balancer?
|
582
|
+
|
583
|
+
@connection.connection_pool.check_in(@connection)
|
584
|
+
@connection = nil
|
585
|
+
end
|
524
586
|
end
|
525
587
|
end
|
526
588
|
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mongo
|
4
|
+
# A shared concern implementing settings and configuration for entities that
|
5
|
+
# "host" (or spawn) cursors.
|
6
|
+
#
|
7
|
+
# The class or module that includes this concern must implement:
|
8
|
+
# * timeout_ms -- this must return either the operation level timeout_ms
|
9
|
+
# (if set) or an inherited timeout_ms from a hierarchically higher
|
10
|
+
# level (if any).
|
11
|
+
module CursorHost
|
12
|
+
# Returns the cursor associated with this view, if any.
|
13
|
+
#
|
14
|
+
# @return [ nil | Cursor ] The cursor, if any.
|
15
|
+
#
|
16
|
+
# @api private
|
17
|
+
attr_reader :cursor
|
18
|
+
|
19
|
+
# @return [ :cursor_lifetime | :iteration ] The timeout mode to be
|
20
|
+
# used by this object.
|
21
|
+
attr_reader :timeout_mode
|
22
|
+
|
23
|
+
# Ensure the timeout mode is appropriate for other options that
|
24
|
+
# have been given.
|
25
|
+
#
|
26
|
+
# @param [ Hash ] options The options to inspect.
|
27
|
+
# @param [ Array<Symbol> ] forbid The list of options to forbid for this
|
28
|
+
# class.
|
29
|
+
#
|
30
|
+
# @raise [ ArgumentError ] if inconsistent or incompatible options are
|
31
|
+
# detected.
|
32
|
+
#
|
33
|
+
# @api private
|
34
|
+
# rubocop:disable Metrics
|
35
|
+
def validate_timeout_mode!(options, forbid: [])
|
36
|
+
forbid.each do |key|
|
37
|
+
raise ArgumentError, "#{key} is not allowed here" if options.key?(key)
|
38
|
+
end
|
39
|
+
|
40
|
+
cursor_type = options[:cursor_type]
|
41
|
+
timeout_mode = options[:timeout_mode]
|
42
|
+
|
43
|
+
if timeout_ms
|
44
|
+
# "Tailable cursors only support the ITERATION value for the
|
45
|
+
# timeoutMode option. This is the default value and drivers MUST
|
46
|
+
# error if the option is set to CURSOR_LIFETIME."
|
47
|
+
if cursor_type
|
48
|
+
timeout_mode ||= :iteration
|
49
|
+
if timeout_mode == :cursor_lifetime
|
50
|
+
raise ArgumentError, 'tailable cursors only support `timeout_mode: :iteration`'
|
51
|
+
end
|
52
|
+
|
53
|
+
# "Drivers MUST error if [the maxAwaitTimeMS] option is set,
|
54
|
+
# timeoutMS is set to a non-zero value, and maxAwaitTimeMS is
|
55
|
+
# greater than or equal to timeoutMS."
|
56
|
+
max_await_time_ms = options[:max_await_time_ms] || 0
|
57
|
+
if cursor_type == :tailable_await && max_await_time_ms >= timeout_ms
|
58
|
+
raise ArgumentError, ':max_await_time_ms must not be >= :timeout_ms'
|
59
|
+
end
|
60
|
+
else
|
61
|
+
# "For non-tailable cursors, the default value of timeoutMode
|
62
|
+
# is CURSOR_LIFETIME."
|
63
|
+
timeout_mode ||= :cursor_lifetime
|
64
|
+
end
|
65
|
+
elsif timeout_mode
|
66
|
+
# "Drivers MUST error if timeoutMode is set and timeoutMS is not."
|
67
|
+
raise ArgumentError, ':timeout_ms must be set if :timeout_mode is set'
|
68
|
+
end
|
69
|
+
|
70
|
+
if timeout_mode == :iteration && respond_to?(:write?) && write?
|
71
|
+
raise ArgumentError, 'timeout_mode=:iteration is not supported for aggregation pipelines with $out or $merge'
|
72
|
+
end
|
73
|
+
|
74
|
+
# set it as an instance variable, rather than updating the options,
|
75
|
+
# because if the cursor type changes (e.g. via #configure()), the new
|
76
|
+
# View instance must be able to select a different default timeout_mode
|
77
|
+
# if no timeout_mode was set initially.
|
78
|
+
@timeout_mode = timeout_mode
|
79
|
+
end
|
80
|
+
# rubocop:enable Metrics
|
81
|
+
end
|
82
|
+
end
|
data/lib/mongo/database/view.rb
CHANGED
@@ -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/nontailable'
|
19
|
+
|
18
20
|
module Mongo
|
19
21
|
class Database
|
20
22
|
|
@@ -25,6 +27,8 @@ module Mongo
|
|
25
27
|
extend Forwardable
|
26
28
|
include Enumerable
|
27
29
|
include Retryable
|
30
|
+
include Mongo::CursorHost
|
31
|
+
include Cursor::NonTailable
|
28
32
|
|
29
33
|
def_delegators :@database, :cluster, :read_preference, :client
|
30
34
|
# @api private
|
@@ -56,6 +60,10 @@ module Mongo
|
|
56
60
|
# to run the command when access control is enforced.
|
57
61
|
# @option options [ Object ] :comment A user-provided
|
58
62
|
# comment to attach to this command.
|
63
|
+
# @option options [ Integer ] :timeout_ms The operation timeout in milliseconds.
|
64
|
+
# Must be a non-negative integer. An explicit value of 0 means infinite.
|
65
|
+
# The default value is unset which means the value is inherited from
|
66
|
+
# the database or the client.
|
59
67
|
#
|
60
68
|
# See https://mongodb.com/docs/manual/reference/command/listCollections/
|
61
69
|
# for more information and usage.
|
@@ -66,9 +74,14 @@ module Mongo
|
|
66
74
|
# @since 2.0.0
|
67
75
|
def collection_names(options = {})
|
68
76
|
@batch_size = options[:batch_size]
|
69
|
-
session = client.
|
70
|
-
|
71
|
-
|
77
|
+
session = client.get_session(options)
|
78
|
+
context = Operation::Context.new(
|
79
|
+
client: client,
|
80
|
+
session: session,
|
81
|
+
operation_timeouts: operation_timeouts(options)
|
82
|
+
)
|
83
|
+
cursor = read_with_retry_cursor(session, ServerSelector.primary, self, context: context) do |server|
|
84
|
+
send_initial_query(server, session, context, options.merge(name_only: true))
|
72
85
|
end
|
73
86
|
cursor.map do |info|
|
74
87
|
if cursor.initial_result.connection_description.features.list_collections_enabled?
|
@@ -112,20 +125,33 @@ module Mongo
|
|
112
125
|
#
|
113
126
|
# @since 2.0.5
|
114
127
|
def list_collections(options = {})
|
115
|
-
session = client.
|
128
|
+
session = client.get_session(options)
|
116
129
|
collections_info(session, ServerSelector.primary, options)
|
117
130
|
end
|
118
131
|
|
119
132
|
# Create the new database view.
|
120
133
|
#
|
121
134
|
# @example Create the new database view.
|
122
|
-
# View
|
135
|
+
# Database::View.new(database)
|
123
136
|
#
|
124
137
|
# @param [ Database ] database The database.
|
138
|
+
# @param [ Hash ] options The options to configure the view with.
|
139
|
+
#
|
140
|
+
# @option options [ :cursor_lifetime | :iteration ] :timeout_mode How to interpret
|
141
|
+
# :timeout_ms (whether it applies to the lifetime of the cursor, or per
|
142
|
+
# iteration).
|
143
|
+
# @option options [ Integer ] :timeout_ms The operation timeout in milliseconds.
|
144
|
+
# Must be a non-negative integer. An explicit value of 0 means infinite.
|
145
|
+
# The default value is unset which means the value is inherited from
|
146
|
+
# the database or the client.
|
125
147
|
#
|
126
148
|
# @since 2.0.0
|
127
|
-
def initialize(database)
|
149
|
+
def initialize(database, options = {})
|
128
150
|
@database = database
|
151
|
+
@operation_timeout_ms = options.delete(:timeout_ms)
|
152
|
+
|
153
|
+
validate_timeout_mode!(options)
|
154
|
+
|
129
155
|
@batch_size = nil
|
130
156
|
@limit = nil
|
131
157
|
@collection = @database[Database::COMMAND]
|
@@ -134,6 +160,12 @@ module Mongo
|
|
134
160
|
# @api private
|
135
161
|
attr_reader :database
|
136
162
|
|
163
|
+
# @return [ Integer | nil | The timeout_ms value that was passed as an
|
164
|
+
# option to the view.
|
165
|
+
#
|
166
|
+
# @api private
|
167
|
+
attr_reader :operation_timeout_ms
|
168
|
+
|
137
169
|
# Execute an aggregation on the database view.
|
138
170
|
#
|
139
171
|
# @example Aggregate documents.
|
@@ -152,15 +184,41 @@ module Mongo
|
|
152
184
|
Collection::View::Aggregation.new(self, pipeline, options)
|
153
185
|
end
|
154
186
|
|
187
|
+
# The timeout_ms value to use for this operation; either specified as an
|
188
|
+
# option to the view, or inherited from the database.
|
189
|
+
#
|
190
|
+
# @return [ Integer | nil ] the timeout_ms for this operation
|
191
|
+
def timeout_ms
|
192
|
+
operation_timeout_ms || database.timeout_ms
|
193
|
+
end
|
194
|
+
|
195
|
+
# @return [ Hash ] timeout_ms value set on the operation level (if any).
|
196
|
+
#
|
197
|
+
# @api private
|
198
|
+
def operation_timeouts(opts = {})
|
199
|
+
{}.tap do |result|
|
200
|
+
if opts[:timeout_ms] || operation_timeout_ms
|
201
|
+
result[:operation_timeout_ms] = opts.delete(:timeout_ms) || operation_timeout_ms
|
202
|
+
else
|
203
|
+
result[:inherited_timeout_ms] = database.timeout_ms
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
155
208
|
private
|
156
209
|
|
157
210
|
def collections_info(session, server_selector, options = {}, &block)
|
158
211
|
description = nil
|
159
|
-
|
212
|
+
context = Operation::Context.new(
|
213
|
+
client: client,
|
214
|
+
session: session,
|
215
|
+
operation_timeouts: operation_timeouts(options)
|
216
|
+
)
|
217
|
+
cursor = read_with_retry_cursor(session, server_selector, self, context: context) do |server|
|
160
218
|
# TODO take description from the connection used to send the query
|
161
219
|
# once https://jira.mongodb.org/browse/RUBY-1601 is fixed.
|
162
220
|
description = server.description
|
163
|
-
send_initial_query(server, session, options)
|
221
|
+
send_initial_query(server, session, context, options)
|
164
222
|
end
|
165
223
|
# On 3.0+ servers, we get just the collection names.
|
166
224
|
# On 2.6 server, we get collection names prefixed with the database
|
@@ -224,17 +282,26 @@ module Mongo
|
|
224
282
|
# types (where possible).
|
225
283
|
#
|
226
284
|
# @return [ Operation::Result ] Result of the query.
|
227
|
-
def send_initial_query(server, session, options = {})
|
285
|
+
def send_initial_query(server, session, context, options = {})
|
228
286
|
opts = options.dup
|
229
287
|
execution_opts = {}
|
230
288
|
if opts.key?(:deserialize_as_bson)
|
231
289
|
execution_opts[:deserialize_as_bson] = opts.delete(:deserialize_as_bson)
|
232
290
|
end
|
233
|
-
|
234
|
-
server
|
235
|
-
|
236
|
-
|
237
|
-
|
291
|
+
if server.load_balancer?
|
292
|
+
connection = server.pool.check_out(context: context)
|
293
|
+
initial_query_op(session, opts).execute_with_connection(
|
294
|
+
connection,
|
295
|
+
context: context,
|
296
|
+
options: execution_opts
|
297
|
+
)
|
298
|
+
else
|
299
|
+
initial_query_op(session, opts).execute(
|
300
|
+
server,
|
301
|
+
context: context,
|
302
|
+
options: execution_opts
|
303
|
+
)
|
304
|
+
end
|
238
305
|
end
|
239
306
|
end
|
240
307
|
end
|