mirror of https://github.com/mongodb/mongo
133 lines
5.7 KiB
JavaScript
133 lines
5.7 KiB
JavaScript
/**
|
|
* Tests that the change stream with 'fullDocument: updateLookup' option performs the lookup only by
|
|
* nss by default and does an additional collection UUID check when
|
|
* 'matchCollectionUUIDForUpdateLookup: true' option is set.
|
|
*/
|
|
import {assertCreateCollection, assertDropCollection} from "jstests/libs/collection_drop_recreate.js";
|
|
import {FixtureHelpers} from "jstests/libs/fixture_helpers.js";
|
|
import {ChangeStreamTest} from "jstests/libs/query/change_stream_util.js";
|
|
|
|
function assertUpdateLookupResultBeforeOp(op, changeStreamOptions) {
|
|
jsTest.log(
|
|
`Running change stream with update lookup test after '${op}' occurred with ${tojson(changeStreamOptions)}`,
|
|
);
|
|
|
|
const collNameA = "collA";
|
|
const collNameB = "collB";
|
|
let cst;
|
|
|
|
function tearDown() {
|
|
cst.cleanUp();
|
|
assertDropCollection(db, collNameA);
|
|
assertDropCollection(db, collNameB);
|
|
}
|
|
|
|
assertCreateCollection(db, collNameA);
|
|
cst = new ChangeStreamTest(db);
|
|
|
|
let cursor = cst.startWatchingChanges({
|
|
pipeline: [{$changeStream: {...changeStreamOptions, fullDocument: "updateLookup"}}],
|
|
collection: collNameA,
|
|
});
|
|
|
|
// Insert 'doc' into 'collA' and ensure it is seen in the change stream.
|
|
const doc = {_id: 0, a: 1};
|
|
assert.commandWorked(db.getCollection(collNameA).insert(doc));
|
|
let expected = {
|
|
documentKey: {_id: doc._id},
|
|
fullDocument: doc,
|
|
ns: {db: "test", coll: collNameA},
|
|
operationType: "insert",
|
|
};
|
|
cst.assertNextChangesEqual({cursor: cursor, expectedChanges: [expected]});
|
|
|
|
// Update the 'doc' in order to generate the update event.
|
|
assert.commandWorked(db.getCollection(collNameA).update({_id: doc._id}, {$inc: {a: 1}}));
|
|
const updatedDocInCollA = {...doc, a: 2};
|
|
|
|
// In case where a change stream is opened with the 'checkUUIDOnUpdateLookup' flag set to true,
|
|
// no 'fullDocument' should be returned to the user as the collection on which 'updateLookup'
|
|
// has been performed has a different UUID from the collection on which change stream has been
|
|
// opened. In case of the flag being set to false or not present return the latest document on
|
|
// the collection with the same name.
|
|
let expectedFullDocument;
|
|
if (op === "renameCollection") {
|
|
// Rename collection collA -> collB.
|
|
assert.commandWorked(db.getCollection(collNameA).renameCollection(collNameB));
|
|
|
|
// Create new collection with the old name, "collA", (yet UUID will be different) and insert
|
|
// document with the same id.
|
|
assertCreateCollection(db, collNameA);
|
|
const newDocInNewCollA = {
|
|
...doc,
|
|
b: "extra field in the new document in the new collection",
|
|
};
|
|
assert.commandWorked(db.getCollection(collNameA).insert(newDocInNewCollA));
|
|
expectedFullDocument = changeStreamOptions.matchCollectionUUIDForUpdateLookup ? null : newDocInNewCollA;
|
|
} else if (op === "shardCollection") {
|
|
if (FixtureHelpers.isSharded(db.getCollection(collNameA))) {
|
|
jsTest.log("Early exit, because collection 'collA' is already sharded");
|
|
tearDown();
|
|
return;
|
|
}
|
|
|
|
// Sharding the unsharded collection does not change its UUID, therefore regardless of
|
|
// 'matchCollectionUUIDForUpdateLookup' being set or not, we should observe the
|
|
// 'updatedDocInCollA' on updateLookup.
|
|
assert.commandWorked(
|
|
db.adminCommand({
|
|
shardCollection: db.getCollection(collNameA).getFullName(),
|
|
key: {_id: 1},
|
|
numInitialChunks: 2,
|
|
}),
|
|
);
|
|
expectedFullDocument = updatedDocInCollA;
|
|
} else if (op === "reshardCollection") {
|
|
if (!FixtureHelpers.isSharded(db.getCollection(collNameA))) {
|
|
jsTest.log("Early exit, because collection 'collA' is not sharded");
|
|
tearDown();
|
|
return;
|
|
}
|
|
|
|
// Reshard the collection in order to generate the new collection with the same name, but
|
|
// different UUID.
|
|
assert.commandWorked(
|
|
db.adminCommand({
|
|
reshardCollection: db.getCollection(collNameA).getFullName(),
|
|
key: {_id: 1},
|
|
numInitialChunks: 2,
|
|
}),
|
|
);
|
|
expectedFullDocument = changeStreamOptions.matchCollectionUUIDForUpdateLookup ? null : updatedDocInCollA;
|
|
}
|
|
|
|
// If this test is running with secondary read preference, it's necessary for the update
|
|
// to propagate to all secondary nodes and be available for majority reads before we can
|
|
// assume looking up the document will succeed.
|
|
FixtureHelpers.awaitLastOpCommitted(db);
|
|
|
|
expected = {
|
|
documentKey: {_id: doc._id},
|
|
fullDocument: expectedFullDocument,
|
|
ns: {db: "test", coll: collNameA},
|
|
operationType: "update",
|
|
};
|
|
cst.assertNextChangesEqual({cursor: cursor, expectedChanges: [expected]});
|
|
|
|
tearDown();
|
|
}
|
|
|
|
assertUpdateLookupResultBeforeOp("renameCollection", {});
|
|
assertUpdateLookupResultBeforeOp("renameCollection", {matchCollectionUUIDForUpdateLookup: false});
|
|
assertUpdateLookupResultBeforeOp("renameCollection", {matchCollectionUUIDForUpdateLookup: true});
|
|
|
|
if (FixtureHelpers.isMongos(db)) {
|
|
assertUpdateLookupResultBeforeOp("shardCollection", {});
|
|
assertUpdateLookupResultBeforeOp("shardCollection", {matchCollectionUUIDForUpdateLookup: false});
|
|
assertUpdateLookupResultBeforeOp("shardCollection", {matchCollectionUUIDForUpdateLookup: true});
|
|
|
|
assertUpdateLookupResultBeforeOp("reshardCollection", {});
|
|
assertUpdateLookupResultBeforeOp("reshardCollection", {matchCollectionUUIDForUpdateLookup: false});
|
|
assertUpdateLookupResultBeforeOp("reshardCollection", {matchCollectionUUIDForUpdateLookup: true});
|
|
}
|