run checks periodically, auto restart services

This commit is contained in:
Lea 2023-04-29 08:25:54 +02:00
parent 0ed1c11866
commit 13d526163f
Signed by: Lea
GPG key ID: 1BAFFE8347019C42

View file

@ -2,10 +2,11 @@ import Revolt from 'revolt.js';
import Discord from 'discord.js'; import Discord from 'discord.js';
import Express from 'express'; import Express from 'express';
import { config } from 'dotenv'; import { config } from 'dotenv';
import { exec } from 'child_process';
config(); config();
const { DISCORD_TOKEN, REVOLT_TOKEN, DISCORD_CHANNEL, REVOLT_CHANNEL, PORT } = process.env; const { DISCORD_TOKEN, REVOLT_TOKEN, DISCORD_CHANNEL, REVOLT_CHANNEL, PORT, RESTART_COMMAND_BOT, RESTART_COMMAND_BRIDGE } = process.env;
if (!DISCORD_TOKEN) throw '$DISCORD_TOKEN not set'; if (!DISCORD_TOKEN) throw '$DISCORD_TOKEN not set';
if (!REVOLT_TOKEN) throw '$REVOLT_TOKEN not set'; if (!REVOLT_TOKEN) throw '$REVOLT_TOKEN not set';
@ -20,6 +21,9 @@ const clients = {
revolt: new Revolt.Client({ autoReconnect: true, pongTimeout: 30, onPongTimeout: 'RECONNECT' }), revolt: new Revolt.Client({ autoReconnect: true, pongTimeout: 30, onPongTimeout: 'RECONNECT' }),
} }
let currentValue: Awaited<ReturnType<typeof periodicCheck>>|null = null;
let restarting = { bot: false, bridge: false };
const app = Express(); const app = Express();
app.listen(PORT, () => console.log('Listening on :' + PORT)); app.listen(PORT, () => console.log('Listening on :' + PORT));
@ -30,15 +34,32 @@ clients.discord.on('ready', () => console.log('Discord ready'));
clients.revolt.on('ready', () => console.log('Revolt ready')); clients.revolt.on('ready', () => console.log('Revolt ready'));
app.get('/healthcheck', async (req: Express.Request, res: Express.Response) => { app.get('/healthcheck', async (req: Express.Request, res: Express.Response) => {
console.log('Health check request received');
if (!currentValue) {
console.log('No health check result stored yet, running checks');
await periodicCheck();
}
res.status(currentValue!.status).send(currentValue);
});
const periodicCheck = async () => {
console.log('Running periodic check');
const now = new Date().toISOString();
const [ botStatus, bridgeStatusDiscord, bridgeStatusRevolt ] = await Promise.all([ const [ botStatus, bridgeStatusDiscord, bridgeStatusRevolt ] = await Promise.all([
retry(checkBot, 3), retry(checkBot, 3),
retry(checkBridgeDiscord, 3), retry(checkBridgeDiscord, 3),
retry(checkBridgeRevolt, 3), retry(checkBridgeRevolt, 3),
]); ]);
let statusCode = (botStatus && bridgeStatusDiscord && bridgeStatusRevolt) ? 200 : 503; if (botStatus) restarting.bot = false;
let response = { if (bridgeStatusDiscord && bridgeStatusRevolt) restarting.bridge = false;
const statusCode = (botStatus && bridgeStatusDiscord && bridgeStatusRevolt) ? 200 : 503;
const response = {
status: statusCode, status: statusCode,
checkedOn: now,
ready: { ready: {
discord: !!clients.discord.readyAt, discord: !!clients.discord.readyAt,
revolt: !!clients.revolt.websocket.ready, revolt: !!clients.revolt.websocket.ready,
@ -50,8 +71,43 @@ app.get('/healthcheck', async (req: Express.Request, res: Express.Response) => {
}, },
}; };
res.status(statusCode).send(response); currentValue = response;
}); runRestarts(response).catch(e => console.log(e)); // Explicitly do not await this
return response;
}
const runRestarts = async (status: Awaited<ReturnType<typeof periodicCheck>>) => {
if (!status.watchdog.bot && !restarting.bot && RESTART_COMMAND_BOT) {
console.log('Restarting bot');
try {
restarting.bot = true;
const result = exec(RESTART_COMMAND_BOT!);
result.stdout?.on('data', data => console.log(data));
result.stderr?.on('data', data => console.log(data));
} catch(e) {
console.log(e);
}
}
if ((!status.watchdog.bridgeDiscord || !status.watchdog.bridgeRevolt) && !restarting.bridge && RESTART_COMMAND_BRIDGE) {
console.log('Restarting bridge');
try {
restarting.bridge = true;
const result = exec(RESTART_COMMAND_BRIDGE!);
result.stdout?.on('data', data => console.log(data));
result.stderr?.on('data', data => console.log(data));
} catch(e) {
console.log(e);
}
}
}
setInterval(async () => {
if (clients.discord.readyAt && clients.revolt.user) {
await periodicCheck();
}
else console.log('Cannot run periodic check as clients aren\'t ready yet');
}, 30000);
const checkBot = (): Promise<boolean> => new Promise(async (resolve, _reject) => { const checkBot = (): Promise<boolean> => new Promise(async (resolve, _reject) => {
const id = Math.round(Math.random() * 1000000); const id = Math.round(Math.random() * 1000000);