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
@@ -83,6 +83,12 @@ module Mongo
|
|
83
83
|
@options.freeze
|
84
84
|
@filename = @options[:filename]
|
85
85
|
@open = true
|
86
|
+
@timeout_holder = CsotTimeoutHolder.new(
|
87
|
+
operation_timeouts: {
|
88
|
+
operation_timeout_ms: options[:timeout_ms],
|
89
|
+
inherited_timeout_ms: fs.database.timeout_ms
|
90
|
+
}
|
91
|
+
)
|
86
92
|
end
|
87
93
|
|
88
94
|
# Write to the GridFS bucket from the source stream or a string.
|
@@ -107,7 +113,12 @@ module Mongo
|
|
107
113
|
end
|
108
114
|
chunks = File::Chunk.split(io, file_info, @n)
|
109
115
|
@n += chunks.size
|
110
|
-
|
116
|
+
unless chunks.empty?
|
117
|
+
chunks_collection.insert_many(
|
118
|
+
chunks,
|
119
|
+
timeout_ms: @timeout_holder.remaining_timeout_ms!
|
120
|
+
)
|
121
|
+
end
|
111
122
|
self
|
112
123
|
end
|
113
124
|
|
@@ -124,7 +135,10 @@ module Mongo
|
|
124
135
|
def close
|
125
136
|
ensure_open!
|
126
137
|
update_length
|
127
|
-
files_collection.insert_one(
|
138
|
+
files_collection.insert_one(
|
139
|
+
file_info,
|
140
|
+
@options.merge(timeout_ms: @timeout_holder.remaining_timeout_ms!)
|
141
|
+
)
|
128
142
|
@open = false
|
129
143
|
file_id
|
130
144
|
end
|
@@ -166,7 +180,10 @@ module Mongo
|
|
166
180
|
#
|
167
181
|
# @since 2.1.0
|
168
182
|
def abort
|
169
|
-
fs.chunks_collection.find(
|
183
|
+
fs.chunks_collection.find(
|
184
|
+
{ :files_id => file_id },
|
185
|
+
@options.merge(timeout_ms: @timeout_holder.remaining_timeout_ms!)
|
186
|
+
).delete_many
|
170
187
|
(@open = false) || true
|
171
188
|
end
|
172
189
|
|
@@ -200,7 +217,7 @@ module Mongo
|
|
200
217
|
end
|
201
218
|
|
202
219
|
def ensure_indexes!
|
203
|
-
fs.send(:ensure_indexes
|
220
|
+
fs.send(:ensure_indexes!, @timeout_holder)
|
204
221
|
end
|
205
222
|
|
206
223
|
def ensure_open!
|
data/lib/mongo/index/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
|
module Index
|
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
|
# @return [ Collection ] collection The indexes collection.
|
30
34
|
attr_reader :collection
|
@@ -33,6 +37,12 @@ module Mongo
|
|
33
37
|
# when sending the listIndexes command.
|
34
38
|
attr_reader :batch_size
|
35
39
|
|
40
|
+
# @return [ Integer | nil | The timeout_ms value that was passed as an
|
41
|
+
# option to the view.
|
42
|
+
#
|
43
|
+
# @api private
|
44
|
+
attr_reader :operation_timeout_ms
|
45
|
+
|
36
46
|
def_delegators :@collection, :cluster, :database, :read_preference, :write_concern, :client
|
37
47
|
def_delegators :cluster, :next_primary
|
38
48
|
|
@@ -90,7 +100,7 @@ module Mongo
|
|
90
100
|
# @since 2.0.0
|
91
101
|
def drop_one(name, options = {})
|
92
102
|
raise Error::MultiIndexDrop.new if name == Index::ALL
|
93
|
-
drop_by_name(name,
|
103
|
+
drop_by_name(name, options)
|
94
104
|
end
|
95
105
|
|
96
106
|
# Drop all indexes on the collection.
|
@@ -107,7 +117,7 @@ module Mongo
|
|
107
117
|
#
|
108
118
|
# @since 2.0.0
|
109
119
|
def drop_all(options = {})
|
110
|
-
drop_by_name(Index::ALL,
|
120
|
+
drop_by_name(Index::ALL, options)
|
111
121
|
end
|
112
122
|
|
113
123
|
# Creates an index on the collection.
|
@@ -161,7 +171,7 @@ module Mongo
|
|
161
171
|
if session = @options[:session]
|
162
172
|
create_options[:session] = session
|
163
173
|
end
|
164
|
-
%i(commit_quorum session comment).each do |key|
|
174
|
+
%i(commit_quorum session comment timeout_ms max_time_ms).each do |key|
|
165
175
|
if value = options.delete(key)
|
166
176
|
create_options[key] = value
|
167
177
|
end
|
@@ -210,7 +220,7 @@ module Mongo
|
|
210
220
|
options = models.pop
|
211
221
|
end
|
212
222
|
|
213
|
-
client.
|
223
|
+
client.with_session(@options.merge(options)) do |session|
|
214
224
|
server = next_primary(nil, session)
|
215
225
|
|
216
226
|
indexes = normalize_models(models, server)
|
@@ -229,8 +239,12 @@ module Mongo
|
|
229
239
|
write_concern: write_concern,
|
230
240
|
comment: options[:comment],
|
231
241
|
}
|
232
|
-
|
233
|
-
|
242
|
+
context = Operation::Context.new(
|
243
|
+
client: client,
|
244
|
+
session: session,
|
245
|
+
operation_timeouts: operation_timeouts(options)
|
246
|
+
)
|
247
|
+
Operation::CreateIndex.new(spec).execute(server, context: context)
|
234
248
|
end
|
235
249
|
end
|
236
250
|
|
@@ -263,9 +277,15 @@ module Mongo
|
|
263
277
|
#
|
264
278
|
# @since 2.0.0
|
265
279
|
def each(&block)
|
266
|
-
session = client.
|
267
|
-
|
268
|
-
|
280
|
+
session = client.get_session(@options)
|
281
|
+
context = Operation::Context.new(
|
282
|
+
client: client,
|
283
|
+
session: session,
|
284
|
+
operation_timeouts: operation_timeouts(@options)
|
285
|
+
)
|
286
|
+
|
287
|
+
cursor = read_with_retry_cursor(session, ServerSelector.primary, self, context: context) do |server|
|
288
|
+
send_initial_query(server, session, context)
|
269
289
|
end
|
270
290
|
if block_given?
|
271
291
|
cursor.each do |doc|
|
@@ -283,22 +303,53 @@ module Mongo
|
|
283
303
|
#
|
284
304
|
# @param [ Collection ] collection The collection.
|
285
305
|
# @param [ Hash ] options Options for getting a list of indexes.
|
286
|
-
# Only relevant for when the listIndexes command is used with server
|
287
|
-
# versions >=2.8.
|
288
306
|
#
|
289
307
|
# @option options [ Integer ] :batch_size The batch size for results
|
290
308
|
# returned from the listIndexes command.
|
309
|
+
# @option options [ :cursor_lifetime | :iteration ] :timeout_mode How to interpret
|
310
|
+
# :timeout_ms (whether it applies to the lifetime of the cursor, or per
|
311
|
+
# iteration).
|
312
|
+
# @option options [ Integer ] :timeout_ms The operation timeout in milliseconds.
|
313
|
+
# Must be a non-negative integer. An explicit value of 0 means infinite.
|
314
|
+
# The default value is unset which means the value is inherited from
|
315
|
+
# the collection or the database or the client.
|
291
316
|
#
|
292
317
|
# @since 2.0.0
|
293
318
|
def initialize(collection, options = {})
|
294
319
|
@collection = collection
|
320
|
+
@operation_timeout_ms = options.delete(:timeout_ms)
|
321
|
+
|
322
|
+
validate_timeout_mode!(options)
|
323
|
+
|
295
324
|
@batch_size = options[:batch_size]
|
296
325
|
@options = options
|
297
326
|
end
|
298
327
|
|
328
|
+
# The timeout_ms value to use for this operation; either specified as an
|
329
|
+
# option to the view, or inherited from the collection.
|
330
|
+
#
|
331
|
+
# @return [ Integer | nil ] the timeout_ms for this operation
|
332
|
+
def timeout_ms
|
333
|
+
operation_timeout_ms || collection.timeout_ms
|
334
|
+
end
|
335
|
+
|
336
|
+
# @return [ Hash ] timeout_ms value set on the operation level (if any),
|
337
|
+
# and/or timeout_ms that is set on collection/database/client level (if any).
|
338
|
+
#
|
339
|
+
# @api private
|
340
|
+
def operation_timeouts(opts = {})
|
341
|
+
{}.tap do |result|
|
342
|
+
if opts[:timeout_ms] || operation_timeout_ms
|
343
|
+
result[:operation_timeout_ms] = opts.delete(:timeout_ms) || operation_timeout_ms
|
344
|
+
else
|
345
|
+
result[:inherited_timeout_ms] = collection.timeout_ms
|
346
|
+
end
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
299
350
|
private
|
300
351
|
|
301
|
-
def drop_by_name(name,
|
352
|
+
def drop_by_name(name, opts = {})
|
302
353
|
client.send(:with_session, @options) do |session|
|
303
354
|
spec = {
|
304
355
|
db_name: database.name,
|
@@ -307,9 +358,14 @@ module Mongo
|
|
307
358
|
session: session,
|
308
359
|
write_concern: write_concern,
|
309
360
|
}
|
310
|
-
spec[:comment] = comment unless comment.nil?
|
361
|
+
spec[:comment] = opts[:comment] unless opts[:comment].nil?
|
311
362
|
server = next_primary(nil, session)
|
312
|
-
|
363
|
+
context = Operation::Context.new(
|
364
|
+
client: client,
|
365
|
+
session: session,
|
366
|
+
operation_timeouts: operation_timeouts(opts)
|
367
|
+
)
|
368
|
+
Operation::DropIndex.new(spec).execute(server, context: context)
|
313
369
|
end
|
314
370
|
end
|
315
371
|
|
@@ -347,8 +403,13 @@ module Mongo
|
|
347
403
|
end
|
348
404
|
end
|
349
405
|
|
350
|
-
def send_initial_query(server, session)
|
351
|
-
|
406
|
+
def send_initial_query(server, session, context)
|
407
|
+
if server.load_balancer?
|
408
|
+
connection = server.pool.check_out(context: context)
|
409
|
+
initial_query_op(session).execute_with_connection(connection, context: context)
|
410
|
+
else
|
411
|
+
initial_query_op(session).execute(server, context: context)
|
412
|
+
end
|
352
413
|
end
|
353
414
|
end
|
354
415
|
end
|
@@ -34,8 +34,15 @@ module Mongo
|
|
34
34
|
# operations.
|
35
35
|
#
|
36
36
|
# @api private
|
37
|
-
class Context
|
38
|
-
def initialize(
|
37
|
+
class Context < CsotTimeoutHolder
|
38
|
+
def initialize(
|
39
|
+
client: nil,
|
40
|
+
session: nil,
|
41
|
+
connection_global_id: nil,
|
42
|
+
operation_timeouts: {},
|
43
|
+
view: nil,
|
44
|
+
options: nil
|
45
|
+
)
|
39
46
|
if options
|
40
47
|
if client
|
41
48
|
raise ArgumentError, 'Client and options cannot both be specified'
|
@@ -52,14 +59,33 @@ module Mongo
|
|
52
59
|
|
53
60
|
@client = client
|
54
61
|
@session = session
|
62
|
+
@view = view
|
55
63
|
@connection_global_id = connection_global_id
|
56
64
|
@options = options
|
65
|
+
super(session: session, operation_timeouts: operation_timeouts)
|
57
66
|
end
|
58
67
|
|
59
68
|
attr_reader :client
|
60
69
|
attr_reader :session
|
70
|
+
attr_reader :view
|
61
71
|
attr_reader :options
|
62
72
|
|
73
|
+
# Returns a new Operation::Context with the deadline refreshed
|
74
|
+
# and relative to the current moment.
|
75
|
+
#
|
76
|
+
# @return [ Operation::Context ] the refreshed context
|
77
|
+
def refresh(connection_global_id: @connection_global_id, timeout_ms: nil, view: nil)
|
78
|
+
operation_timeouts = @operation_timeouts
|
79
|
+
operation_timeouts = operation_timeouts.merge(operation_timeout_ms: timeout_ms) if timeout_ms
|
80
|
+
|
81
|
+
self.class.new(client: client,
|
82
|
+
session: session,
|
83
|
+
connection_global_id: connection_global_id,
|
84
|
+
operation_timeouts: operation_timeouts,
|
85
|
+
view: view || self.view,
|
86
|
+
options: options)
|
87
|
+
end
|
88
|
+
|
63
89
|
def connection_global_id
|
64
90
|
@connection_global_id || session&.pinned_connection_global_id
|
65
91
|
end
|
@@ -122,10 +148,18 @@ module Mongo
|
|
122
148
|
client&.encrypter&.encrypt? || false
|
123
149
|
end
|
124
150
|
|
151
|
+
def encrypt(db_name, cmd)
|
152
|
+
encrypter.encrypt(db_name, cmd, self)
|
153
|
+
end
|
154
|
+
|
125
155
|
def decrypt?
|
126
156
|
!!client&.encrypter
|
127
157
|
end
|
128
158
|
|
159
|
+
def decrypt(cmd)
|
160
|
+
encrypter.decrypt(cmd, self)
|
161
|
+
end
|
162
|
+
|
129
163
|
def encrypter
|
130
164
|
if client&.encrypter
|
131
165
|
client.encrypter
|
@@ -133,6 +167,10 @@ module Mongo
|
|
133
167
|
raise Error::InternalDriverError, 'Encrypter should only be accessed when encryption is to be performed'
|
134
168
|
end
|
135
169
|
end
|
170
|
+
|
171
|
+
def inspect
|
172
|
+
"#<#{self.class} connection_global_id=#{connection_global_id.inspect} deadline=#{deadline.inspect} options=#{options.inspect} operation_timeouts=#{operation_timeouts.inspect}>"
|
173
|
+
end
|
136
174
|
end
|
137
175
|
end
|
138
176
|
end
|
@@ -14,11 +14,11 @@ module Mongo
|
|
14
14
|
# Returns the command to send to the database, describing the
|
15
15
|
# desired createSearchIndexes operation.
|
16
16
|
#
|
17
|
-
# @param [
|
17
|
+
# @param [ Connection ] _connection the connection that will receive the
|
18
18
|
# command
|
19
19
|
#
|
20
20
|
# @return [ Hash ] the selector
|
21
|
-
def selector(
|
21
|
+
def selector(_connection)
|
22
22
|
{
|
23
23
|
createSearchIndexes: coll_name,
|
24
24
|
:$db => db_name,
|
@@ -49,7 +49,8 @@ module Mongo
|
|
49
49
|
|
50
50
|
def message(connection)
|
51
51
|
section = Protocol::Msg::Section1.new(IDENTIFIER, send(IDENTIFIER))
|
52
|
-
|
52
|
+
cmd = apply_relevant_timeouts_to(command(connection), connection)
|
53
|
+
Protocol::Msg.new(flags, {}, cmd, section)
|
53
54
|
end
|
54
55
|
end
|
55
56
|
end
|
@@ -14,11 +14,11 @@ module Mongo
|
|
14
14
|
# Returns the command to send to the database, describing the
|
15
15
|
# desired dropSearchIndex operation.
|
16
16
|
#
|
17
|
-
# @param [
|
17
|
+
# @param [ Connection ] _connection the connection that will receive the
|
18
18
|
# command
|
19
19
|
#
|
20
20
|
# @return [ Hash ] the selector
|
21
|
-
def selector(
|
21
|
+
def selector(_connection)
|
22
22
|
{
|
23
23
|
dropSearchIndex: coll_name,
|
24
24
|
:$db => db_name,
|
@@ -31,6 +31,51 @@ module Mongo
|
|
31
31
|
|
32
32
|
private
|
33
33
|
|
34
|
+
# Applies the relevant CSOT timeouts for a find command.
|
35
|
+
# Considers the cursor type and timeout mode and will add (or omit) a
|
36
|
+
# maxTimeMS field accordingly.
|
37
|
+
def apply_relevant_timeouts_to(spec, connection)
|
38
|
+
with_max_time(connection) do |max_time_sec|
|
39
|
+
timeout_ms = max_time_sec ? (max_time_sec * 1_000).to_i : nil
|
40
|
+
apply_find_timeouts_to(spec, timeout_ms) unless connection.description.mongocryptd?
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def apply_find_timeouts_to(spec, timeout_ms)
|
45
|
+
view = context&.view
|
46
|
+
return spec unless view
|
47
|
+
|
48
|
+
case view.cursor_type
|
49
|
+
when nil # non-tailable
|
50
|
+
if view.timeout_mode == :cursor_lifetime
|
51
|
+
spec[:maxTimeMS] = timeout_ms || view.options[:max_time_ms]
|
52
|
+
else # timeout_mode == :iterable
|
53
|
+
# drivers MUST honor the timeoutMS option for the initial command
|
54
|
+
# but MUST NOT append a maxTimeMS field to the command sent to the
|
55
|
+
# server
|
56
|
+
if !timeout_ms && view.options[:max_time_ms]
|
57
|
+
spec[:maxTimeMS] = view.options[:max_time_ms]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
when :tailable
|
62
|
+
# If timeoutMS is set, drivers...MUST NOT append a maxTimeMS field to any commands.
|
63
|
+
if !timeout_ms && view.options[:max_time_ms]
|
64
|
+
spec[:maxTimeMS] = view.options[:max_time_ms]
|
65
|
+
end
|
66
|
+
|
67
|
+
when :tailable_await
|
68
|
+
# The server supports the maxTimeMS option for the original command.
|
69
|
+
if timeout_ms || view.options[:max_time_ms]
|
70
|
+
spec[:maxTimeMS] = timeout_ms || view.options[:max_time_ms]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
spec.tap do |spc|
|
75
|
+
spc.delete(:maxTimeMS) if spc[:maxTimeMS].nil?
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
34
79
|
def selector(connection)
|
35
80
|
# The mappings are BSON::Documents and as such store keys as
|
36
81
|
# strings, the spec here has symbol keys.
|
@@ -28,6 +28,39 @@ module Mongo
|
|
28
28
|
include ExecutableTransactionLabel
|
29
29
|
include PolymorphicResult
|
30
30
|
include CommandBuilder
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
# Applies the relevant CSOT timeouts for a getMore command.
|
35
|
+
# Considers the cursor type and timeout mode and will add (or omit) a
|
36
|
+
# maxTimeMS field accordingly.
|
37
|
+
def apply_relevant_timeouts_to(spec, connection)
|
38
|
+
with_max_time(connection) do |max_time_sec|
|
39
|
+
timeout_ms = max_time_sec ? (max_time_sec * 1_000).to_i : nil
|
40
|
+
apply_get_more_timeouts_to(spec, timeout_ms)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def apply_get_more_timeouts_to(spec, timeout_ms)
|
45
|
+
view = context&.view
|
46
|
+
return spec unless view
|
47
|
+
|
48
|
+
if view.cursor_type == :tailable_await
|
49
|
+
# If timeoutMS is set, drivers MUST apply it to the original operation.
|
50
|
+
# Drivers MUST also apply the original timeoutMS value to each next
|
51
|
+
# call on the resulting cursor but MUST NOT use it to derive a
|
52
|
+
# maxTimeMS value for getMore commands. Helpers for operations that
|
53
|
+
# create tailable awaitData cursors MUST also support the
|
54
|
+
# maxAwaitTimeMS option. Drivers MUST error if this option is set,
|
55
|
+
# timeoutMS is set to a non-zero value, and maxAwaitTimeMS is greater
|
56
|
+
# than or equal to timeoutMS. If this option is set, drivers MUST use
|
57
|
+
# it as the maxTimeMS field on getMore commands.
|
58
|
+
max_await_time_ms = view.respond_to?(:max_await_time_ms) ? view.max_await_time_ms : nil
|
59
|
+
spec[:maxTimeMS] = max_await_time_ms if max_await_time_ms
|
60
|
+
end
|
61
|
+
|
62
|
+
spec
|
63
|
+
end
|
31
64
|
end
|
32
65
|
end
|
33
66
|
end
|
@@ -35,7 +35,7 @@ module Mongo
|
|
35
35
|
|
36
36
|
def get_result(connection, context, options = {})
|
37
37
|
# This is a Mongo::Operation::Insert::Result
|
38
|
-
Result.new(*dispatch_message(connection, context), @ids)
|
38
|
+
Result.new(*dispatch_message(connection, context), @ids, context: context)
|
39
39
|
end
|
40
40
|
|
41
41
|
def selector(connection)
|
@@ -49,7 +49,8 @@ module Mongo
|
|
49
49
|
|
50
50
|
def message(connection)
|
51
51
|
section = Protocol::Msg::Section1.new(IDENTIFIER, send(IDENTIFIER))
|
52
|
-
|
52
|
+
cmd = apply_relevant_timeouts_to(command(connection), connection)
|
53
|
+
Protocol::Msg.new(flags, {}, cmd, section)
|
53
54
|
end
|
54
55
|
end
|
55
56
|
end
|
@@ -47,11 +47,13 @@ module Mongo
|
|
47
47
|
# Global id of the connection on which the operation that
|
48
48
|
# this result is for was performed.
|
49
49
|
# @param [ Array<Object> ] ids The ids of the inserted documents.
|
50
|
+
# @param [ Operation::Context | nil ] context the operation context that
|
51
|
+
# was active when this result was produced.
|
50
52
|
#
|
51
53
|
# @since 2.0.0
|
52
54
|
# @api private
|
53
|
-
def initialize(replies, connection_description, connection_global_id, ids)
|
54
|
-
super(replies, connection_description, connection_global_id)
|
55
|
+
def initialize(replies, connection_description, connection_global_id, ids, context: nil)
|
56
|
+
super(replies, connection_description, connection_global_id, context: context)
|
55
57
|
@inserted_ids = ids
|
56
58
|
end
|
57
59
|
|
@@ -108,7 +108,7 @@ module Mongo
|
|
108
108
|
# @example Validate the result.
|
109
109
|
# result.validate!
|
110
110
|
#
|
111
|
-
# @raise [ Error::OperationFailure ] If an error is in the result.
|
111
|
+
# @raise [ Error::OperationFailure::Family ] If an error is in the result.
|
112
112
|
#
|
113
113
|
# @return [ Result ] The result if verification passed.
|
114
114
|
#
|
@@ -22,11 +22,13 @@ module Mongo
|
|
22
22
|
include Specifiable
|
23
23
|
include Executable
|
24
24
|
include SessionsSupported
|
25
|
+
include Timed
|
25
26
|
|
26
27
|
private
|
27
28
|
|
28
29
|
def message(connection)
|
29
|
-
|
30
|
+
cmd = apply_relevant_timeouts_to(command(connection), connection)
|
31
|
+
Protocol::Msg.new(flags, options(connection), cmd)
|
30
32
|
end
|
31
33
|
end
|
32
34
|
end
|
@@ -100,9 +100,13 @@ module Mongo
|
|
100
100
|
# @param [ Integer ] connection_global_id
|
101
101
|
# Global id of the connection on which the operation that
|
102
102
|
# this result is for was performed.
|
103
|
+
# @param [ Operation::Context | nil ] context the context that was active
|
104
|
+
# when this result was produced.
|
103
105
|
#
|
104
106
|
# @api private
|
105
|
-
def initialize(replies, connection_description = nil, connection_global_id = nil)
|
107
|
+
def initialize(replies, connection_description = nil, connection_global_id = nil, context: nil, connection: nil)
|
108
|
+
@context = context
|
109
|
+
|
106
110
|
if replies
|
107
111
|
if replies.is_a?(Array)
|
108
112
|
if replies.length != 1
|
@@ -118,6 +122,7 @@ module Mongo
|
|
118
122
|
@replies = [ reply ]
|
119
123
|
@connection_description = connection_description
|
120
124
|
@connection_global_id = connection_global_id
|
125
|
+
@connection = connection
|
121
126
|
end
|
122
127
|
end
|
123
128
|
|
@@ -138,6 +143,14 @@ module Mongo
|
|
138
143
|
# @api private
|
139
144
|
attr_reader :connection_global_id
|
140
145
|
|
146
|
+
# @return [ Operation::Context | nil ] the operation context (if any)
|
147
|
+
# that was active when this result was produced.
|
148
|
+
#
|
149
|
+
# @api private
|
150
|
+
attr_reader :context
|
151
|
+
|
152
|
+
attr_reader :connection
|
153
|
+
|
141
154
|
# @api private
|
142
155
|
def_delegators :parser,
|
143
156
|
:not_master?, :node_recovering?, :node_shutting_down?
|
@@ -320,7 +333,7 @@ module Mongo
|
|
320
333
|
# @example Validate the result.
|
321
334
|
# result.validate!
|
322
335
|
#
|
323
|
-
# @raise [ Error::OperationFailure ] If an error is in the result.
|
336
|
+
# @raise [ Error::OperationFailure::Family ] If an error is in the result.
|
324
337
|
#
|
325
338
|
# @return [ Result ] The result if verification passed.
|
326
339
|
#
|
@@ -330,16 +343,16 @@ module Mongo
|
|
330
343
|
!successful? ? raise_operation_failure : self
|
331
344
|
end
|
332
345
|
|
333
|
-
# The exception instance (of
|
346
|
+
# The exception instance (of Error::OperationFailure::Family)
|
334
347
|
# that would be raised during processing of this result.
|
335
348
|
#
|
336
349
|
# This method should only be called when result is not successful.
|
337
350
|
#
|
338
|
-
# @return [ Error::OperationFailure ] The exception.
|
351
|
+
# @return [ Error::OperationFailure::Family ] The exception.
|
339
352
|
#
|
340
353
|
# @api private
|
341
354
|
def error
|
342
|
-
@error ||=
|
355
|
+
@error ||= operation_failure_class.new(
|
343
356
|
parser.message,
|
344
357
|
self,
|
345
358
|
code: parser.code,
|
@@ -453,6 +466,14 @@ module Mongo
|
|
453
466
|
|
454
467
|
private
|
455
468
|
|
469
|
+
def operation_failure_class
|
470
|
+
if context&.csot? && parser.code == 50
|
471
|
+
Error::ServerTimeoutError
|
472
|
+
else
|
473
|
+
Error::OperationFailure
|
474
|
+
end
|
475
|
+
end
|
476
|
+
|
456
477
|
def aggregate_returned_count
|
457
478
|
replies.reduce(0) do |n, reply|
|
458
479
|
n += reply.number_returned
|
@@ -28,7 +28,18 @@ module Mongo
|
|
28
28
|
|
29
29
|
include ResponseHandling
|
30
30
|
|
31
|
+
# @return [ Operation::Context | nil ] the operation context used to
|
32
|
+
# execute this operation.
|
33
|
+
attr_accessor :context
|
34
|
+
|
31
35
|
def do_execute(connection, context, options = {})
|
36
|
+
# Save the context on the instance, to avoid having to pass it as a
|
37
|
+
# parameter to every single method. There are many legacy methods that
|
38
|
+
# still accept it as a parameter, which are left as-is for now to
|
39
|
+
# minimize the impact of this change. Moving forward, it may be
|
40
|
+
# reasonable to refactor things so this saved reference is used instead.
|
41
|
+
@context = context
|
42
|
+
|
32
43
|
session&.materialize_if_needed
|
33
44
|
unpin_maybe(session, connection) do
|
34
45
|
add_error_labels(connection, context) do
|
@@ -93,7 +104,7 @@ module Mongo
|
|
93
104
|
end
|
94
105
|
|
95
106
|
def get_result(connection, context, options = {})
|
96
|
-
result_class.new(*dispatch_message(connection, context, options))
|
107
|
+
result_class.new(*dispatch_message(connection, context, options), context: context, connection: connection)
|
97
108
|
end
|
98
109
|
|
99
110
|
# Returns a Protocol::Message or nil as reply.
|
@@ -32,7 +32,10 @@ module Mongo
|
|
32
32
|
#
|
33
33
|
# @return [ Mongo::Operation::Result ] The operation result.
|
34
34
|
def execute(server, context:, options: {})
|
35
|
-
server.with_connection(
|
35
|
+
server.with_connection(
|
36
|
+
connection_global_id: context.connection_global_id,
|
37
|
+
context: context
|
38
|
+
) do |connection|
|
36
39
|
execute_with_connection(connection, context: context, options: options)
|
37
40
|
end
|
38
41
|
end
|