Add recovery startup mode (#757)

* Add recovery startup mode

* Change error code to RecoveryMode
This commit is contained in:
Cooldude2606 authored and GitHub committed 2025-05-10 21:33:45 +01:00
1 parent 7cf13a8b3b
commit be071be8f2
7 files changed
+58

No files matched your search

+8
View File
@@ -270,6 +270,10 @@ async function initialize(): Promise<InitializeParameters> {
type: "boolean", nargs: 0, default: false,
describe: "Indicate that a process monitor will restart the controller on failure",
});
yargs.option("recovery", {
type: "boolean", nargs: 0, default: false,
describe: "Start the controller in recovery mode with all plugins disabled and hosts disconnected",
});
yargs.option("dev", { hidden: true, type: "boolean", nargs: 0 });
yargs.option("dev-plugin", { hidden: true, type: "array" });
})
@@ -313,6 +317,9 @@ async function initialize(): Promise<InitializeParameters> {
let shouldRun = false;
if (command === "run") {
logger.info(`Starting Clusterio controller ${version}`);
if (args.recovery) {
logger.warn("Controller recovery mode enabled. Some features will be disabled.");
}
shouldRun = true;
}
@@ -406,6 +413,7 @@ async function startup() {
controllerConfigPath,
controllerConfig,
Boolean(args.canRestart),
Boolean(args.recovery),
...await Controller.bootstrap(controllerConfig)
);
+14
View File
@@ -163,6 +163,11 @@ export default class Controller {
* will restart the controller on non-zero exit codes.
*/
public canRestart: boolean = false,
/**
* If true indicates the controller is in recovery mode and should
* disable certain actions such as loading plugins or connecting to hosts
*/
public recoveryMode: boolean = false,
public systems = new lib.SubscribableDatastore<lib.SystemInfo>(),
/** Mapping of host id to host info */
public hosts = new lib.SubscribableDatastore<HostInfo>(),
@@ -538,6 +543,10 @@ export default class Controller {
clearInterval(this.autosaveInterval);
this.autosaveInterval = undefined;
}
if (this.recoveryMode) {
logger.warn("Recovery | autosaving disabled");
return;
}
const autosaveIntervalSeconds = this.config.get("controller.autosave_interval");
if (autosaveIntervalSeconds > 0) {
this.autosaveInterval = setInterval(this.saveData.bind(this), autosaveIntervalSeconds * 1000);
@@ -1058,6 +1067,11 @@ export default class Controller {
continue;
}
if (this.recoveryMode) {
logger.warn(`Recovery | force disabled plugin ${pluginInfo.name}`);
continue;
}
let ControllerPluginClass = BaseControllerPlugin;
try {
if (pluginInfo.controllerEntrypoint) {
+7
View File
@@ -239,6 +239,13 @@ ${err.stack}`
}
async registerHost(data: lib.RegisterHostData, socket: WebSocket, req: IncomingMessage) {
if (this.controller.recoveryMode) {
logger.warn(`Recovery | rejected host connection attempt for ${this.remoteAddr(req)}`);
wsRejectedConnectionsCounter.inc();
socket.close(lib.ConnectionClosed.RecoveryMode, "Connection Refused: Controller in recovery mode");
return;
}
try {
let tokenPayload = jwt.verify(
data.token,