mongo 2.25.0 → 2.26.1
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/lib/mongo/bulk_write/combineable.rb +0 -7
- data/lib/mongo/bulk_write/validatable.rb +0 -4
- data/lib/mongo/bulk_write.rb +0 -34
- data/lib/mongo/client.rb +35 -5
- data/lib/mongo/client_encryption.rb +36 -11
- data/lib/mongo/cluster.rb +1 -2
- data/lib/mongo/collection/queryable_encryption.rb +7 -6
- data/lib/mongo/collection/view/aggregation.rb +9 -9
- data/lib/mongo/collection/view/change_stream.rb +1 -5
- data/lib/mongo/collection/view/iterable.rb +2 -9
- data/lib/mongo/collection/view/map_reduce.rb +5 -4
- data/lib/mongo/collection/view/readable.rb +3 -3
- data/lib/mongo/collection/view/writable.rb +0 -35
- data/lib/mongo/crypt/auto_encrypter.rb +5 -1
- data/lib/mongo/crypt/binding.rb +66 -1
- data/lib/mongo/crypt/explicit_encrypter.rb +27 -12
- data/lib/mongo/crypt/explicit_encryption_context.rb +51 -12
- data/lib/mongo/crypt/handle.rb +18 -0
- data/lib/mongo/cursor.rb +13 -0
- data/lib/mongo/database/view.rb +7 -6
- data/lib/mongo/database.rb +7 -10
- data/lib/mongo/error/unsupported_option.rb +0 -40
- data/lib/mongo/grid/fs_bucket.rb +2 -2
- data/lib/mongo/grid/stream/read.rb +2 -2
- data/lib/mongo/grid/stream/write.rb +1 -1
- data/lib/mongo/index/view.rb +3 -2
- data/lib/mongo/monitoring/event/secure.rb +6 -1
- data/lib/mongo/operation/map_reduce/result.rb +6 -2
- data/lib/mongo/operation/result.rb +9 -0
- data/lib/mongo/operation/shared/executable.rb +1 -6
- data/lib/mongo/operation/shared/result/aggregatable.rb +3 -3
- data/lib/mongo/protocol/message.rb +0 -4
- data/lib/mongo/protocol/msg.rb +1 -12
- data/lib/mongo/protocol/serializers.rb +1 -9
- data/lib/mongo/retryable/backpressure.rb +17 -2
- data/lib/mongo/retryable/read_worker.rb +1 -1
- data/lib/mongo/retryable/retry_policy.rb +2 -2
- data/lib/mongo/retryable/write_worker.rb +2 -2
- data/lib/mongo/retryable.rb +1 -1
- data/lib/mongo/server/app_metadata.rb +1 -2
- data/lib/mongo/server/connection.rb +7 -0
- data/lib/mongo/server/connection_pool.rb +60 -9
- data/lib/mongo/server/description/features.rb +2 -3
- data/lib/mongo/server/description.rb +0 -1
- data/lib/mongo/server/pending_connection.rb +0 -5
- data/lib/mongo/server.rb +1 -2
- data/lib/mongo/session.rb +10 -3
- data/lib/mongo/tracing/open_telemetry/command_tracer.rb +141 -102
- data/lib/mongo/tracing/open_telemetry/operation_tracer.rb +52 -17
- data/lib/mongo/tracing/open_telemetry/tracer.rb +10 -1
- data/lib/mongo/uri/options_mapper.rb +15 -4
- data/lib/mongo/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 39d9792c95b149dbbcb1b065df222c345eea9c84912e03de9a8994d7aea32ab8
|
|
4
|
+
data.tar.gz: b491401e88ffde8324e802267b35f75f6f92997f5746b3634612e1a9d63f11e8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: aad7e612834dd20849a707f6fde3d5a8101765af93df37eee119ad0418dd518b738ec8834689f0aeac267ac117aab2f89f84362f0c588f8714b96c1c87c286ef
|
|
7
|
+
data.tar.gz: 6a1c05b23598ac63e37267393de256bd0f2d250f14e881e2fda7a436a2ee2775d60e61d076c4fbaaa77230e7135f89095c55a737edca13a3434f048fdf8aa5db
|
|
@@ -39,7 +39,6 @@ module Mongo
|
|
|
39
39
|
@requests = requests
|
|
40
40
|
@has_collation = false
|
|
41
41
|
@has_array_filters = false
|
|
42
|
-
@has_hint = false
|
|
43
42
|
end
|
|
44
43
|
|
|
45
44
|
# @return [ Boolean ] Whether one or more operation specifies the collation
|
|
@@ -54,12 +53,6 @@ module Mongo
|
|
|
54
53
|
@has_array_filters
|
|
55
54
|
end
|
|
56
55
|
|
|
57
|
-
# @return [ Boolean ] Whether one or more operation specifies the
|
|
58
|
-
# hint option.
|
|
59
|
-
def has_hint?
|
|
60
|
-
@has_hint
|
|
61
|
-
end
|
|
62
|
-
|
|
63
56
|
private
|
|
64
57
|
|
|
65
58
|
def combine_requests(ops)
|
|
@@ -43,10 +43,6 @@ module Mongo
|
|
|
43
43
|
@has_collation = true if document.respond_to?(:keys) && (document[:collation] || document[Operation::COLLATION])
|
|
44
44
|
|
|
45
45
|
@has_array_filters = true if document.respond_to?(:keys) && document[:array_filters]
|
|
46
|
-
|
|
47
|
-
return unless document.respond_to?(:keys) && document[:hint]
|
|
48
|
-
|
|
49
|
-
@has_hint = true
|
|
50
46
|
end
|
|
51
47
|
|
|
52
48
|
private
|
data/lib/mongo/bulk_write.rb
CHANGED
|
@@ -236,8 +236,6 @@ module Mongo
|
|
|
236
236
|
end
|
|
237
237
|
|
|
238
238
|
def execute_operation(name, values, connection, context, operation_id, result_combiner, session, txn_num = nil)
|
|
239
|
-
validate_hint!(connection)
|
|
240
|
-
|
|
241
239
|
unpin_maybe(session, connection) do
|
|
242
240
|
if values.size > connection.description.max_write_batch_size
|
|
243
241
|
split_execute(name, values, connection, context, operation_id, result_combiner, session, txn_num)
|
|
@@ -310,38 +308,6 @@ module Mongo
|
|
|
310
308
|
Operation::Update.new(spec).bulk_execute(connection, context: context)
|
|
311
309
|
end
|
|
312
310
|
|
|
313
|
-
def validate_hint!(connection)
|
|
314
|
-
return unless op_combiner.has_hint?
|
|
315
|
-
return unless !can_hint?(connection) && write_concern && !write_concern.acknowledged?
|
|
316
|
-
|
|
317
|
-
raise Error::UnsupportedOption.hint_error(unacknowledged_write: true)
|
|
318
|
-
end
|
|
319
|
-
|
|
320
|
-
# Loop through the requests and check if each operation is allowed to send
|
|
321
|
-
# a hint for each operation on the given server version.
|
|
322
|
-
#
|
|
323
|
-
# For the following operations, the client can send a hint for all supported
|
|
324
|
-
# server versions, and for the rest, the client can only send it for 4.4+:
|
|
325
|
-
# - updateOne
|
|
326
|
-
# - updateMany
|
|
327
|
-
# - replaceOne
|
|
328
|
-
#
|
|
329
|
-
# @param [ Connection ] connection The connection object.
|
|
330
|
-
#
|
|
331
|
-
# @return [ true | false ] Whether the request is able to send hints for
|
|
332
|
-
# the current server version.
|
|
333
|
-
def can_hint?(connection)
|
|
334
|
-
gte_4_4 = connection.server.description.server_version_gte?('4.4')
|
|
335
|
-
op_combiner.requests.all? do |req|
|
|
336
|
-
op = req.keys.first
|
|
337
|
-
if req[op].keys.include?(:hint)
|
|
338
|
-
%i[update_one update_many replace_one].include?(op) || gte_4_4
|
|
339
|
-
else
|
|
340
|
-
true
|
|
341
|
-
end
|
|
342
|
-
end
|
|
343
|
-
end
|
|
344
|
-
|
|
345
311
|
# Perform the request document validation required by driver specifications.
|
|
346
312
|
# This method validates the first key of each update request document to be
|
|
347
313
|
# an operator (i.e. start with $) and the first key of each replacement
|
data/lib/mongo/client.rb
CHANGED
|
@@ -241,7 +241,11 @@ module Mongo
|
|
|
241
241
|
# printed to the mongod logs upon establishing a connection
|
|
242
242
|
# @option options [ Symbol ] :auth_mech The authentication mechanism to
|
|
243
243
|
# use. One of :mongodb_cr, :mongodb_x509, :plain, :scram, :scram256
|
|
244
|
-
# @option options [ Hash ] :auth_mech_properties
|
|
244
|
+
# @option options [ Hash ] :auth_mech_properties When passed in a
|
|
245
|
+
# connection string as authMechanismProperties, key-value pairs are
|
|
246
|
+
# delimited by commas, so a value containing a comma (",") must not be
|
|
247
|
+
# provided as part of the connection string. Such a value must be passed
|
|
248
|
+
# through this option instead. Values may contain colons (":").
|
|
245
249
|
# @option options [ String ] :auth_source The source to authenticate from.
|
|
246
250
|
# @option options [ true | false | nil | Integer ] :bg_error_backtrace
|
|
247
251
|
# Experimental. Set to true to log complete backtraces for errors in
|
|
@@ -509,6 +513,10 @@ module Mongo
|
|
|
509
513
|
# (this part of the API is subject to change).
|
|
510
514
|
# - :encrypted_fields_map => Hash | nil, maps a collection namespace to
|
|
511
515
|
# a hash describing encrypted fields for queryable encryption.
|
|
516
|
+
# - Note: Supplying an encrypted_fields_map provides more security
|
|
517
|
+
# than relying on an encryptedFields obtained from the server. It
|
|
518
|
+
# protects against a malicious server advertising a false
|
|
519
|
+
# encryptedFields.
|
|
512
520
|
# - Note: If a collection is present on both the encryptedFieldsMap
|
|
513
521
|
# and schemaMap, an error will be raised.
|
|
514
522
|
# - :bypass_query_analysis => Boolean | nil, when true disables automatic
|
|
@@ -519,6 +527,10 @@ module Mongo
|
|
|
519
527
|
# - :crypt_shared_lib_required => [ Boolean | nil ] Whether
|
|
520
528
|
# crypt shared library is required. If 'true', an error will be raised
|
|
521
529
|
# if a crypt_shared library cannot be loaded by libmongocrypt.
|
|
530
|
+
# - :key_expiration_ms => Integer | nil, the lifetime of the data
|
|
531
|
+
# encryption key cache, in milliseconds. Must be a non-negative
|
|
532
|
+
# integer. A value of 0 means the cache never expires. Defaults to
|
|
533
|
+
# 60000.
|
|
522
534
|
#
|
|
523
535
|
# Notes on automatic encryption:
|
|
524
536
|
# - Automatic encryption is an enterprise only feature that only applies
|
|
@@ -601,9 +613,7 @@ module Mongo
|
|
|
601
613
|
sdam_proc.call(self) if sdam_proc
|
|
602
614
|
|
|
603
615
|
@connect_lock = Mutex.new
|
|
604
|
-
@retry_policy =
|
|
605
|
-
max_retries: @options[:max_adaptive_retries] || Retryable::Backpressure::DEFAULT_MAX_RETRIES
|
|
606
|
-
)
|
|
616
|
+
@retry_policy = build_retry_policy
|
|
607
617
|
@connect_lock.synchronize do
|
|
608
618
|
@cluster = Cluster.new(
|
|
609
619
|
addresses,
|
|
@@ -621,7 +631,11 @@ module Mongo
|
|
|
621
631
|
build_encrypter
|
|
622
632
|
end
|
|
623
633
|
end
|
|
624
|
-
|
|
634
|
+
# ScriptError is rescued in addition to StandardError because
|
|
635
|
+
# Mongo::Crypt::Binding raises a LoadError when libmongocrypt cannot be
|
|
636
|
+
# found. Without it the cluster built above would be left open, leaking
|
|
637
|
+
# its monitoring and connection pool threads.
|
|
638
|
+
rescue StandardError, ScriptError
|
|
625
639
|
begin
|
|
626
640
|
@cluster.close
|
|
627
641
|
rescue StandardError => e
|
|
@@ -830,6 +844,12 @@ module Mongo
|
|
|
830
844
|
options.update(opts)
|
|
831
845
|
@options = options.freeze
|
|
832
846
|
|
|
847
|
+
# The retry policy is built from the options, so a client created by
|
|
848
|
+
# #with needs its own policy when the option changed.
|
|
849
|
+
if @options[:max_adaptive_retries] != old_options[:max_adaptive_retries]
|
|
850
|
+
@retry_policy = build_retry_policy
|
|
851
|
+
end
|
|
852
|
+
|
|
833
853
|
auto_encryption_options_changed =
|
|
834
854
|
@options[:auto_encryption_options] != old_options[:auto_encryption_options]
|
|
835
855
|
|
|
@@ -1260,6 +1280,16 @@ module Mongo
|
|
|
1260
1280
|
|
|
1261
1281
|
private
|
|
1262
1282
|
|
|
1283
|
+
# Builds the retry policy for the backpressure retry loops from the
|
|
1284
|
+
# client's options.
|
|
1285
|
+
#
|
|
1286
|
+
# @return [ Retryable::RetryPolicy ] The retry policy.
|
|
1287
|
+
def build_retry_policy
|
|
1288
|
+
Retryable::RetryPolicy.new(
|
|
1289
|
+
max_retries: @options[:max_adaptive_retries] || Retryable::Backpressure::DEFAULT_MAX_RETRIES
|
|
1290
|
+
)
|
|
1291
|
+
end
|
|
1292
|
+
|
|
1263
1293
|
# Attempts to parse the given list of addresses, using the provided options.
|
|
1264
1294
|
#
|
|
1265
1295
|
# @param [ String | Array<String> ] addresses the list of addresses
|
|
@@ -42,6 +42,10 @@ module Mongo
|
|
|
42
42
|
# @option options [ Integer ] :timeout_ms The operation timeout in milliseconds.
|
|
43
43
|
# Must be a non-negative integer. An explicit value of 0 means infinite.
|
|
44
44
|
# The default value is unset which means the feature is disabled.
|
|
45
|
+
# @option options [ Integer ] :key_expiration_ms The lifetime of the data
|
|
46
|
+
# encryption key cache, in milliseconds. Must be a non-negative integer.
|
|
47
|
+
# An explicit value of 0 means the cache never expires. The default is
|
|
48
|
+
# 60000.
|
|
45
49
|
#
|
|
46
50
|
# @raise [ ArgumentError ] If required options are missing or incorrectly
|
|
47
51
|
# formatted.
|
|
@@ -50,7 +54,9 @@ module Mongo
|
|
|
50
54
|
key_vault_client,
|
|
51
55
|
options[:key_vault_namespace],
|
|
52
56
|
Crypt::KMS::Credentials.new(options[:kms_providers]),
|
|
53
|
-
Crypt::KMS::Validations.validate_tls_options(options[:kms_tls_options])
|
|
57
|
+
Crypt::KMS::Validations.validate_tls_options(options[:kms_tls_options]),
|
|
58
|
+
options[:timeout_ms],
|
|
59
|
+
options[:key_expiration_ms]
|
|
54
60
|
)
|
|
55
61
|
end
|
|
56
62
|
|
|
@@ -100,15 +106,34 @@ module Mongo
|
|
|
100
106
|
# encryption key.
|
|
101
107
|
# @option options [ String ] :algorithm The algorithm used to encrypt the value.
|
|
102
108
|
# Valid algorithms are "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic",
|
|
103
|
-
# "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "Indexed", "Unindexed"
|
|
109
|
+
# "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "Indexed", "Unindexed", "Range",
|
|
110
|
+
# "String".
|
|
104
111
|
# @option options [ Integer | nil ] :contention_factor Contention factor
|
|
105
|
-
# to be applied if encryption algorithm is set to "Indexed"
|
|
106
|
-
# provided, it defaults to a value of 0. Contention factor
|
|
107
|
-
# only if encryption algorithm is set to "Indexed"
|
|
112
|
+
# to be applied if encryption algorithm is set to "Indexed", "Range", or
|
|
113
|
+
# "String". If not provided, it defaults to a value of 0. Contention factor
|
|
114
|
+
# should be set only if encryption algorithm is set to "Indexed", "Range",
|
|
115
|
+
# or "String".
|
|
108
116
|
# @option options [ String | nil ] query_type Query type to be applied
|
|
109
|
-
#
|
|
110
|
-
#
|
|
111
|
-
#
|
|
117
|
+
# if encryption algorithm is set to "Indexed", "Range", or "String".
|
|
118
|
+
# Allowed values are "equality" (for "Indexed"), "range" (for "Range"),
|
|
119
|
+
# and "prefix", "suffix", "substring" (for "String").
|
|
120
|
+
# @option options [ Hash | nil ] :range_opts Specifies index options for a
|
|
121
|
+
# Queryable Encryption field supporting "range" queries. Required when
|
|
122
|
+
# algorithm is "Range". Allowed options are :min, :max, :trim_factor,
|
|
123
|
+
# :sparsity, :precision.
|
|
124
|
+
# @option options [ Hash | nil ] :string_opts Specifies index options for a
|
|
125
|
+
# Queryable Encryption field supporting "prefix", "suffix", or "substring"
|
|
126
|
+
# queries. Required when algorithm is "String". Allowed options are
|
|
127
|
+
# :case_sensitive, :diacritic_sensitive, :prefix, :suffix, :substring.
|
|
128
|
+
#
|
|
129
|
+
# @note The result of explicit encryption with the "Indexed", "Range", or
|
|
130
|
+
# "String" algorithm must be processed by the server to insert or query.
|
|
131
|
+
# To insert or query with such a payload, use a Mongo::Client configured
|
|
132
|
+
# with :auto_encryption_options. The :bypass_query_analysis option may be
|
|
133
|
+
# true; the :bypass_auto_encryption option must be false.
|
|
134
|
+
#
|
|
135
|
+
# @note The "substring" query type is unstable and subject to backwards
|
|
136
|
+
# breaking changes.
|
|
112
137
|
#
|
|
113
138
|
# @note The :key_id and :key_alt_name options are mutually exclusive. Only
|
|
114
139
|
# one is required to perform explicit encryption.
|
|
@@ -116,8 +141,8 @@ module Mongo
|
|
|
116
141
|
# @return [ BSON::Binary ] A BSON Binary object of subtype 6 (ciphertext)
|
|
117
142
|
# representing the encrypted value.
|
|
118
143
|
#
|
|
119
|
-
# @raise [ ArgumentError ] if either contention_factor or query_type
|
|
120
|
-
#
|
|
144
|
+
# @raise [ ArgumentError ] if either contention_factor or query_type is set,
|
|
145
|
+
# and algorithm is not "Indexed", "Range", or "String".
|
|
121
146
|
def encrypt(value, options = {})
|
|
122
147
|
@encrypter.encrypt(value, options)
|
|
123
148
|
end
|
|
@@ -148,7 +173,7 @@ module Mongo
|
|
|
148
173
|
# expression. The only allowed value is "Range"
|
|
149
174
|
# @option options [ Integer | nil ] :contention_factor Contention factor
|
|
150
175
|
# to be applied If not provided, it defaults to a value of 0.
|
|
151
|
-
# @option options [ String | nil ] query_type Query type to be applied.
|
|
176
|
+
# @option options [ String | nil ] :query_type Query type to be applied.
|
|
152
177
|
# The only allowed value is "range".
|
|
153
178
|
#
|
|
154
179
|
# @note The :key_id and :key_alt_name options are mutually exclusive. Only
|
data/lib/mongo/cluster.rb
CHANGED
|
@@ -586,8 +586,7 @@ module Mongo
|
|
|
586
586
|
# @option options [ true | false ] :keep_connection_pool Usually when the
|
|
587
587
|
# new server description is unknown, the connection pool on the
|
|
588
588
|
# respective server is cleared. Set this option to true to keep the
|
|
589
|
-
# existing connection pool (required when handling not master errors
|
|
590
|
-
# on 4.2+ servers).
|
|
589
|
+
# existing connection pool (required when handling not master errors).
|
|
591
590
|
# @option options [ true | false ] :awaited Whether the updated description
|
|
592
591
|
# was a result of processing an awaited hello.
|
|
593
592
|
# @option options [ Object ] :service_id Change state for the specified
|
|
@@ -62,8 +62,8 @@ module Mongo
|
|
|
62
62
|
def maybe_drop_emm_collections(encrypted_fields, client, session)
|
|
63
63
|
encrypted_fields = if encrypted_fields
|
|
64
64
|
encrypted_fields
|
|
65
|
-
elsif
|
|
66
|
-
|
|
65
|
+
elsif client.options[:auto_encryption_options]
|
|
66
|
+
encrypted_fields_for_drop
|
|
67
67
|
else
|
|
68
68
|
{}
|
|
69
69
|
end
|
|
@@ -127,12 +127,13 @@ module Mongo
|
|
|
127
127
|
{}
|
|
128
128
|
end
|
|
129
129
|
|
|
130
|
-
# Tries to return the encrypted fields
|
|
131
|
-
# value,
|
|
130
|
+
# Tries to return the encrypted fields for the current namespace from
|
|
131
|
+
# the {{encrypted_fields_map}} value, falling back to the encrypted
|
|
132
|
+
# fields advertised by the server for the collection.
|
|
132
133
|
#
|
|
133
134
|
# @return [ Hash | nil ] the encrypted fields, if found
|
|
134
|
-
def
|
|
135
|
-
encrypted_fields_map[namespace] ||
|
|
135
|
+
def encrypted_fields_for_drop
|
|
136
|
+
(encrypted_fields_map && encrypted_fields_map[namespace]) ||
|
|
136
137
|
database.list_collections(filter: { name: name })
|
|
137
138
|
.first
|
|
138
139
|
&.fetch(:options, {})
|
|
@@ -115,15 +115,15 @@ module Mongo
|
|
|
115
115
|
|
|
116
116
|
def send_initial_query(server, context, operation: nil)
|
|
117
117
|
if server.load_balancer?
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
118
|
+
server.pool.with_cursor_connection(context: context) do |connection|
|
|
119
|
+
initial_query_op(
|
|
120
|
+
context.session,
|
|
121
|
+
effective_read_preference(connection)
|
|
122
|
+
).execute_with_connection(
|
|
123
|
+
connection,
|
|
124
|
+
context: context
|
|
125
|
+
)
|
|
126
|
+
end
|
|
127
127
|
else
|
|
128
128
|
server.with_connection do |connection|
|
|
129
129
|
initial_query_op(
|
|
@@ -350,8 +350,7 @@ module Mongo
|
|
|
350
350
|
if server.load_balancer?
|
|
351
351
|
# In load balanced topology, manually check out a connection
|
|
352
352
|
# so it remains checked out and pinned to the cursor.
|
|
353
|
-
|
|
354
|
-
begin
|
|
353
|
+
server.pool.with_cursor_connection(context: context) do |connection|
|
|
355
354
|
result = send_initial_query(connection, context)
|
|
356
355
|
|
|
357
356
|
start_at_operation_time = if (doc = result.replies.first && result.replies.first.documents.first)
|
|
@@ -360,9 +359,6 @@ module Mongo
|
|
|
360
359
|
nil
|
|
361
360
|
end
|
|
362
361
|
result
|
|
363
|
-
rescue StandardError
|
|
364
|
-
server.pool.check_in(connection)
|
|
365
|
-
raise
|
|
366
362
|
end
|
|
367
363
|
else
|
|
368
364
|
server.with_connection do |connection|
|
|
@@ -172,16 +172,9 @@ module Mongo
|
|
|
172
172
|
def send_initial_query(server, context, operation: nil)
|
|
173
173
|
operation ||= initial_query_op(context.session)
|
|
174
174
|
if server.load_balancer?
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
# case it stays checked out for the transaction duration).
|
|
178
|
-
if context.connection_global_id
|
|
179
|
-
connection = server.pool.check_out_pinned_connection(
|
|
180
|
-
context.connection_global_id
|
|
181
|
-
)
|
|
175
|
+
server.pool.with_cursor_connection(context: context) do |connection|
|
|
176
|
+
operation.execute_with_connection(connection, context: context)
|
|
182
177
|
end
|
|
183
|
-
connection ||= server.pool.check_out(context: context)
|
|
184
|
-
operation.execute_with_connection(connection, context: context)
|
|
185
178
|
else
|
|
186
179
|
operation.execute(server, context: context)
|
|
187
180
|
end
|
|
@@ -73,10 +73,11 @@ module Mongo
|
|
|
73
73
|
context = Operation::Context.new(client: client, session: session,
|
|
74
74
|
operation_timeouts: view.operation_timeouts)
|
|
75
75
|
if server.load_balancer?
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
result = server.pool.with_cursor_connection(context: context) do |connection|
|
|
77
|
+
res = send_initial_query_with_connection(connection, context.session, context: context)
|
|
78
|
+
res = send_fetch_query_with_connection(connection, session) unless inline?
|
|
79
|
+
res
|
|
80
|
+
end
|
|
80
81
|
else
|
|
81
82
|
result = send_initial_query(server, context)
|
|
82
83
|
result = send_fetch_query(server, session) unless inline?
|
|
@@ -739,9 +739,9 @@ module Mongo
|
|
|
739
739
|
connection_global_id: result.connection_global_id
|
|
740
740
|
)
|
|
741
741
|
result = if server.load_balancer?
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
742
|
+
server.pool.with_cursor_connection(context: context) do |connection|
|
|
743
|
+
op.execute_with_connection(connection, context: context)
|
|
744
|
+
end
|
|
745
745
|
else
|
|
746
746
|
op.execute(server, context: context)
|
|
747
747
|
end
|
|
@@ -88,11 +88,6 @@ module Mongo
|
|
|
88
88
|
operation_timeouts: operation_timeouts(opts)
|
|
89
89
|
)
|
|
90
90
|
write_with_retry(write_concern, context: context) do |connection, txn_num, context|
|
|
91
|
-
gte_4_4 = connection.server.description.server_version_gte?('4.4')
|
|
92
|
-
if !gte_4_4 && opts[:hint] && write_concern && !write_concern.acknowledged?
|
|
93
|
-
raise Error::UnsupportedOption.hint_error(unacknowledged_write: true)
|
|
94
|
-
end
|
|
95
|
-
|
|
96
91
|
Operation::WriteCommand.new(
|
|
97
92
|
selector: cmd,
|
|
98
93
|
db_name: database.name,
|
|
@@ -216,11 +211,6 @@ module Mongo
|
|
|
216
211
|
)
|
|
217
212
|
value = tracer.trace_operation(operation, context, op_name: 'findOneAndUpdate') do
|
|
218
213
|
write_with_retry(write_concern, context: context) do |connection, txn_num, context|
|
|
219
|
-
gte_4_4 = connection.server.description.server_version_gte?('4.4')
|
|
220
|
-
if !gte_4_4 && opts[:hint] && write_concern && !write_concern.acknowledged?
|
|
221
|
-
raise Error::UnsupportedOption.hint_error(unacknowledged_write: true)
|
|
222
|
-
end
|
|
223
|
-
|
|
224
214
|
operation.txn_num = txn_num
|
|
225
215
|
operation.execute_with_connection(connection, context: context)
|
|
226
216
|
end
|
|
@@ -287,11 +277,6 @@ module Mongo
|
|
|
287
277
|
)
|
|
288
278
|
tracer.trace_operation(operation, context, op_name: 'deleteMany') do
|
|
289
279
|
nro_write_with_retry(write_concern, context: context) do |connection, _txn_num, context|
|
|
290
|
-
gte_4_4 = connection.server.description.server_version_gte?('4.4')
|
|
291
|
-
if !gte_4_4 && opts[:hint] && write_concern && !write_concern.acknowledged?
|
|
292
|
-
raise Error::UnsupportedOption.hint_error(unacknowledged_write: true)
|
|
293
|
-
end
|
|
294
|
-
|
|
295
280
|
operation.execute_with_connection(connection, context: context)
|
|
296
281
|
end
|
|
297
282
|
end
|
|
@@ -346,11 +331,6 @@ module Mongo
|
|
|
346
331
|
operation_timeouts: operation_timeouts(opts)
|
|
347
332
|
)
|
|
348
333
|
write_with_retry(write_concern, context: context) do |connection, txn_num, context|
|
|
349
|
-
gte_4_4 = connection.server.description.server_version_gte?('4.4')
|
|
350
|
-
if !gte_4_4 && opts[:hint] && write_concern && !write_concern.acknowledged?
|
|
351
|
-
raise Error::UnsupportedOption.hint_error(unacknowledged_write: true)
|
|
352
|
-
end
|
|
353
|
-
|
|
354
334
|
Operation::Delete.new(
|
|
355
335
|
deletes: [ delete_doc ],
|
|
356
336
|
db_name: collection.database.name,
|
|
@@ -428,11 +408,6 @@ module Mongo
|
|
|
428
408
|
operation_timeouts: operation_timeouts(opts)
|
|
429
409
|
)
|
|
430
410
|
write_with_retry(write_concern, context: context) do |connection, txn_num, context|
|
|
431
|
-
gte_4_2 = connection.server.description.server_version_gte?('4.2')
|
|
432
|
-
if !gte_4_2 && opts[:hint] && write_concern && !write_concern.acknowledged?
|
|
433
|
-
raise Error::UnsupportedOption.hint_error(unacknowledged_write: true)
|
|
434
|
-
end
|
|
435
|
-
|
|
436
411
|
Operation::Update.new(
|
|
437
412
|
updates: [ update_doc ],
|
|
438
413
|
db_name: collection.database.name,
|
|
@@ -507,11 +482,6 @@ module Mongo
|
|
|
507
482
|
operation_timeouts: operation_timeouts(opts)
|
|
508
483
|
)
|
|
509
484
|
nro_write_with_retry(write_concern, context: context) do |connection, _txn_num, context|
|
|
510
|
-
gte_4_2 = connection.server.description.server_version_gte?('4.2')
|
|
511
|
-
if !gte_4_2 && opts[:hint] && write_concern && !write_concern.acknowledged?
|
|
512
|
-
raise Error::UnsupportedOption.hint_error(unacknowledged_write: true)
|
|
513
|
-
end
|
|
514
|
-
|
|
515
485
|
Operation::Update.new(
|
|
516
486
|
updates: [ update_doc ],
|
|
517
487
|
db_name: collection.database.name,
|
|
@@ -601,11 +571,6 @@ module Mongo
|
|
|
601
571
|
)
|
|
602
572
|
tracer.trace_operation(operation, context) do
|
|
603
573
|
write_with_retry(write_concern, context: context) do |connection, txn_num, context|
|
|
604
|
-
gte_4_2 = connection.server.description.server_version_gte?('4.2')
|
|
605
|
-
if !gte_4_2 && opts[:hint] && write_concern && !write_concern.acknowledged?
|
|
606
|
-
raise Error::UnsupportedOption.hint_error(unacknowledged_write: true)
|
|
607
|
-
end
|
|
608
|
-
|
|
609
574
|
operation.txn_num = txn_num
|
|
610
575
|
operation.execute_with_connection(connection, context: context)
|
|
611
576
|
end
|
|
@@ -81,6 +81,9 @@ module Mongo
|
|
|
81
81
|
# @option options [ Boolean | nil ] :crypt_shared_lib_required Whether
|
|
82
82
|
# crypt shared library is required. If 'true', an error will be raised
|
|
83
83
|
# if a crypt_shared library cannot be loaded by libmongocrypt.
|
|
84
|
+
# @option options [ Integer | nil ] :key_expiration_ms The lifetime of the
|
|
85
|
+
# data encryption key cache, in milliseconds. A value of 0 means the
|
|
86
|
+
# cache never expires. Defaults to 60000.
|
|
84
87
|
#
|
|
85
88
|
# @raise [ ArgumentError ] If required options are missing or incorrectly
|
|
86
89
|
# formatted.
|
|
@@ -99,7 +102,8 @@ module Mongo
|
|
|
99
102
|
bypass_query_analysis: @options[:bypass_query_analysis],
|
|
100
103
|
crypt_shared_lib_path: @options[:extra_options][:crypt_shared_lib_path],
|
|
101
104
|
crypt_shared_lib_required: @options[:extra_options][:crypt_shared_lib_required],
|
|
102
|
-
disable_crypt_shared_lib_search: @options[:extra_options][:disable_crypt_shared_lib_search]
|
|
105
|
+
disable_crypt_shared_lib_search: @options[:extra_options][:disable_crypt_shared_lib_search],
|
|
106
|
+
key_expiration_ms: @options[:key_expiration_ms]
|
|
103
107
|
)
|
|
104
108
|
|
|
105
109
|
@mongocryptd_options = @options[:extra_options].slice(
|
data/lib/mongo/crypt/binding.rb
CHANGED
|
@@ -81,7 +81,7 @@ module Mongo
|
|
|
81
81
|
# will cause a `LoadError`.
|
|
82
82
|
#
|
|
83
83
|
# @api private
|
|
84
|
-
MIN_LIBMONGOCRYPT_VERSION = Gem::Version.new('1.
|
|
84
|
+
MIN_LIBMONGOCRYPT_VERSION = Gem::Version.new('1.20.0')
|
|
85
85
|
|
|
86
86
|
# @!method self.mongocrypt_version(len)
|
|
87
87
|
# @api private
|
|
@@ -1479,6 +1479,31 @@ module Mongo
|
|
|
1479
1479
|
mongocrypt_setopt_bypass_query_analysis(handle.ref)
|
|
1480
1480
|
end
|
|
1481
1481
|
|
|
1482
|
+
# @!method self.mongocrypt_setopt_key_expiration(crypt, cache_expiration_ms)
|
|
1483
|
+
# @api private
|
|
1484
|
+
#
|
|
1485
|
+
# Set the expiration time for the data encryption key cache.
|
|
1486
|
+
#
|
|
1487
|
+
# @param [ FFI::Pointer ] crypt A pointer to a mongocrypt_t object.
|
|
1488
|
+
# @param [ Integer ] cache_expiration_ms The cache expiration time in
|
|
1489
|
+
# milliseconds. If zero, the cache never expires.
|
|
1490
|
+
# @return [ Boolean ] Returns whether the option was set successfully.
|
|
1491
|
+
attach_function(:mongocrypt_setopt_key_expiration, %i[pointer uint64], :bool)
|
|
1492
|
+
|
|
1493
|
+
# Set the expiration time for the data encryption key cache on the
|
|
1494
|
+
# Mongo::Crypt::Handle object.
|
|
1495
|
+
#
|
|
1496
|
+
# @param [ Mongo::Crypt::Handle ] handle
|
|
1497
|
+
# @param [ Integer ] cache_expiration_ms The cache expiration time in
|
|
1498
|
+
# milliseconds. If zero, the cache never expires.
|
|
1499
|
+
#
|
|
1500
|
+
# @raise [ Mongo::Error::CryptError ] If the option is not set successfully.
|
|
1501
|
+
def self.setopt_key_expiration(handle, cache_expiration_ms)
|
|
1502
|
+
check_status(handle) do
|
|
1503
|
+
mongocrypt_setopt_key_expiration(handle.ref, cache_expiration_ms)
|
|
1504
|
+
end
|
|
1505
|
+
end
|
|
1506
|
+
|
|
1482
1507
|
# @!method self.mongocrypt_setopt_aes_256_ctr(crypt, aes_256_ctr_encrypt, aes_256_ctr_decrypt, ctx)
|
|
1483
1508
|
# @api private
|
|
1484
1509
|
#
|
|
@@ -1873,6 +1898,46 @@ module Mongo
|
|
|
1873
1898
|
end
|
|
1874
1899
|
end
|
|
1875
1900
|
|
|
1901
|
+
# @!method self.mongocrypt_ctx_setopt_algorithm_text(ctx, opts)
|
|
1902
|
+
# @api private
|
|
1903
|
+
#
|
|
1904
|
+
# Set options for explicit encryption with the "String" algorithm.
|
|
1905
|
+
#
|
|
1906
|
+
# @note The libmongocrypt C function is named `..._algorithm_text` (the
|
|
1907
|
+
# original "text" name), even though the algorithm string passed to
|
|
1908
|
+
# mongocrypt_ctx_setopt_algorithm is "String" (renamed for GA). There is
|
|
1909
|
+
# no `..._algorithm_string` symbol; `..._algorithm_text` is the correct
|
|
1910
|
+
# and only setter for these options.
|
|
1911
|
+
#
|
|
1912
|
+
# @param [ FFI::Pointer ] ctx A pointer to a mongocrypt_ctx_t object.
|
|
1913
|
+
# @param [ FFI::Pointer ] opts A pointer to a string options document.
|
|
1914
|
+
#
|
|
1915
|
+
# @return [ Boolean ] Whether setting this option succeeded.
|
|
1916
|
+
attach_function(
|
|
1917
|
+
:mongocrypt_ctx_setopt_algorithm_text,
|
|
1918
|
+
%i[
|
|
1919
|
+
pointer
|
|
1920
|
+
pointer
|
|
1921
|
+
],
|
|
1922
|
+
:bool
|
|
1923
|
+
)
|
|
1924
|
+
|
|
1925
|
+
# Set options for explicit encryption with the "String" algorithm.
|
|
1926
|
+
#
|
|
1927
|
+
# @param [ Mongo::Crypt::Context ] context
|
|
1928
|
+
# @param [ Hash ] opts options
|
|
1929
|
+
#
|
|
1930
|
+
# @raise [ Mongo::Error::CryptError ] If the operation failed
|
|
1931
|
+
def self.ctx_setopt_algorithm_text(context, opts)
|
|
1932
|
+
validate_document(opts)
|
|
1933
|
+
data = opts.to_bson.to_s
|
|
1934
|
+
Binary.wrap_string(data) do |data_p|
|
|
1935
|
+
check_ctx_status(context) do
|
|
1936
|
+
mongocrypt_ctx_setopt_algorithm_text(context.ctx_p, data_p)
|
|
1937
|
+
end
|
|
1938
|
+
end
|
|
1939
|
+
end
|
|
1940
|
+
|
|
1876
1941
|
# Raise a Mongo::Error::CryptError based on the status of the underlying
|
|
1877
1942
|
# mongocrypt_t object.
|
|
1878
1943
|
#
|