diff options
author | Mickey. J Winters <mickey.winters@mongodb.com> | 2022-04-28 13:54:23 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-04-28 14:27:30 +0000 |
commit | 18ad6a3c107d165be8b66b6b4be25c849d34f814 (patch) | |
tree | 28f374d03d161d3572bf9bad690aac0baeb21890 | |
parent | 1de5826097917875f48ca1ea4f2e53b40139f9ff (diff) | |
download | mongo-18ad6a3c107d165be8b66b6b4be25c849d34f814.tar.gz |
SERVER-64780 filter out resharding events that aren't related to the namespace being watched by a changeStream
3 files changed, 68 insertions, 1 deletions
diff --git a/etc/backports_required_for_multiversion_tests.yml b/etc/backports_required_for_multiversion_tests.yml index 9fcc921e897..805b4e0ae8f 100644 --- a/etc/backports_required_for_multiversion_tests.yml +++ b/etc/backports_required_for_multiversion_tests.yml @@ -453,6 +453,8 @@ last-lts: test_file: jstests/sharding/update_with_dollar_fields.js - ticket: SERVER-63531 test_file: jstests/replsets/buildindexes_false_commit_quorum.js + - ticket: SERVER-64780 + test_file: jstest/sharding/resharding_change_stream_namespace_filtering.js # Tests that should only be excluded from particular suites should be listed under that suite. suites: diff --git a/jstests/sharding/resharding_change_stream_namespace_filtering.js b/jstests/sharding/resharding_change_stream_namespace_filtering.js new file mode 100644 index 00000000000..85b5fd8a33d --- /dev/null +++ b/jstests/sharding/resharding_change_stream_namespace_filtering.js @@ -0,0 +1,63 @@ +/* + * Tests that a change stream on collection X doesn't erroneously see resharding events which occur + * on collection Y. Exercises the fix for SERVER-64780. + * @tags: [ + * uses_change_streams, + * requires_fcv_50 + * ] + */ + +(function() { +"use strict"; + +load("jstests/libs/collection_drop_recreate.js"); // For assertDropAndRecreateCollection. +load("jstests/libs/chunk_manipulation_util.js"); // For pauseMigrateAtStep, waitForMigrateStep and + // unpauseMigrateAtStep. + +const st = new ShardingTest({ + shards: 2, + rs: {nodes: 1, setParameter: {writePeriodicNoops: true, periodicNoopIntervalSecs: 1}}, + other: { + configOptions: {setParameter: {reshardingCriticalSectionTimeoutMillis: 24 * 60 * 60 * 1000}} + } +}); + +const dbName = jsTestName(); +const reshardCollName = "coll_reshard"; +const otherCollName = "coll_other"; + +const mongosDB = st.s.getDB(dbName); +const mongosReshardColl = mongosDB[reshardCollName]; + +const mongosOtherColl = mongosDB[otherCollName]; +const shardOtherColl = st.rs0.getPrimary().getDB(dbName)[otherCollName]; + +// Open a {showMigrationEvents:true} change stream directly on the shard, monitoring events on +// 'coll_other'. +const shardOtherCollCsCursor = + shardOtherColl.aggregate([{$changeStream: {showMigrationEvents: true}}]); + +// Drop, recreate, and shard the 'coll_reshard' collection. +assertDropAndRecreateCollection(mongosDB, reshardCollName); + +st.ensurePrimaryShard(dbName, st.rs0.name); +st.shardColl(mongosReshardColl, {a: 1}, {a: 50}); + +for (let i = 0; i < 100; ++i) { + assert.commandWorked(mongosReshardColl.insert({a: i, b: -i})); +} + +// Reshard the 'coll_reshard' collection on {b: 1}. +assert.commandWorked( + mongosDB.adminCommand({reshardCollection: mongosReshardColl.getFullName(), key: {b: 1}})); + +// Confirm that the change stream we opened on 'coll_other' only sees the sentinel 'insert' but does +// not see the earlier 'reshardBegin' or 'reshardDoneCatchUp' events on the 'coll_reshard' +// collection. +assert.commandWorked(mongosOtherColl.insert({_id: "sentinel_write"})); + +assert.soon(() => shardOtherCollCsCursor.hasNext()); +assert.eq(shardOtherCollCsCursor.next().operationType, "insert"); + +st.stop(); +})(); diff --git a/src/mongo/db/pipeline/change_stream_filter_helpers.cpp b/src/mongo/db/pipeline/change_stream_filter_helpers.cpp index 8ab33cce834..6792facbbd3 100644 --- a/src/mongo/db/pipeline/change_stream_filter_helpers.cpp +++ b/src/mongo/db/pipeline/change_stream_filter_helpers.cpp @@ -236,9 +236,11 @@ std::unique_ptr<MatchExpression> buildInternalOpFilter( } internalOpTypeOrBuilder.done(); + auto nsRegex = DocumentSourceChangeStream::getNsRegexForChangeStream(expCtx->ns); return MatchExpressionParser::parseAndNormalize(BSON("op" << "n" - << "$or" << internalOpTypeOrBuilder.arr()), + << "ns" << BSONRegEx(nsRegex) << "$or" + << internalOpTypeOrBuilder.arr()), expCtx); } |