run checks periodically, auto restart services
This commit is contained in:
parent
0ed1c11866
commit
13d526163f
66
src/index.ts
66
src/index.ts
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue