mongo 2.13.1 → 2.14.0.rc1
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
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +1 -4
- data/lib/mongo.rb +9 -0
- data/lib/mongo/address/ipv4.rb +1 -1
- data/lib/mongo/address/ipv6.rb +1 -1
- data/lib/mongo/bulk_write.rb +17 -0
- data/lib/mongo/caching_cursor.rb +74 -0
- data/lib/mongo/client.rb +47 -8
- data/lib/mongo/cluster.rb +3 -3
- data/lib/mongo/cluster/topology/single.rb +1 -1
- data/lib/mongo/collection.rb +26 -0
- data/lib/mongo/collection/view.rb +24 -20
- data/lib/mongo/collection/view/aggregation.rb +25 -4
- data/lib/mongo/collection/view/builder/find_command.rb +38 -18
- data/lib/mongo/collection/view/explainable.rb +27 -8
- data/lib/mongo/collection/view/iterable.rb +72 -12
- data/lib/mongo/collection/view/readable.rb +12 -2
- data/lib/mongo/collection/view/writable.rb +15 -1
- data/lib/mongo/crypt/encryption_io.rb +6 -6
- data/lib/mongo/cursor.rb +1 -0
- data/lib/mongo/database.rb +6 -0
- data/lib/mongo/error.rb +2 -0
- data/lib/mongo/error/invalid_read_concern.rb +28 -0
- data/lib/mongo/error/server_certificate_revoked.rb +22 -0
- data/lib/mongo/error/unsupported_option.rb +14 -12
- data/lib/mongo/lint.rb +2 -1
- data/lib/mongo/logger.rb +3 -3
- data/lib/mongo/operation.rb +2 -0
- data/lib/mongo/operation/aggregate/result.rb +9 -8
- data/lib/mongo/operation/collections_info/result.rb +2 -0
- data/lib/mongo/operation/delete/bulk_result.rb +2 -0
- data/lib/mongo/operation/delete/result.rb +3 -0
- data/lib/mongo/operation/explain/command.rb +4 -0
- data/lib/mongo/operation/explain/legacy.rb +4 -0
- data/lib/mongo/operation/explain/op_msg.rb +6 -0
- data/lib/mongo/operation/explain/result.rb +3 -0
- data/lib/mongo/operation/find/legacy/result.rb +2 -0
- data/lib/mongo/operation/find/result.rb +3 -0
- data/lib/mongo/operation/get_more/result.rb +3 -0
- data/lib/mongo/operation/indexes/result.rb +5 -0
- data/lib/mongo/operation/insert/bulk_result.rb +5 -0
- data/lib/mongo/operation/insert/result.rb +5 -0
- data/lib/mongo/operation/list_collections/result.rb +5 -0
- data/lib/mongo/operation/map_reduce/result.rb +10 -0
- data/lib/mongo/operation/parallel_scan/result.rb +4 -0
- data/lib/mongo/operation/result.rb +35 -6
- data/lib/mongo/operation/shared/bypass_document_validation.rb +1 -0
- data/lib/mongo/operation/shared/causal_consistency_supported.rb +1 -0
- data/lib/mongo/operation/shared/collections_info_or_list_collections.rb +2 -0
- data/lib/mongo/operation/shared/executable.rb +1 -0
- data/lib/mongo/operation/shared/idable.rb +2 -1
- data/lib/mongo/operation/shared/limited.rb +1 -0
- data/lib/mongo/operation/shared/object_id_generator.rb +1 -0
- data/lib/mongo/operation/shared/result/aggregatable.rb +1 -0
- data/lib/mongo/operation/shared/sessions_supported.rb +1 -0
- data/lib/mongo/operation/shared/specifiable.rb +1 -0
- data/lib/mongo/operation/shared/write.rb +1 -0
- data/lib/mongo/operation/shared/write_concern_supported.rb +1 -0
- data/lib/mongo/operation/update/legacy/result.rb +7 -0
- data/lib/mongo/operation/update/result.rb +8 -0
- data/lib/mongo/operation/users_info/result.rb +3 -0
- data/lib/mongo/query_cache.rb +242 -0
- data/lib/mongo/retryable.rb +8 -1
- data/lib/mongo/server.rb +5 -1
- data/lib/mongo/server/connection_common.rb +2 -2
- data/lib/mongo/server/connection_pool.rb +3 -0
- data/lib/mongo/server/monitor.rb +1 -1
- data/lib/mongo/server/monitor/connection.rb +3 -3
- data/lib/mongo/server/pending_connection.rb +2 -2
- data/lib/mongo/server/push_monitor.rb +1 -1
- data/lib/mongo/server_selector/base.rb +5 -1
- data/lib/mongo/session.rb +3 -0
- data/lib/mongo/socket.rb +6 -4
- data/lib/mongo/socket/ocsp_cache.rb +97 -0
- data/lib/mongo/socket/ocsp_verifier.rb +368 -0
- data/lib/mongo/socket/ssl.rb +45 -24
- data/lib/mongo/srv/monitor.rb +7 -13
- data/lib/mongo/srv/resolver.rb +14 -10
- data/lib/mongo/timeout.rb +2 -0
- data/lib/mongo/uri.rb +21 -390
- data/lib/mongo/uri/options_mapper.rb +582 -0
- data/lib/mongo/uri/srv_protocol.rb +3 -2
- data/lib/mongo/utils.rb +12 -1
- data/lib/mongo/version.rb +1 -1
- data/spec/NOTES.aws-auth.md +12 -7
- data/spec/README.md +56 -1
- data/spec/integration/bulk_write_spec.rb +48 -0
- data/spec/integration/client_authentication_options_spec.rb +55 -28
- data/spec/integration/connection_pool_populator_spec.rb +3 -1
- data/spec/integration/cursor_reaping_spec.rb +53 -17
- data/spec/integration/ocsp_connectivity_spec.rb +26 -0
- data/spec/integration/ocsp_verifier_cache_spec.rb +188 -0
- data/spec/integration/ocsp_verifier_spec.rb +334 -0
- data/spec/integration/query_cache_spec.rb +1045 -0
- data/spec/integration/query_cache_transactions_spec.rb +179 -0
- data/spec/integration/retryable_writes/retryable_writes_40_and_newer_spec.rb +1 -0
- data/spec/integration/retryable_writes/shared/performs_legacy_retries.rb +2 -0
- data/spec/integration/sdam_error_handling_spec.rb +68 -0
- data/spec/integration/server_selection_spec.rb +36 -0
- data/spec/integration/srv_monitoring_spec.rb +38 -3
- data/spec/integration/srv_spec.rb +56 -0
- data/spec/lite_spec_helper.rb +3 -1
- data/spec/mongo/address_spec.rb +1 -1
- data/spec/mongo/caching_cursor_spec.rb +70 -0
- data/spec/mongo/client_construction_spec.rb +54 -1
- data/spec/mongo/client_spec.rb +40 -0
- data/spec/mongo/cluster/topology/single_spec.rb +14 -5
- data/spec/mongo/cluster_spec.rb +3 -0
- data/spec/mongo/collection/view/explainable_spec.rb +87 -4
- data/spec/mongo/collection/view/map_reduce_spec.rb +2 -0
- data/spec/mongo/collection_spec.rb +60 -0
- data/spec/mongo/crypt/auto_decryption_context_spec.rb +1 -1
- data/spec/mongo/crypt/auto_encryption_context_spec.rb +1 -1
- data/spec/mongo/crypt/explicit_decryption_context_spec.rb +1 -1
- data/spec/mongo/crypt/explicit_encryption_context_spec.rb +1 -1
- data/spec/mongo/database_spec.rb +44 -0
- data/spec/mongo/error/no_server_available_spec.rb +1 -1
- data/spec/mongo/logger_spec.rb +13 -11
- data/spec/mongo/query_cache_spec.rb +279 -0
- data/spec/mongo/server/connection_pool_spec.rb +7 -3
- data/spec/mongo/server/connection_spec.rb +14 -7
- data/spec/mongo/socket/ssl_spec.rb +1 -1
- data/spec/mongo/socket_spec.rb +1 -1
- data/spec/mongo/uri/srv_protocol_spec.rb +64 -33
- data/spec/mongo/uri_option_parsing_spec.rb +11 -11
- data/spec/mongo/uri_spec.rb +68 -41
- data/spec/mongo/utils_spec.rb +39 -0
- data/spec/runners/auth.rb +3 -0
- data/spec/runners/connection_string.rb +35 -124
- data/spec/spec_tests/cmap_spec.rb +7 -3
- data/spec/spec_tests/data/change_streams/change-streams-errors.yml +0 -1
- data/spec/spec_tests/data/change_streams/change-streams.yml +0 -1
- data/spec/spec_tests/data/cmap/pool-checkout-connection.yml +6 -2
- data/spec/spec_tests/data/cmap/pool-create-min-size.yml +3 -0
- data/spec/spec_tests/data/connection_string/valid-warnings.yml +24 -0
- data/spec/spec_tests/data/sdam_monitoring/discovered_standalone.yml +1 -3
- data/spec/spec_tests/data/sdam_monitoring/standalone.yml +2 -2
- data/spec/spec_tests/data/sdam_monitoring/standalone_repeated.yml +2 -2
- data/spec/spec_tests/data/sdam_monitoring/standalone_suppress_equal_description_changes.yml +2 -2
- data/spec/spec_tests/data/sdam_monitoring/standalone_to_rs_with_me_mismatch.yml +2 -2
- data/spec/spec_tests/data/uri_options/auth-options.yml +25 -0
- data/spec/spec_tests/data/uri_options/compression-options.yml +6 -3
- data/spec/spec_tests/data/uri_options/read-preference-options.yml +24 -0
- data/spec/spec_tests/data/uri_options/ruby-connection-options.yml +1 -0
- data/spec/spec_tests/data/uri_options/tls-options.yml +160 -4
- data/spec/spec_tests/dns_seedlist_discovery_spec.rb +9 -1
- data/spec/spec_tests/uri_options_spec.rb +31 -33
- data/spec/support/certificates/atlas-ocsp-ca.crt +28 -0
- data/spec/support/certificates/atlas-ocsp.crt +41 -0
- data/spec/support/client_registry_macros.rb +11 -2
- data/spec/support/common_shortcuts.rb +45 -0
- data/spec/support/constraints.rb +23 -0
- data/spec/support/lite_constraints.rb +24 -0
- data/spec/support/matchers.rb +16 -0
- data/spec/support/ocsp +1 -0
- data/spec/support/session_registry.rb +52 -0
- data/spec/support/spec_config.rb +22 -0
- data/spec/support/utils.rb +19 -1
- metadata +38 -3
- metadata.gz.sig +0 -0
@@ -21,17 +21,20 @@ module Mongo
|
|
21
21
|
# version <= 2.4.
|
22
22
|
#
|
23
23
|
# @since 2.0.0
|
24
|
+
# @api semiprivate
|
24
25
|
class Result < Operation::Result
|
25
26
|
include Operation::Result::UseLegacyErrorParser
|
26
27
|
|
27
28
|
# Whether an existing document was updated.
|
28
29
|
#
|
29
30
|
# @since 2.0.0
|
31
|
+
# @api private
|
30
32
|
UPDATED_EXISTING = 'updatedExisting'.freeze
|
31
33
|
|
32
34
|
# The upserted docs field in the result.
|
33
35
|
#
|
34
36
|
# @since 2.0.0
|
37
|
+
# @api private
|
35
38
|
UPSERTED = 'upserted'.freeze
|
36
39
|
|
37
40
|
# Get the number of documents matched.
|
@@ -42,6 +45,7 @@ module Mongo
|
|
42
45
|
# @return [ Integer ] The matched count.
|
43
46
|
#
|
44
47
|
# @since 2.0.0
|
48
|
+
# @api public
|
45
49
|
def matched_count
|
46
50
|
return 0 unless acknowledged?
|
47
51
|
if upsert?
|
@@ -59,6 +63,7 @@ module Mongo
|
|
59
63
|
# @return [ nil ] Always omitted for legacy versions.
|
60
64
|
#
|
61
65
|
# @since 2.0.0
|
66
|
+
# @api public
|
62
67
|
def modified_count; end
|
63
68
|
|
64
69
|
# The identifier of the inserted document if an upsert
|
@@ -70,6 +75,7 @@ module Mongo
|
|
70
75
|
# @return [ Object ] The upserted id.
|
71
76
|
#
|
72
77
|
# @since 2.0.0
|
78
|
+
# @api public
|
73
79
|
def upserted_id
|
74
80
|
first[UPSERTED] if upsert?
|
75
81
|
end
|
@@ -82,6 +88,7 @@ module Mongo
|
|
82
88
|
# @return [ Integer ] The number upserted.
|
83
89
|
#
|
84
90
|
# @since 2.4.2
|
91
|
+
# @api public
|
85
92
|
def upserted_count
|
86
93
|
upsert? ? n : 0
|
87
94
|
end
|
@@ -19,16 +19,19 @@ module Mongo
|
|
19
19
|
# Defines custom behavior of results for an update.
|
20
20
|
#
|
21
21
|
# @since 2.0.0
|
22
|
+
# @api semiprivate
|
22
23
|
class Result < Operation::Result
|
23
24
|
|
24
25
|
# The number of modified docs field in the result.
|
25
26
|
#
|
26
27
|
# @since 2.0.0
|
28
|
+
# @api private
|
27
29
|
MODIFIED = 'nModified'.freeze
|
28
30
|
|
29
31
|
# The upserted docs field in the result.
|
30
32
|
#
|
31
33
|
# @since 2.0.0
|
34
|
+
# @api private
|
32
35
|
UPSERTED = 'upserted'.freeze
|
33
36
|
|
34
37
|
# Get the number of documents matched.
|
@@ -39,6 +42,7 @@ module Mongo
|
|
39
42
|
# @return [ Integer ] The matched count.
|
40
43
|
#
|
41
44
|
# @since 2.0.0
|
45
|
+
# @api public
|
42
46
|
def matched_count
|
43
47
|
return 0 unless acknowledged?
|
44
48
|
if upsert?
|
@@ -56,6 +60,7 @@ module Mongo
|
|
56
60
|
# @return [ Integer ] The modified count.
|
57
61
|
#
|
58
62
|
# @since 2.0.0
|
63
|
+
# @api public
|
59
64
|
def modified_count
|
60
65
|
return 0 unless acknowledged?
|
61
66
|
first[MODIFIED]
|
@@ -70,6 +75,7 @@ module Mongo
|
|
70
75
|
# @return [ Object ] The upserted id.
|
71
76
|
#
|
72
77
|
# @since 2.0.0
|
78
|
+
# @api public
|
73
79
|
def upserted_id
|
74
80
|
return nil unless upsert?
|
75
81
|
upsert?.first['_id']
|
@@ -83,10 +89,12 @@ module Mongo
|
|
83
89
|
# @return [ Integer ] The number upserted.
|
84
90
|
#
|
85
91
|
# @since 2.4.2
|
92
|
+
# @api public
|
86
93
|
def upserted_count
|
87
94
|
upsert? ? n : 0
|
88
95
|
end
|
89
96
|
|
97
|
+
# @api public
|
90
98
|
def bulk_result
|
91
99
|
BulkResult.new(@replies, connection_description)
|
92
100
|
end
|
@@ -20,13 +20,16 @@ module Mongo
|
|
20
20
|
# usersInfo command.
|
21
21
|
#
|
22
22
|
# @since 2.1.0
|
23
|
+
# @api semiprivate
|
23
24
|
class Result < Operation::Result
|
24
25
|
|
25
26
|
# The field name for the users document in a usersInfo result.
|
26
27
|
#
|
27
28
|
# @since 2.1.0
|
29
|
+
# @api private
|
28
30
|
USERS = 'users'.freeze
|
29
31
|
|
32
|
+
# @api public
|
30
33
|
def documents
|
31
34
|
reply.documents.first[USERS]
|
32
35
|
end
|
@@ -0,0 +1,242 @@
|
|
1
|
+
# Copyright (C) 2020 MongoDB, Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
module Mongo
|
16
|
+
module QueryCache
|
17
|
+
class << self
|
18
|
+
|
19
|
+
# Set whether the cache is enabled.
|
20
|
+
#
|
21
|
+
# @example Set if the cache is enabled.
|
22
|
+
# QueryCache.enabled = true
|
23
|
+
#
|
24
|
+
# @param [ true, false ] value The enabled value.
|
25
|
+
def enabled=(value)
|
26
|
+
Thread.current["[mongo]:query_cache:enabled"] = value
|
27
|
+
end
|
28
|
+
|
29
|
+
# Is the query cache enabled on the current thread?
|
30
|
+
#
|
31
|
+
# @example Is the query cache enabled?
|
32
|
+
# QueryCache.enabled?
|
33
|
+
#
|
34
|
+
# @return [ true, false ] If the cache is enabled.
|
35
|
+
def enabled?
|
36
|
+
!!Thread.current["[mongo]:query_cache:enabled"]
|
37
|
+
end
|
38
|
+
|
39
|
+
# Execute the block while using the query cache.
|
40
|
+
#
|
41
|
+
# @example Execute with the cache.
|
42
|
+
# QueryCache.cache { collection.find }
|
43
|
+
#
|
44
|
+
# @return [ Object ] The result of the block.
|
45
|
+
def cache
|
46
|
+
enabled = enabled?
|
47
|
+
self.enabled = true
|
48
|
+
begin
|
49
|
+
yield
|
50
|
+
ensure
|
51
|
+
self.enabled = enabled
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Execute the block with the query cache disabled.
|
56
|
+
#
|
57
|
+
# @example Execute without the cache.
|
58
|
+
# QueryCache.uncached { collection.find }
|
59
|
+
#
|
60
|
+
# @return [ Object ] The result of the block.
|
61
|
+
def uncached
|
62
|
+
enabled = enabled?
|
63
|
+
self.enabled = false
|
64
|
+
begin
|
65
|
+
yield
|
66
|
+
ensure
|
67
|
+
self.enabled = enabled
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Get the cached queries.
|
72
|
+
#
|
73
|
+
# @example Get the cached queries from the current thread.
|
74
|
+
# QueryCache.cache_table
|
75
|
+
#
|
76
|
+
# @return [ Hash ] The hash of cached queries.
|
77
|
+
private def cache_table
|
78
|
+
Thread.current["[mongo]:query_cache"] ||= {}
|
79
|
+
end
|
80
|
+
|
81
|
+
# Clear the query cache.
|
82
|
+
#
|
83
|
+
# @example Clear the cache.
|
84
|
+
# QueryCache.clear
|
85
|
+
#
|
86
|
+
# @return [ nil ] Always nil.
|
87
|
+
def clear
|
88
|
+
Thread.current["[mongo]:query_cache"] = nil
|
89
|
+
end
|
90
|
+
|
91
|
+
# Clear the section of the query cache storing cursors with results
|
92
|
+
# from this namespace.
|
93
|
+
#
|
94
|
+
# @param [ String ] namespace The namespace to be cleared, in the format
|
95
|
+
# "database.collection".
|
96
|
+
#
|
97
|
+
# @return [ nil ] Always nil.
|
98
|
+
#
|
99
|
+
# @api private
|
100
|
+
def clear_namespace(namespace)
|
101
|
+
cache_table.delete(namespace)
|
102
|
+
# The nil key is where cursors are stored that could potentially read from
|
103
|
+
# multiple collections. This key should be cleared on every write operation
|
104
|
+
# to prevent returning stale data.
|
105
|
+
cache_table.delete(nil)
|
106
|
+
nil
|
107
|
+
end
|
108
|
+
|
109
|
+
# Store a CachingCursor instance in the query cache associated with the
|
110
|
+
# specified query options.
|
111
|
+
#
|
112
|
+
# @param [ Mongo::CachingCursor ] cursor The CachingCursor instance to store.
|
113
|
+
#
|
114
|
+
# @option opts [ String | nil ] namespace The namespace of the query,
|
115
|
+
# in the format "database_name.collection_name".
|
116
|
+
# @option opts [ Array, Hash ] selector The selector passed to the query.
|
117
|
+
# For most queries, this will be a Hash, but for aggregations, this
|
118
|
+
# will be an Array representing the aggregation pipeline. May not be nil.
|
119
|
+
# @option opts [ Integer | nil ] skip The skip value of the query.
|
120
|
+
# @option opts [ Hash | nil ] sort The order of the query results
|
121
|
+
# (e.g. { name: -1 }).
|
122
|
+
# @option opts [ Integer | nil ] limit The limit value of the query.
|
123
|
+
# @option opts [ Hash | nil ] projection The projection of the query
|
124
|
+
# results (e.g. { name: 1 }).
|
125
|
+
# @option opts [ Hash | nil ] collation The collation of the query
|
126
|
+
# (e.g. { "locale" => "fr_CA" }).
|
127
|
+
# @option opts [ Hash | nil ] read_concern The read concern of the query
|
128
|
+
# (e.g. { level: :majority }).
|
129
|
+
# @option opts [ Hash | nil ] read_preference The read preference of
|
130
|
+
# the query (e.g. { mode: :secondary }).
|
131
|
+
# @option opts [ Boolean | nil ] multi_collection Whether the query
|
132
|
+
# results could potentially come from multiple collections. When true,
|
133
|
+
# these results will be stored under the nil namespace key and cleared
|
134
|
+
# on every write command.
|
135
|
+
#
|
136
|
+
# @return [ true ] Always true.
|
137
|
+
#
|
138
|
+
# @api private
|
139
|
+
def set(cursor, **opts)
|
140
|
+
_cache_key = cache_key(**opts)
|
141
|
+
_namespace_key = namespace_key(**opts)
|
142
|
+
|
143
|
+
cache_table[_namespace_key] ||= {}
|
144
|
+
cache_table[_namespace_key][_cache_key] = cursor
|
145
|
+
|
146
|
+
true
|
147
|
+
end
|
148
|
+
|
149
|
+
# For the given query options, retrieve a cached cursor that can be used
|
150
|
+
# to obtain the correct query results, if one exists in the cache.
|
151
|
+
#
|
152
|
+
# @option opts [ String | nil ] namespace The namespace of the query,
|
153
|
+
# in the format "database_name.collection_name".
|
154
|
+
# @option opts [ Array, Hash ] selector The selector passed to the query.
|
155
|
+
# For most queries, this will be a Hash, but for aggregations, this
|
156
|
+
# will be an Array representing the aggregation pipeline. May not be nil.
|
157
|
+
# @option opts [ Integer | nil ] skip The skip value of the query.
|
158
|
+
# @option opts [ Hash | nil ] sort The order of the query results
|
159
|
+
# (e.g. { name: -1 }).
|
160
|
+
# @option opts [ Integer | nil ] limit The limit value of the query.
|
161
|
+
# @option opts [ Hash | nil ] projection The projection of the query
|
162
|
+
# results (e.g. { name: 1 }).
|
163
|
+
# @option opts [ Hash | nil ] collation The collation of the query
|
164
|
+
# (e.g. { "locale" => "fr_CA" }).
|
165
|
+
# @option opts [ Hash | nil ] read_concern The read concern of the query
|
166
|
+
# (e.g. { level: :majority }).
|
167
|
+
# @option opts [ Hash | nil ] read_preference The read preference of
|
168
|
+
# the query (e.g. { mode: :secondary }).
|
169
|
+
# @option opts [ Boolean | nil ] multi_collection Whether the query
|
170
|
+
# results could potentially come from multiple collections. When true,
|
171
|
+
# these results will be stored under the nil namespace key and cleared
|
172
|
+
# on every write command.
|
173
|
+
#
|
174
|
+
# @return [ Mongo::CachingCursor | nil ] Returns a CachingCursor if one
|
175
|
+
# exists in the query cache, otherwise returns nil.
|
176
|
+
#
|
177
|
+
# @api private
|
178
|
+
def get(**opts)
|
179
|
+
limit = opts[:limit]
|
180
|
+
_namespace_key = namespace_key(**opts)
|
181
|
+
_cache_key = cache_key(**opts)
|
182
|
+
|
183
|
+
namespace_hash = cache_table[_namespace_key]
|
184
|
+
return nil unless namespace_hash
|
185
|
+
|
186
|
+
caching_cursor = namespace_hash[_cache_key]
|
187
|
+
return nil unless caching_cursor
|
188
|
+
|
189
|
+
caching_cursor_limit = caching_cursor.view.limit
|
190
|
+
|
191
|
+
# There are two scenarios in which a caching cursor could fulfill the
|
192
|
+
# query:
|
193
|
+
# 1. The query has a limit, and the stored cursor has no limit or
|
194
|
+
# a larger limit.
|
195
|
+
# 2. The query has no limit and the stored cursor has no limit.
|
196
|
+
#
|
197
|
+
# Otherwise, return nil because the stored cursor will not satisfy
|
198
|
+
# the query.
|
199
|
+
if limit && (caching_cursor_limit.nil? || caching_cursor_limit >= limit)
|
200
|
+
caching_cursor
|
201
|
+
elsif limit.nil? && caching_cursor_limit.nil?
|
202
|
+
caching_cursor
|
203
|
+
else
|
204
|
+
nil
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
private
|
209
|
+
|
210
|
+
def cache_key(**opts)
|
211
|
+
unless opts[:namespace]
|
212
|
+
raise ArgumentError.new("Cannot generate cache key without namespace")
|
213
|
+
end
|
214
|
+
unless opts[:selector]
|
215
|
+
raise ArgumentError.new("Cannot generate cache key without selector")
|
216
|
+
end
|
217
|
+
|
218
|
+
[
|
219
|
+
opts[:namespace],
|
220
|
+
opts[:selector],
|
221
|
+
opts[:skip],
|
222
|
+
opts[:sort],
|
223
|
+
opts[:projection],
|
224
|
+
opts[:collation],
|
225
|
+
opts[:read_concern],
|
226
|
+
opts[:read_preference]
|
227
|
+
]
|
228
|
+
end
|
229
|
+
|
230
|
+
# If the cached results can come from multiple collections, store this
|
231
|
+
# cursor under the nil namespace to be cleared on every write operation.
|
232
|
+
# Otherwise, store it under the specified namespace.
|
233
|
+
def namespace_key(**opts)
|
234
|
+
if opts[:multi_collection]
|
235
|
+
nil
|
236
|
+
else
|
237
|
+
opts[:namespace]
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|