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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
/**
* Tests running the update command on a time-series collection with concurrent modifications to the
* collection.
* @tags: [
* assumes_unsharded_collection, # TODO SERVER-60233: Remove this tag.
* does_not_support_stepdowns,
* does_not_support_transactions,
* # $currentOp can't run with a readConcern other than 'local'.
* assumes_read_concern_unchanged,
* # This test only synchronizes updates on the primary.
* assumes_read_preference_unchanged,
* # Fail points in this test do not exist on mongos.
* assumes_against_mongod_not_mongos,
* uses_parallel_shell,
* ]
*/
(function() {
"use strict";
load("jstests/core/timeseries/libs/timeseries.js");
load("jstests/libs/curop_helpers.js");
load("jstests/libs/parallel_shell_helpers.js");
if (!TimeseriesTest.timeseriesUpdatesAndDeletesEnabled(db.getMongo())) {
jsTestLog("Skipping test because the time-series updates and deletes feature flag is disabled");
return;
}
const timeFieldName = "time";
const metaFieldName = "tag";
const collName = 't';
const dbName = jsTestName();
const testCases = {
DROP_COLLECTION: 0,
REPLACE_COLLECTION: 1,
REPLACE_METAFIELD: 2
};
const validateUpdateIndex = (initialDocList,
updateList,
testType,
failCode,
newMetaField = null) => {
const testDB = db.getSiblingDB(dbName);
const awaitTestUpdate = startParallelShell(funWithArgs(
function(
dbName, collName, timeFieldName, metaFieldName, initialDocList, updateList, failCode) {
const testDB = db.getSiblingDB(dbName);
const coll = testDB.getCollection(collName);
assert.commandWorked(testDB.createCollection(
coll.getName(),
{timeseries: {timeField: timeFieldName, metaField: metaFieldName}}));
assert.commandWorked(coll.insert(initialDocList));
assert.commandWorked(testDB.adminCommand(
{configureFailPoint: "hangDuringBatchUpdate", mode: "alwaysOn"}));
assert.commandFailedWithCode(
testDB.runCommand({update: coll.getName(), updates: updateList}), failCode);
coll.drop();
},
dbName,
collName,
timeFieldName,
metaFieldName,
initialDocList,
updateList,
failCode));
const coll = testDB.getCollection(collName);
const childOp = waitForCurOpByFailPoint(testDB, coll.getFullName(), "hangDuringBatchUpdate")[0];
// Drop the collection in all test cases.
assert(coll.drop());
switch (testType) {
case testCases.REPLACE_COLLECTION:
assert.commandWorked(testDB.createCollection(coll.getName()));
break;
case testCases.REPLACE_METAFIELD:
assert.commandWorked(testDB.createCollection(
coll.getName(), {timeseries: {timeField: timeFieldName, metaField: newMetaField}}));
break;
}
assert.commandWorked(
testDB.adminCommand({configureFailPoint: "hangDuringBatchUpdate", mode: "off"}));
// Wait for testUpdate to finish.
awaitTestUpdate();
};
const docs = [
{_id: 0, [timeFieldName]: ISODate(), [metaFieldName]: {a: "A"}, "measurement": {"m": 1}},
{_id: 1, [timeFieldName]: ISODate(), [metaFieldName]: {a: "A"}, "measurement": {"n": 3}},
{_id: 2, [timeFieldName]: ISODate(), [metaFieldName]: {a: "B"}},
];
// Attempt to update a document in a collection that has been dropped.
validateUpdateIndex(
docs,
[{q: {[metaFieldName]: {a: "B"}}, u: {$set: {[metaFieldName]: {c: "C"}}}, multi: true}],
testCases.DROP_COLLECTION,
ErrorCodes.NamespaceNotFound);
// Attempt to update a document in a collection that has been replaced with a non-time-series
// collection.
validateUpdateIndex(
docs,
[{q: {[metaFieldName]: {a: "B"}}, u: {$set: {[metaFieldName]: {c: "C"}}}, multi: true}],
testCases.REPLACE_COLLECTION,
ErrorCodes.NamespaceNotFound);
// Attempt to update a document in a collection that has been replaced with a new time-series
// collection with a different metaField.
validateUpdateIndex(
docs,
[{q: {[metaFieldName]: {a: "B"}}, u: {$set: {[metaFieldName]: {c: "C"}}}, multi: true}],
testCases.REPLACE_METAFIELD,
ErrorCodes.InvalidOptions,
"meta");
})();
|