1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
/**
* Tests that the post-image of an update which occurred while the collection was unsharded can
* still be looked up after the collection becomes sharded. Exercises the fix for SERVER-44484.
* @tags: [
* uses_change_streams,
* ]
*/
(function() {
"use strict";
// Start a new sharded cluster with 2 nodes and obtain references to the test DB and collection.
const st = new ShardingTest({
shards: 2,
mongos: 1,
rs: {nodes: 1, setParameter: {periodicNoopIntervalSecs: 1, writePeriodicNoops: true}}
});
const mongosDB = st.s0.getDB(jsTestName());
const mongosColl = mongosDB.test;
// Open a change stream on the unsharded collection.
let csCur = mongosColl.watch([], {fullDocument: "updateLookup"});
// Insert one document with a known _id into the unsharded collection, and obtain its resume token.
assert.commandWorked(mongosColl.insert({_id: 0, a: -100}));
assert.soon(() => csCur.hasNext());
const insertEvent = csCur.next();
assert.eq(insertEvent.operationType, "insert");
// Update the document and confirm that we can see the updateLookup fullDocument.
assert.commandWorked(mongosColl.update({_id: 0}, {$set: {updated: true}}));
assert.soon(() => csCur.hasNext());
let updateEvent = csCur.next();
assert.eq(updateEvent.operationType, "update");
assert.docEq({_id: 0, a: -100, updated: true}, updateEvent.fullDocument);
// Now shard the collection on {a: 1} and move the upper chunk to the other shard.
assert.commandWorked(mongosColl.createIndex({a: 1}));
st.shardColl(mongosColl, {a: 1}, {a: 0}, {a: 0});
// Resume a change stream just after the initial insert. We expect the update lookup to succeed,
// despite the fact that only the _id and not the entire documentKey was recorded in the oplog.
csCur = mongosColl.watch([], {resumeAfter: insertEvent._id, fullDocument: "updateLookup"});
assert.soon(() => csCur.hasNext());
updateEvent = csCur.next();
assert.eq(updateEvent.operationType, "update");
assert.docEq({_id: 0, a: -100, updated: true}, updateEvent.fullDocument);
// Insert a second document with the same _id on the second shard.
assert.commandWorked(mongosColl.insert({_id: 0, a: 100}));
// Now that two documents with the same _id are present, the update lookup fails.
csCur = mongosColl.watch([], {resumeAfter: insertEvent._id, fullDocument: "updateLookup"});
assert.soon(() => {
try {
assert.eq(csCur.hasNext(), false, () => tojson(csCur.next()));
return false;
} catch (ex) {
assert.eq(ex.code, ErrorCodes.ChangeStreamFatalError, () => tojson({originalError: ex}));
return true;
}
});
st.stop();
})();
|