mirror of https://github.com/mongodb/mongo
132 lines
5.4 KiB
JavaScript
132 lines
5.4 KiB
JavaScript
/**
|
|
* Utilities for turning on/off and waiting for fail points.
|
|
*/
|
|
|
|
import {isMongos} from "jstests/concurrency/fsm_workload_helpers/server_types.js";
|
|
|
|
export var configureFailPoint;
|
|
|
|
export var configureFailPointForRS;
|
|
export var kDefaultWaitForFailPointTimeout;
|
|
|
|
(function () {
|
|
if (configureFailPoint) {
|
|
return; // Protect against this file being double-loaded.
|
|
}
|
|
|
|
// This table is the opposite to failPointRenameTable below. It maps from a fail point name to
|
|
// either a router-specific or a shard-specific version, based on the type of connection that is
|
|
// passed to configureFailPoint.
|
|
const failPointRouterShardRenameTable = {
|
|
"waitInFindBeforeMakingBatch": {
|
|
router: "routerWaitInFindBeforeMakingBatch",
|
|
shard: "shardWaitInFindBeforeMakingBatch",
|
|
},
|
|
};
|
|
|
|
function getActualFailPointName(conn, failPointName) {
|
|
const names = failPointRouterShardRenameTable[failPointName];
|
|
if (!names) {
|
|
return failPointName;
|
|
}
|
|
const isRouter = typeof conn.getMongo == "function" ? isMongos(conn) : isMongos(conn.getDB("admin"));
|
|
return isRouter ? names.router : names.shard;
|
|
}
|
|
|
|
function getShardFailPointName(failPointName) {
|
|
const names = failPointRouterShardRenameTable[failPointName];
|
|
if (!names) {
|
|
return failPointName;
|
|
}
|
|
return names.shard;
|
|
}
|
|
|
|
kDefaultWaitForFailPointTimeout = 10 * 60 * 1000;
|
|
|
|
configureFailPoint = function (conn, failPointName, data = {}, failPointMode = "alwaysOn") {
|
|
failPointName = getActualFailPointName(conn, failPointName);
|
|
|
|
const res = sh.assertRetryableCommandWorkedOrFailedWithCodes(() => {
|
|
return conn.adminCommand({configureFailPoint: failPointName, mode: failPointMode, data: data});
|
|
}, "Timed out enabling fail point " + failPointName);
|
|
|
|
return {
|
|
conn: conn,
|
|
failPointName: failPointName,
|
|
timesEntered: res.count,
|
|
wait: function ({
|
|
maxTimeMS = kDefaultWaitForFailPointTimeout,
|
|
timesEntered = 1,
|
|
expectedErrorCodes = [],
|
|
} = {}) {
|
|
// Can only be called once because this function does not keep track of the
|
|
// number of times the fail point is entered between the time it returns
|
|
// and the next time it gets called.
|
|
// This function has three possible outcomes:
|
|
//
|
|
// 1) Returns true when the failpoint was hit.
|
|
// 2) Returns false when the command returned one of the expected error codes.
|
|
// 3) Otherwise, this throws for an unexpected error.
|
|
let res = sh.assertRetryableCommandWorkedOrFailedWithCodes(
|
|
() => {
|
|
return conn.adminCommand({
|
|
waitForFailPoint: failPointName,
|
|
timesEntered: this.timesEntered + timesEntered,
|
|
maxTimeMS: maxTimeMS,
|
|
});
|
|
},
|
|
"Timed out waiting for failpoint " + failPointName,
|
|
expectedErrorCodes,
|
|
);
|
|
return res !== undefined && res["ok"] === 1;
|
|
},
|
|
waitWithTimeout: function (timeoutMS) {
|
|
// This function has three possible outcomes:
|
|
//
|
|
// 1) Returns true when the failpoint was hit.
|
|
// 2) Returns false when the command returned a `MaxTimeMSExpired` response.
|
|
// 3) Otherwise, this throws for an unexpected error.
|
|
let res = sh.assertRetryableCommandWorkedOrFailedWithCodes(
|
|
() => {
|
|
return conn.adminCommand({
|
|
waitForFailPoint: failPointName,
|
|
timesEntered: this.timesEntered + 1,
|
|
maxTimeMS: timeoutMS,
|
|
});
|
|
},
|
|
"Timed out waiting for failpoint " + failPointName,
|
|
[ErrorCodes.MaxTimeMSExpired],
|
|
);
|
|
return res !== undefined && res["ok"] === 1;
|
|
},
|
|
off: function () {
|
|
sh.assertRetryableCommandWorkedOrFailedWithCodes(() => {
|
|
return conn.adminCommand({configureFailPoint: failPointName, mode: "off"});
|
|
}, "Timed out disabling fail point " + failPointName);
|
|
},
|
|
};
|
|
};
|
|
|
|
configureFailPointForRS = function (conns, failPointName, data = {}, failPointMode = "alwaysOn") {
|
|
failPointName = getShardFailPointName(failPointName);
|
|
|
|
conns.forEach((conn) => {
|
|
sh.assertRetryableCommandWorkedOrFailedWithCodes(() => {
|
|
return conn.adminCommand({configureFailPoint: failPointName, mode: failPointMode, data: data});
|
|
}, "Timed out setting failpoint " + failPointName);
|
|
});
|
|
|
|
return {
|
|
conns: conns,
|
|
failPointName: failPointName,
|
|
off: function () {
|
|
conns.forEach((conn) => {
|
|
sh.assertRetryableCommandWorkedOrFailedWithCodes(() => {
|
|
return conn.adminCommand({configureFailPoint: failPointName, mode: "off"});
|
|
}, "Timed out disabling fail point " + failPointName);
|
|
});
|
|
},
|
|
};
|
|
};
|
|
})();
|