mongo 2.9.2 → 2.10.0.rc0
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 +0 -0
- data/lib/mongo.rb +1 -0
- data/lib/mongo/auth/user/view.rb +4 -4
- data/lib/mongo/bulk_write.rb +14 -8
- data/lib/mongo/bulk_write/result.rb +1 -1
- data/lib/mongo/bulk_write/result_combiner.rb +2 -2
- data/lib/mongo/bulk_write/transformable.rb +17 -9
- data/lib/mongo/client.rb +107 -16
- data/lib/mongo/cluster.rb +47 -25
- data/lib/mongo/cluster/topology/replica_set_no_primary.rb +1 -1
- data/lib/mongo/cluster_time.rb +139 -0
- data/lib/mongo/collection.rb +84 -25
- data/lib/mongo/collection/view.rb +7 -3
- data/lib/mongo/collection/view/aggregation.rb +4 -4
- data/lib/mongo/collection/view/builder/aggregation.rb +31 -6
- data/lib/mongo/collection/view/builder/find_command.rb +4 -1
- data/lib/mongo/collection/view/builder/map_reduce.rb +4 -1
- data/lib/mongo/collection/view/change_stream.rb +54 -66
- data/lib/mongo/collection/view/iterable.rb +2 -2
- data/lib/mongo/collection/view/map_reduce.rb +6 -4
- data/lib/mongo/collection/view/readable.rb +36 -16
- data/lib/mongo/collection/view/writable.rb +68 -22
- data/lib/mongo/cursor.rb +87 -20
- data/lib/mongo/database.rb +47 -43
- data/lib/mongo/database/view.rb +54 -11
- data/lib/mongo/error.rb +13 -4
- data/lib/mongo/error/invalid_write_concern.rb +2 -2
- data/lib/mongo/error/operation_failure.rb +65 -11
- data/lib/mongo/error/parser.rb +41 -8
- data/lib/mongo/grid/fs_bucket.rb +26 -6
- data/lib/mongo/grid/stream/read.rb +9 -2
- data/lib/mongo/grid/stream/write.rb +21 -5
- data/lib/mongo/index/view.rb +3 -3
- data/lib/mongo/lint.rb +10 -3
- data/lib/mongo/operation.rb +2 -0
- data/lib/mongo/operation/aggregate/result.rb +19 -6
- data/lib/mongo/operation/collections_info.rb +1 -1
- data/lib/mongo/operation/get_more/result.rb +9 -0
- data/lib/mongo/operation/list_collections/command.rb +1 -3
- data/lib/mongo/operation/list_collections/op_msg.rb +1 -2
- data/lib/mongo/operation/parallel_scan/command.rb +4 -1
- data/lib/mongo/operation/parallel_scan/op_msg.rb +4 -1
- data/lib/mongo/operation/result.rb +27 -4
- data/lib/mongo/operation/shared/executable.rb +19 -5
- data/lib/mongo/operation/shared/executable_no_validate.rb +1 -2
- data/lib/mongo/operation/shared/executable_transaction_label.rb +0 -9
- data/lib/mongo/operation/shared/polymorphic_result.rb +9 -1
- data/lib/mongo/operation/shared/result/aggregatable.rb +2 -2
- data/lib/mongo/operation/shared/sessions_supported.rb +42 -32
- data/lib/mongo/operation/shared/specifiable.rb +40 -0
- data/lib/mongo/operation/shared/unpinnable.rb +39 -0
- data/lib/mongo/operation/shared/write.rb +1 -1
- data/lib/mongo/protocol/update.rb +6 -2
- data/lib/mongo/retryable.rb +79 -39
- data/lib/mongo/server/connection.rb +10 -3
- data/lib/mongo/server/description.rb +25 -1
- data/lib/mongo/server/monitor/connection.rb +1 -1
- data/lib/mongo/server_selector.rb +10 -0
- data/lib/mongo/server_selector/selectable.rb +172 -32
- data/lib/mongo/session.rb +654 -581
- data/lib/mongo/session/session_pool.rb +1 -1
- data/lib/mongo/socket.rb +7 -28
- data/lib/mongo/socket/ssl.rb +26 -1
- data/lib/mongo/socket/tcp.rb +3 -0
- data/lib/mongo/socket/unix.rb +3 -0
- data/lib/mongo/uri.rb +112 -265
- data/lib/mongo/uri/srv_protocol.rb +4 -1
- data/lib/mongo/version.rb +1 -1
- data/lib/mongo/write_concern.rb +10 -29
- data/lib/mongo/write_concern/acknowledged.rb +12 -0
- data/lib/mongo/write_concern/base.rb +17 -13
- data/lib/mongo/write_concern/unacknowledged.rb +12 -0
- data/spec/atlas/atlas_connectivity_spec.rb +7 -37
- data/spec/atlas/operations_spec.rb +25 -0
- data/spec/integration/change_stream_examples_spec.rb +45 -31
- data/spec/integration/change_stream_spec.rb +305 -5
- data/spec/integration/client_spec.rb +44 -0
- data/spec/integration/command_monitoring_spec.rb +1 -0
- data/spec/integration/command_spec.rb +7 -1
- data/spec/integration/mmapv1_spec.rb +28 -0
- data/spec/integration/mongos_pinning_spec.rb +34 -0
- data/spec/integration/operation_failure_code_spec.rb +2 -2
- data/spec/integration/{read_concern.rb → read_concern_spec.rb} +7 -1
- data/spec/integration/read_preference_spec.rb +485 -0
- data/spec/integration/retryable_writes_spec.rb +8 -19
- data/spec/integration/sdam_error_handling_spec.rb +1 -1
- data/spec/integration/sdam_events_spec.rb +2 -2
- data/spec/integration/server_description_spec.rb +14 -17
- data/spec/integration/server_selector_spec.rb +7 -3
- data/spec/integration/server_spec.rb +48 -0
- data/spec/integration/ssl_uri_options_spec.rb +1 -1
- data/spec/integration/step_down_spec.rb +10 -4
- data/spec/integration/transactions_examples_spec.rb +11 -10
- data/spec/lite_spec_helper.rb +19 -16
- data/spec/mongo/auth/scram/negotiation_spec.rb +11 -8
- data/spec/mongo/bulk_write/ordered_combiner_spec.rb +6 -6
- data/spec/mongo/bulk_write/unordered_combiner_spec.rb +4 -4
- data/spec/mongo/bulk_write_spec.rb +12 -2
- data/spec/mongo/client_construction_spec.rb +160 -8
- data/spec/mongo/client_spec.rb +5 -4
- data/spec/mongo/cluster_spec.rb +6 -6
- data/spec/mongo/cluster_time_spec.rb +148 -0
- data/spec/mongo/collection/view/aggregation_spec.rb +34 -15
- data/spec/mongo/collection/view/change_stream_spec.rb +62 -3
- data/spec/mongo/collection/view/map_reduce_spec.rb +7 -5
- data/spec/mongo/collection/view/readable_spec.rb +4 -4
- data/spec/mongo/collection_spec.rb +331 -14
- data/spec/mongo/cursor_spec.rb +117 -5
- data/spec/mongo/database_spec.rb +240 -8
- data/spec/mongo/error/operation_failure_spec.rb +47 -1
- data/spec/mongo/error/parser_spec.rb +160 -23
- data/spec/mongo/operation/insert/bulk_spec.rb +2 -1
- data/spec/mongo/operation/result_spec.rb +27 -0
- data/spec/mongo/operation/update/bulk_spec.rb +1 -0
- data/spec/mongo/retryable_spec.rb +2 -0
- data/spec/mongo/server/app_metadata_spec.rb +2 -2
- data/spec/mongo/server/connection_spec.rb +13 -17
- data/spec/mongo/server/monitor/connection_spec.rb +13 -10
- data/spec/mongo/server_selector_spec.rb +34 -2
- data/spec/mongo/session/session_pool_spec.rb +14 -3
- data/spec/mongo/session_spec.rb +3 -3
- data/spec/mongo/session_transaction_spec.rb +4 -3
- data/spec/mongo/socket/ssl_spec.rb +19 -5
- data/spec/mongo/socket_spec.rb +1 -62
- data/spec/mongo/uri/srv_protocol_spec.rb +14 -20
- data/spec/mongo/uri_option_parsing_spec.rb +94 -8
- data/spec/mongo/uri_spec.rb +23 -10
- data/spec/mongo/write_concern_spec.rb +56 -3
- data/spec/spec_tests/change_streams_spec.rb +2 -1
- data/spec/spec_tests/cmap_spec.rb +1 -1
- data/spec/spec_tests/crud_spec.rb +12 -2
- data/spec/spec_tests/data/change_streams/change-streams-errors.yml +24 -1
- data/spec/spec_tests/data/change_streams/change-streams.yml +172 -3
- data/spec/spec_tests/data/command_monitoring/bulkWrite.yml +1 -1
- data/spec/spec_tests/data/command_monitoring/updateMany.yml +0 -2
- data/spec/spec_tests/data/command_monitoring/updateOne.yml +0 -5
- data/spec/spec_tests/data/crud/read/aggregate-out.yml +0 -6
- data/spec/spec_tests/data/crud/read/count-empty.yml +29 -0
- data/spec/spec_tests/data/crud/write/bulkWrite-arrayFilters.yml +1 -0
- data/spec/spec_tests/data/crud/write/bulkWrite-collation.yml +101 -0
- data/spec/spec_tests/data/crud/write/bulkWrite.yml +401 -0
- data/spec/spec_tests/data/crud/write/insertMany.yml +58 -2
- data/spec/spec_tests/data/crud/write/updateMany-arrayFilters.yml +3 -0
- data/spec/spec_tests/data/crud/write/updateOne-arrayFilters.yml +6 -1
- data/spec/spec_tests/data/crud_v2/aggregate-merge.yml +103 -0
- data/spec/spec_tests/data/crud_v2/aggregate-out-readConcern.yml +110 -0
- data/spec/spec_tests/data/crud_v2/bulkWrite-arrayFilters.yml +81 -0
- data/spec/spec_tests/data/crud_v2/db-aggregate.yml +38 -0
- data/spec/spec_tests/data/crud_v2/updateWithPipelines.yml +92 -0
- data/spec/spec_tests/data/retryable_writes/insertOne-serverErrors.yml +2 -2
- data/spec/spec_tests/data/transactions/abort.yml +3 -0
- data/spec/spec_tests/data/transactions/bulk.yml +3 -8
- data/spec/spec_tests/data/transactions/causal-consistency.yml +3 -8
- data/spec/spec_tests/data/transactions/commit.yml +3 -1
- data/spec/spec_tests/data/transactions/count.yml +3 -0
- data/spec/spec_tests/data/transactions/delete.yml +3 -0
- data/spec/spec_tests/data/transactions/error-labels.yml +4 -1
- data/spec/spec_tests/data/transactions/errors-client.yml +56 -0
- data/spec/spec_tests/data/transactions/errors.yml +3 -0
- data/spec/spec_tests/data/transactions/findOneAndDelete.yml +3 -0
- data/spec/spec_tests/data/transactions/findOneAndReplace.yml +3 -0
- data/spec/spec_tests/data/transactions/findOneAndUpdate.yml +3 -0
- data/spec/spec_tests/data/transactions/insert.yml +3 -0
- data/spec/spec_tests/data/transactions/isolation.yml +3 -0
- data/spec/spec_tests/data/transactions/mongos-pin-auto.yml +1671 -0
- data/spec/spec_tests/data/transactions/mongos-recovery-token.yml +347 -0
- data/spec/spec_tests/data/transactions/pin-mongos.yml +557 -0
- data/spec/spec_tests/data/transactions/read-concern.yml +3 -0
- data/spec/spec_tests/data/transactions/read-pref.yml +3 -0
- data/spec/spec_tests/data/transactions/reads.yml +3 -0
- data/spec/spec_tests/data/transactions/retryable-abort.yml +5 -2
- data/spec/spec_tests/data/transactions/retryable-commit.yml +4 -1
- data/spec/spec_tests/data/transactions/retryable-writes.yml +3 -0
- data/spec/spec_tests/data/transactions/run-command.yml +3 -0
- data/spec/spec_tests/data/transactions/transaction-options.yml +6 -0
- data/spec/spec_tests/data/transactions/update.yml +3 -8
- data/spec/spec_tests/data/transactions/write-concern.yml +348 -38
- data/spec/spec_tests/data/transactions_api/callback-aborts.yml +6 -0
- data/spec/spec_tests/data/transactions_api/callback-commits.yml +5 -0
- data/spec/spec_tests/data/transactions_api/callback-retry.yml +7 -2
- data/spec/spec_tests/data/transactions_api/commit-retry.yml +70 -15
- data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror-4.2.yml +3 -0
- data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror.yml +3 -0
- data/spec/spec_tests/data/transactions_api/commit-writeconcernerror.yml +59 -109
- data/spec/spec_tests/data/transactions_api/commit.yml +5 -0
- data/spec/spec_tests/data/transactions_api/transaction-options.yml +10 -0
- data/spec/spec_tests/retryable_reads_spec.rb +5 -2
- data/spec/spec_tests/retryable_writes_spec.rb +5 -2
- data/spec/spec_tests/sdam_monitoring_spec.rb +3 -3
- data/spec/spec_tests/sdam_spec.rb +2 -2
- data/spec/spec_tests/transactions_api_spec.rb +1 -67
- data/spec/spec_tests/transactions_spec.rb +2 -66
- data/spec/support/authorization.rb +4 -0
- data/spec/support/change_streams.rb +30 -10
- data/spec/support/change_streams/operation.rb +27 -0
- data/spec/support/client_registry.rb +44 -25
- data/spec/support/cluster_config.rb +25 -14
- data/spec/support/cluster_tools.rb +32 -10
- data/spec/support/command_monitoring.rb +1 -1
- data/spec/support/common_shortcuts.rb +30 -0
- data/spec/support/connection_string.rb +8 -3
- data/spec/support/constraints.rb +34 -0
- data/spec/support/crud.rb +31 -16
- data/spec/support/crud/context.rb +23 -0
- data/spec/support/crud/operation.rb +311 -14
- data/spec/support/crud/spec.rb +2 -1
- data/spec/support/crud/test.rb +24 -27
- data/spec/support/crud/test_base.rb +22 -0
- data/spec/support/crud/verifier.rb +15 -1
- data/spec/support/event_subscriber.rb +12 -0
- data/spec/support/sdam_formatter_integration.rb +12 -6
- data/spec/support/shared/server_selector.rb +10 -0
- data/spec/support/shared/session.rb +13 -12
- data/spec/support/spec_config.rb +32 -22
- data/spec/support/spec_setup.rb +2 -2
- data/spec/support/transactions.rb +87 -0
- data/spec/support/transactions/context.rb +33 -0
- data/spec/support/transactions/operation.rb +99 -349
- data/spec/support/transactions/spec.rb +1 -3
- data/spec/support/transactions/test.rb +110 -49
- data/spec/support/utils.rb +74 -1
- metadata +52 -10
- metadata.gz.sig +0 -0
- data/spec/support/crud/read.rb +0 -265
- data/spec/support/crud/write.rb +0 -284
@@ -46,7 +46,6 @@ module Mongo
|
|
46
46
|
include Immutable
|
47
47
|
include Iterable
|
48
48
|
include Readable
|
49
|
-
include Retryable
|
50
49
|
include Explainable
|
51
50
|
include Writable
|
52
51
|
|
@@ -60,7 +59,12 @@ module Mongo
|
|
60
59
|
def_delegators :collection,
|
61
60
|
:client,
|
62
61
|
:cluster,
|
63
|
-
:database
|
62
|
+
:database,
|
63
|
+
:read_with_retry,
|
64
|
+
:read_with_retry_cursor,
|
65
|
+
:write_with_retry,
|
66
|
+
:nro_write_with_retry,
|
67
|
+
:write_concern_with_session
|
64
68
|
|
65
69
|
# Delegate to the cluster for the next primary.
|
66
70
|
def_delegators :cluster, :next_primary
|
@@ -163,7 +167,7 @@ module Mongo
|
|
163
167
|
#
|
164
168
|
# @since 2.0.0
|
165
169
|
def write_concern
|
166
|
-
WriteConcern.get(options[:
|
170
|
+
WriteConcern.get(options[:write_concern] || options[:write] || collection.write_concern)
|
167
171
|
end
|
168
172
|
|
169
173
|
private
|
@@ -111,18 +111,18 @@ module Mongo
|
|
111
111
|
server.standalone? || server.mongos? || server.primary? || secondary_ok?
|
112
112
|
end
|
113
113
|
|
114
|
-
def
|
115
|
-
pipeline.any? { |op| op.key?('$out') || op.key?(:$out) }
|
114
|
+
def write?
|
115
|
+
pipeline.any? { |op| op.key?('$out') || op.key?(:$out) || op.key?('$merge') || op.key?(:$merge) }
|
116
116
|
end
|
117
117
|
|
118
118
|
def secondary_ok?
|
119
|
-
!
|
119
|
+
!write?
|
120
120
|
end
|
121
121
|
|
122
122
|
def send_initial_query(server, session)
|
123
123
|
unless valid_server?(server)
|
124
124
|
log_warn("Rerouting the Aggregation operation to the primary server - #{server.summary} is not suitable")
|
125
|
-
server = cluster.next_primary
|
125
|
+
server = cluster.next_primary(nil, session)
|
126
126
|
end
|
127
127
|
validate_collation!(server)
|
128
128
|
initial_query_op(session).execute(server)
|
@@ -78,22 +78,40 @@ module Mongo
|
|
78
78
|
spec = {
|
79
79
|
selector: aggregation_command,
|
80
80
|
db_name: database.name,
|
81
|
-
read:
|
81
|
+
read: view.read_preference,
|
82
82
|
session: @options[:session]
|
83
83
|
}
|
84
|
-
write?
|
84
|
+
if write?
|
85
|
+
spec.update(write_concern: write_concern)
|
86
|
+
end
|
87
|
+
spec
|
85
88
|
end
|
86
89
|
|
87
90
|
private
|
88
91
|
|
89
92
|
def write?
|
90
|
-
pipeline.any?
|
93
|
+
pipeline.any? do |operator|
|
94
|
+
operator[:$out] || operator['$out'] ||
|
95
|
+
operator[:$merge] || operator['$merge']
|
96
|
+
end
|
91
97
|
end
|
92
98
|
|
93
99
|
def aggregation_command
|
94
|
-
command = BSON::Document.new
|
100
|
+
command = BSON::Document.new
|
101
|
+
# aggregate must be the first key in the command document
|
102
|
+
if view.is_a?(Collection::View)
|
103
|
+
command[:aggregate] = collection.name
|
104
|
+
elsif view.is_a?(Database::View)
|
105
|
+
command[:aggregate] = 1
|
106
|
+
else
|
107
|
+
raise ArgumentError, "Unknown view class: #{view}"
|
108
|
+
end
|
109
|
+
command[:pipeline] = pipeline
|
110
|
+
if read_concern = view.read_concern
|
111
|
+
command[:readConcern] = Options::Mapper.transform_values_to_strings(
|
112
|
+
read_concern)
|
113
|
+
end
|
95
114
|
command[:cursor] = cursor if cursor
|
96
|
-
command[:readConcern] = collection.read_concern if collection.read_concern
|
97
115
|
command.merge!(Options::Mapper.transform_documents(options, MAPPINGS))
|
98
116
|
command
|
99
117
|
end
|
@@ -105,7 +123,14 @@ module Mongo
|
|
105
123
|
end
|
106
124
|
|
107
125
|
def batch_size_doc
|
108
|
-
|
126
|
+
value = options[:batch_size] || view.batch_size
|
127
|
+
if value == 0 && write?
|
128
|
+
{}
|
129
|
+
elsif value
|
130
|
+
{ :batchSize => value }
|
131
|
+
else
|
132
|
+
{}
|
133
|
+
end
|
109
134
|
end
|
110
135
|
end
|
111
136
|
end
|
@@ -96,7 +96,10 @@ module Mongo
|
|
96
96
|
|
97
97
|
def find_command
|
98
98
|
document = BSON::Document.new('find' => collection.name, 'filter' => filter)
|
99
|
-
|
99
|
+
if collection.read_concern
|
100
|
+
document[:readConcern] = Options::Mapper.transform_values_to_strings(
|
101
|
+
collection.read_concern)
|
102
|
+
end
|
100
103
|
command = Options::Mapper.transform_documents(convert_flags(options), MAPPINGS, document)
|
101
104
|
convert_limit_and_batch_size(command)
|
102
105
|
command
|
@@ -139,7 +139,10 @@ module Mongo
|
|
139
139
|
:query => filter,
|
140
140
|
:out => { inline: 1 }
|
141
141
|
)
|
142
|
-
|
142
|
+
if collection.read_concern
|
143
|
+
command[:readConcern] = Options::Mapper.transform_values_to_strings(
|
144
|
+
collection.read_concern)
|
145
|
+
end
|
143
146
|
command.merge!(view_options)
|
144
147
|
command.merge!(Options::Mapper.transform_documents(options, MAPPINGS))
|
145
148
|
command
|
@@ -94,8 +94,12 @@ module Mongo
|
|
94
94
|
@changes_for = changes_for
|
95
95
|
@change_stream_filters = pipeline && pipeline.dup
|
96
96
|
@options = options && options.dup.freeze
|
97
|
-
@resume_token = @options[:resume_after]
|
98
97
|
@start_after = @options[:start_after]
|
98
|
+
|
99
|
+
# The resume token tracked by the change stream, used only
|
100
|
+
# when there is no cursor, or no cursor resume token
|
101
|
+
@resume_token = @start_after || @options[:resume_after]
|
102
|
+
|
99
103
|
create_cursor!
|
100
104
|
|
101
105
|
# We send different parameters when we resume a change stream
|
@@ -121,26 +125,12 @@ module Mongo
|
|
121
125
|
# @yieldparam [ BSON::Document ] Each change stream document.
|
122
126
|
def each
|
123
127
|
raise StopIteration.new if closed?
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
cache_resume_token(doc)
|
128
|
-
yield doc
|
129
|
-
end if block_given?
|
130
|
-
@cursor.to_enum
|
131
|
-
rescue Mongo::Error => e
|
132
|
-
if retried || !e.change_stream_resumable?
|
133
|
-
raise
|
134
|
-
end
|
135
|
-
|
136
|
-
retried = true
|
137
|
-
# Rerun initial aggregation.
|
138
|
-
# Any errors here will stop iteration and break out of this
|
139
|
-
# method
|
140
|
-
close
|
141
|
-
create_cursor!
|
142
|
-
retry
|
128
|
+
loop do
|
129
|
+
document = try_next
|
130
|
+
yield document if document
|
143
131
|
end
|
132
|
+
rescue StopIteration => e
|
133
|
+
return self
|
144
134
|
end
|
145
135
|
|
146
136
|
# Return one document from the change stream, if one is available.
|
@@ -153,10 +143,7 @@ module Mongo
|
|
153
143
|
# for changes from the server, and if no changes are received
|
154
144
|
# it will return nil.
|
155
145
|
#
|
156
|
-
# @note This method is experimental and subject to change.
|
157
|
-
#
|
158
146
|
# @return [ BSON::Document | nil ] A change stream document.
|
159
|
-
# @api experimental
|
160
147
|
# @since 2.6.0
|
161
148
|
def try_next
|
162
149
|
raise StopIteration.new if closed?
|
@@ -165,27 +152,28 @@ module Mongo
|
|
165
152
|
begin
|
166
153
|
doc = @cursor.try_next
|
167
154
|
rescue Mongo::Error => e
|
168
|
-
|
155
|
+
if retried || !e.change_stream_resumable?
|
169
156
|
raise
|
170
157
|
end
|
171
158
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
end
|
159
|
+
retried = true
|
160
|
+
# Rerun initial aggregation.
|
161
|
+
# Any errors here will stop iteration and break out of this
|
162
|
+
# method
|
163
|
+
|
164
|
+
# Save cursor's resume token so we can use it
|
165
|
+
# to create a new cursor
|
166
|
+
@resume_token = @cursor.resume_token
|
167
|
+
|
168
|
+
close
|
169
|
+
create_cursor!
|
170
|
+
retry
|
185
171
|
end
|
186
172
|
|
187
|
-
|
188
|
-
|
173
|
+
# We need to verify each doc has an _id, so we
|
174
|
+
# have a resume token to work with
|
175
|
+
if doc && doc['_id'].nil?
|
176
|
+
raise Error::MissingResumeToken
|
189
177
|
end
|
190
178
|
doc
|
191
179
|
end
|
@@ -238,7 +226,21 @@ module Mongo
|
|
238
226
|
# @since 2.5.0
|
239
227
|
def inspect
|
240
228
|
"#<Mongo::Collection::View:ChangeStream:0x#{object_id} filters=#{@change_stream_filters} " +
|
241
|
-
"options=#{@options} resume_token=#{
|
229
|
+
"options=#{@options} resume_token=#{resume_token}>"
|
230
|
+
end
|
231
|
+
|
232
|
+
# Returns the resume token that the stream will
|
233
|
+
# use to automatically resume, if one exists.
|
234
|
+
#
|
235
|
+
# @example Get the change stream resume token.
|
236
|
+
# stream.resume_token
|
237
|
+
#
|
238
|
+
# @return [ BSON::Document | nil ] The change stream resume token.
|
239
|
+
#
|
240
|
+
# @since 2.10.0
|
241
|
+
def resume_token
|
242
|
+
cursor_resume_token = @cursor.resume_token if @cursor
|
243
|
+
cursor_resume_token || @resume_token
|
242
244
|
end
|
243
245
|
|
244
246
|
private
|
@@ -255,15 +257,6 @@ module Mongo
|
|
255
257
|
!for_cluster? && !for_database?
|
256
258
|
end
|
257
259
|
|
258
|
-
def cache_resume_token(doc)
|
259
|
-
# Always record both resume token and operation time,
|
260
|
-
# in case we get an older or newer server during rolling
|
261
|
-
# upgrades/downgrades
|
262
|
-
unless @resume_token = (doc[:_id] && doc[:_id].dup)
|
263
|
-
raise Error::MissingResumeToken
|
264
|
-
end
|
265
|
-
end
|
266
|
-
|
267
260
|
def create_cursor!
|
268
261
|
# clear the cache because we may get a newer or an older server
|
269
262
|
# (rolling upgrades)
|
@@ -271,7 +264,10 @@ module Mongo
|
|
271
264
|
|
272
265
|
session = client.send(:get_session, @options)
|
273
266
|
start_at_operation_time = nil
|
267
|
+
start_at_operation_time_supported = nil
|
274
268
|
@cursor = read_with_retry_cursor(session, server_selector, view) do |server|
|
269
|
+
start_at_operation_time_supported = server.description.server_version_gte?('4.0')
|
270
|
+
|
275
271
|
result = send_initial_query(server, session)
|
276
272
|
if doc = result.replies.first && result.replies.first.documents.first
|
277
273
|
start_at_operation_time = doc['operationTime']
|
@@ -286,6 +282,7 @@ module Mongo
|
|
286
282
|
result
|
287
283
|
end
|
288
284
|
@start_at_operation_time = start_at_operation_time
|
285
|
+
@start_at_operation_time_supported = start_at_operation_time_supported
|
289
286
|
end
|
290
287
|
|
291
288
|
def pipeline
|
@@ -305,14 +302,11 @@ module Mongo
|
|
305
302
|
# However, if the first getMore fails and the user didn't pass
|
306
303
|
# a resume token we won't have a resume token to use.
|
307
304
|
# Use start_at_operation time in this case
|
308
|
-
if
|
309
|
-
# Spec says we need to remove startAtOperationTime if
|
310
|
-
#
|
311
|
-
|
312
|
-
|
313
|
-
# either `startAfter` or `startAtOperationTime`.
|
314
|
-
@resume_token = @start_after
|
315
|
-
elsif start_at_operation_time_supported? && @start_at_operation_time
|
305
|
+
if resume_token
|
306
|
+
# Spec says we need to remove both startAtOperationTime and startAfter if
|
307
|
+
# either was passed in by user, thus we won't forward them
|
308
|
+
doc[:resumeAfter] = resume_token
|
309
|
+
elsif @start_at_operation_time_supported && @start_at_operation_time
|
316
310
|
# It is crucial to check @start_at_operation_time_supported
|
317
311
|
# here - we may have switched to an older server that
|
318
312
|
# does not support operation times and therefore shouldn't
|
@@ -327,6 +321,8 @@ module Mongo
|
|
327
321
|
else
|
328
322
|
if @start_after
|
329
323
|
doc[:startAfter] = @start_after
|
324
|
+
elsif resume_token
|
325
|
+
doc[:resumeAfter] = resume_token
|
330
326
|
end
|
331
327
|
|
332
328
|
if options[:start_at_operation_time]
|
@@ -334,7 +330,7 @@ module Mongo
|
|
334
330
|
options[:start_at_operation_time])
|
335
331
|
end
|
336
332
|
end
|
337
|
-
|
333
|
+
|
338
334
|
doc[:allChangesForCluster] = true if for_cluster?
|
339
335
|
end
|
340
336
|
end
|
@@ -357,14 +353,6 @@ module Mongo
|
|
357
353
|
def resuming?
|
358
354
|
!!@resuming
|
359
355
|
end
|
360
|
-
|
361
|
-
def start_at_operation_time_supported?
|
362
|
-
if @start_at_operation_time_supported.nil?
|
363
|
-
server = server_selector.select_server(cluster)
|
364
|
-
@start_at_operation_time_supported = server.description.max_wire_version >= 7
|
365
|
-
end
|
366
|
-
@start_at_operation_time_supported
|
367
|
-
end
|
368
356
|
end
|
369
357
|
end
|
370
358
|
end
|
@@ -37,8 +37,8 @@ module Mongo
|
|
37
37
|
def each
|
38
38
|
@cursor = nil
|
39
39
|
session = client.send(:get_session, @options)
|
40
|
-
@cursor = if respond_to?(:
|
41
|
-
server = server_selector.select_server(cluster)
|
40
|
+
@cursor = if respond_to?(:write?, true) && write?
|
41
|
+
server = server_selector.select_server(cluster, nil, session)
|
42
42
|
result = send_initial_query(server, session)
|
43
43
|
Cursor.new(view, result, server, session: session)
|
44
44
|
else
|
@@ -68,7 +68,7 @@ module Mongo
|
|
68
68
|
def each
|
69
69
|
@cursor = nil
|
70
70
|
session = client.send(:get_session, @options)
|
71
|
-
server = cluster.next_primary
|
71
|
+
server = cluster.next_primary(nil, session)
|
72
72
|
result = send_initial_query(server, session)
|
73
73
|
result = send_fetch_query(server, session) unless inline?
|
74
74
|
@cursor = Cursor.new(view, result, server, session: session)
|
@@ -195,7 +195,8 @@ module Mongo
|
|
195
195
|
# @since 2.5.0
|
196
196
|
def execute
|
197
197
|
view.send(:with_session, @options) do |session|
|
198
|
-
|
198
|
+
write_concern = view.write_concern_with_session(session)
|
199
|
+
nro_write_with_retry(session, write_concern) do |server|
|
199
200
|
send_initial_query(server, session)
|
200
201
|
end
|
201
202
|
end
|
@@ -233,8 +234,9 @@ module Mongo
|
|
233
234
|
|
234
235
|
def send_initial_query(server, session)
|
235
236
|
unless valid_server?(server)
|
236
|
-
|
237
|
-
|
237
|
+
msg = "Rerouting the MapReduce operation to the primary server - #{server.summary} is not suitable"
|
238
|
+
log_warn(msg)
|
239
|
+
server = cluster.next_primary(nil, session)
|
238
240
|
end
|
239
241
|
validate_collation!(server)
|
240
242
|
initial_query_op(session).execute(server)
|
@@ -138,7 +138,10 @@ module Mongo
|
|
138
138
|
cmd[:skip] = opts[:skip] if opts[:skip]
|
139
139
|
cmd[:hint] = opts[:hint] if opts[:hint]
|
140
140
|
cmd[:limit] = opts[:limit] if opts[:limit]
|
141
|
-
|
141
|
+
if read_concern
|
142
|
+
cmd[:readConcern] = Options::Mapper.transform_values_to_strings(
|
143
|
+
read_concern)
|
144
|
+
end
|
142
145
|
cmd[:maxTimeMS] = opts[:max_time_ms] if opts[:max_time_ms]
|
143
146
|
Mongo::Lint.validate_underscore_read_preference(opts[:read])
|
144
147
|
read_pref = opts[:read] || read_preference
|
@@ -205,7 +208,10 @@ module Mongo
|
|
205
208
|
def estimated_document_count(opts = {})
|
206
209
|
cmd = { count: collection.name }
|
207
210
|
cmd[:maxTimeMS] = opts[:max_time_ms] if opts[:max_time_ms]
|
208
|
-
|
211
|
+
if read_concern
|
212
|
+
cmd[:readConcern] = Options::Mapper.transform_values_to_strings(
|
213
|
+
read_concern)
|
214
|
+
end
|
209
215
|
Mongo::Lint.validate_underscore_read_preference(opts[:read])
|
210
216
|
read_pref = opts[:read] || read_preference
|
211
217
|
selector = ServerSelector.get(read_pref || server_selector)
|
@@ -242,7 +248,10 @@ module Mongo
|
|
242
248
|
:key => field_name.to_s,
|
243
249
|
:query => filter }
|
244
250
|
cmd[:maxTimeMS] = opts[:max_time_ms] if opts[:max_time_ms]
|
245
|
-
|
251
|
+
if read_concern
|
252
|
+
cmd[:readConcern] = Options::Mapper.transform_values_to_strings(
|
253
|
+
read_concern)
|
254
|
+
end
|
246
255
|
Mongo::Lint.validate_underscore_read_preference(opts[:read])
|
247
256
|
read_pref = opts[:read] || read_preference
|
248
257
|
selector = ServerSelector.get(read_pref || server_selector)
|
@@ -533,12 +542,7 @@ module Mongo
|
|
533
542
|
configure(:cursor_type, type)
|
534
543
|
end
|
535
544
|
|
536
|
-
private
|
537
|
-
|
538
|
-
def collation(doc = nil)
|
539
|
-
configure(:collation, doc)
|
540
|
-
end
|
541
|
-
|
545
|
+
# @api private
|
542
546
|
def read_concern
|
543
547
|
if options[:session] && options[:session].in_transaction?
|
544
548
|
options[:session].send(:txn_read_concern) || collection.client.read_concern
|
@@ -547,14 +551,30 @@ module Mongo
|
|
547
551
|
end
|
548
552
|
end
|
549
553
|
|
554
|
+
# @api private
|
550
555
|
def read_preference
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
556
|
+
@read_preference ||= begin
|
557
|
+
# Operation read preference is always respected, and has the
|
558
|
+
# highest priority. If we are in a transaction, we look at
|
559
|
+
# transaction read preference and default to client, ignoring
|
560
|
+
# collection read preference. If we are not in transaction we
|
561
|
+
# look at collection read preference which defaults to client.
|
562
|
+
rp = if options[:read]
|
563
|
+
options[:read]
|
564
|
+
elsif options[:session] && options[:session].in_transaction?
|
565
|
+
options[:session].txn_read_preference || collection.client.read_preference
|
566
|
+
else
|
567
|
+
collection.read_preference
|
568
|
+
end
|
569
|
+
Lint.validate_underscore_read_preference(rp)
|
570
|
+
rp
|
555
571
|
end
|
556
|
-
|
557
|
-
|
572
|
+
end
|
573
|
+
|
574
|
+
private
|
575
|
+
|
576
|
+
def collation(doc = nil)
|
577
|
+
configure(:collation, doc)
|
558
578
|
end
|
559
579
|
|
560
580
|
def server_selector
|
@@ -571,7 +591,7 @@ module Mongo
|
|
571
591
|
else
|
572
592
|
session = nil
|
573
593
|
end
|
574
|
-
server = server_selector.select_server(cluster)
|
594
|
+
server = server_selector.select_server(cluster, nil, session)
|
575
595
|
cmd = Operation::ParallelScan.new({
|
576
596
|
:coll_name => collection.name,
|
577
597
|
:db_name => database.name,
|