Hopefully prevent danging child processes Reduce unnecessary db calls in moderation manager
This commit is contained in:
parent
5f07fd3e15
commit
a3e6793632
@ -210,14 +210,6 @@ class DiscordClient extends Client
|
|||||||
this.emit('invalidRequestWarning', ...args);
|
this.emit('invalidRequestWarning', ...args);
|
||||||
});
|
});
|
||||||
|
|
||||||
// this.once('ready', () => {
|
|
||||||
// this._setActivity();
|
|
||||||
|
|
||||||
// setInterval(() => {
|
|
||||||
// this._setActivity();
|
|
||||||
// }, 1800000); // I think this is 30 minutes. I could be wrong.
|
|
||||||
// });
|
|
||||||
|
|
||||||
this.#loadEevents();
|
this.#loadEevents();
|
||||||
|
|
||||||
// process.on('uncaughtException', (err) => {
|
// process.on('uncaughtException', (err) => {
|
||||||
@ -230,7 +222,13 @@ class DiscordClient extends Client
|
|||||||
});
|
});
|
||||||
|
|
||||||
process.on('message', this.#handleMessage.bind(this));
|
process.on('message', this.#handleMessage.bind(this));
|
||||||
process.on('SIGINT', () => this.shutdown());
|
process.on('SIGINT', () => this.logger.info('Received SIGINT'));
|
||||||
|
process.on('SIGTERM', () => this.logger.info('Received SIGTERM'));
|
||||||
|
process.on('disconnect', () =>
|
||||||
|
{
|
||||||
|
this.logger.info('Process disconnected from parent for some reason, exiting');
|
||||||
|
this.shutdown(1);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async build ()
|
async build ()
|
||||||
@ -271,7 +269,7 @@ class DiscordClient extends Client
|
|||||||
this.#activityInterval = setInterval(() =>
|
this.#activityInterval = setInterval(() =>
|
||||||
{
|
{
|
||||||
this.setActivity();
|
this.setActivity();
|
||||||
}, Util.random(5, 10) * 60 * 60 * 1000);
|
}, Util.random(5, 10) * 60 * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#built = true;
|
this.#built = true;
|
||||||
@ -296,6 +294,8 @@ class DiscordClient extends Client
|
|||||||
// Handle misc. messages.
|
// Handle misc. messages.
|
||||||
if (message._mEvalResult)
|
if (message._mEvalResult)
|
||||||
this.evalResult(message);
|
this.evalResult(message);
|
||||||
|
if (message._shutdown)
|
||||||
|
this.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
@ -397,6 +397,10 @@ class DiscordClient extends Client
|
|||||||
this.user?.setActivity(`${userCount} users`, { type: ActivityType.Listening });
|
this.user?.setActivity(`${userCount} users`, { type: ActivityType.Listening });
|
||||||
},
|
},
|
||||||
async () =>
|
async () =>
|
||||||
|
{
|
||||||
|
this.user?.setActivity('out for troublemakers', { type: ActivityType.Watching });
|
||||||
|
},
|
||||||
|
async () =>
|
||||||
{
|
{
|
||||||
this.user?.setActivity('for /help', { type: ActivityType.Listening });
|
this.user?.setActivity('for /help', { type: ActivityType.Listening });
|
||||||
}
|
}
|
||||||
|
@ -185,9 +185,9 @@ class CallbackManager implements Initialisable
|
|||||||
*
|
*
|
||||||
* @async
|
* @async
|
||||||
* @param {string} id
|
* @param {string} id
|
||||||
* @returns {*}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
async removeCallback (id: string)
|
async removeCallback (id: string): Promise<void>
|
||||||
{
|
{
|
||||||
await this.storage.deleteOne({ _id: id });
|
await this.storage.deleteOne({ _id: id });
|
||||||
const timeout = this.#timeouts.get(id);
|
const timeout = this.#timeouts.get(id);
|
||||||
|
@ -591,9 +591,9 @@ class ModerationManager implements Initialisable, CallbackClient
|
|||||||
return responses;
|
return responses;
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleCallback (id: string)
|
async handleCallback (_id: string, infraction: InfractionJSON)
|
||||||
{
|
{
|
||||||
const infraction = await this.#client.mongodb.infractions.findOne({ id });
|
// const infraction = await this.#client.mongodb.infractions.findOne({ id });
|
||||||
if (!infraction)
|
if (!infraction)
|
||||||
return;
|
return;
|
||||||
this.#logger.debug(`Infraction callback: ${infraction.id} (${infraction.type})`);
|
this.#logger.debug(`Infraction callback: ${infraction.id} (${infraction.type})`);
|
||||||
@ -667,7 +667,7 @@ class ModerationManager implements Initialisable, CallbackClient
|
|||||||
if (expiresAt - currentDate <= 0)
|
if (expiresAt - currentDate <= 0)
|
||||||
{
|
{
|
||||||
this.#logger.debug(`Expired infraction:\n${inspect(infraction)}`);
|
this.#logger.debug(`Expired infraction:\n${inspect(infraction)}`);
|
||||||
return this.handleCallback(infraction.id);
|
return this.handleCallback(infraction.id, infraction);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#logger.debug(`Creating infraction callback for ${infraction.id} (${infraction.type}), expiring in ${Util.humanise(duration / 1000)}`);
|
this.#logger.debug(`Creating infraction callback for ${infraction.id} (${infraction.type}), expiring in ${Util.humanise(duration / 1000)}`);
|
||||||
|
@ -1,27 +1,47 @@
|
|||||||
import { EventEmitter } from 'node:events';
|
import {
|
||||||
import { inspect } from 'node:util';
|
EventEmitter
|
||||||
|
} from 'node:events';
|
||||||
|
|
||||||
|
import {
|
||||||
|
inspect
|
||||||
|
} from 'node:util';
|
||||||
|
|
||||||
|
import {
|
||||||
|
existsSync
|
||||||
|
} from 'node:fs';
|
||||||
|
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
|
|
||||||
import { CommandsDef, IPCMessage } from '../../@types/Shared.js';
|
import {
|
||||||
import { BroadcastEvalOptions, ShardMethod, ShardingOptions } from '../../@types/Shard.js';
|
CommandsDef,
|
||||||
import { ControllerOptions } from '../../@types/Controller.js';
|
IPCMessage
|
||||||
|
} from '../../@types/Shared.js';
|
||||||
|
|
||||||
import { MasterLogger } from '@navy.gif/logger';
|
import {
|
||||||
import { Collection } from 'discord.js';
|
BroadcastEvalOptions,
|
||||||
|
ShardMethod,
|
||||||
|
ShardingOptions
|
||||||
|
} from '../../@types/Shard.js';
|
||||||
|
|
||||||
|
import {
|
||||||
|
ControllerOptions
|
||||||
|
} from '../../@types/Controller.js';
|
||||||
|
|
||||||
|
import {
|
||||||
|
MasterLogger
|
||||||
|
} from '@navy.gif/logger';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Collection
|
||||||
|
} from 'discord.js';
|
||||||
|
|
||||||
// Available for evals
|
// Available for evals
|
||||||
import ClientUtils from './ClientUtils.js';
|
import ClientUtils from './ClientUtils.js';
|
||||||
import Metrics from './Metrics.js';
|
import Metrics from './Metrics.js';
|
||||||
// import ApiClientUtil from './ApiClientUtil.js';
|
// import ApiClientUtil from './ApiClientUtil.js';
|
||||||
import SlashCommandManager from './rest/SlashCommandManager.js';
|
import SlashCommandManager from './SlashCommandManager.js';
|
||||||
import { Shard } from './shard/index.js';
|
|
||||||
import { existsSync } from 'node:fs';
|
|
||||||
import Util from '../utilities/Util.js';
|
import Util from '../utilities/Util.js';
|
||||||
|
import Shard from './Shard.js';
|
||||||
// Placeholder
|
|
||||||
type GalacticAPI = {
|
|
||||||
init: () => Promise<void>
|
|
||||||
}
|
|
||||||
|
|
||||||
class Controller extends EventEmitter
|
class Controller extends EventEmitter
|
||||||
{
|
{
|
||||||
@ -39,7 +59,6 @@ class Controller extends EventEmitter
|
|||||||
#readyAt: number | null;
|
#readyAt: number | null;
|
||||||
#built: boolean;
|
#built: boolean;
|
||||||
|
|
||||||
#api?: GalacticAPI;
|
|
||||||
clientUtils: typeof ClientUtils;
|
clientUtils: typeof ClientUtils;
|
||||||
|
|
||||||
constructor (options: ControllerOptions, version: string)
|
constructor (options: ControllerOptions, version: string)
|
||||||
@ -92,28 +111,7 @@ class Controller extends EventEmitter
|
|||||||
async build ()
|
async build ()
|
||||||
{
|
{
|
||||||
const start = Date.now();
|
const start = Date.now();
|
||||||
// const API = this._options.api.load ? await import('/Documents/My programs/GBot/api/index.js')
|
|
||||||
// .catch(() => this.logger.warn(`Error importing API files, continuing without`)) : null;
|
|
||||||
|
|
||||||
// let API = null;
|
|
||||||
// if (this.#options.api.load)
|
|
||||||
// API = await import('../../api/index.js').catch(() => this.#logger.warn(`Error importing API files, continuing without`));
|
|
||||||
// if (API) {
|
|
||||||
// this.#logger.info('Booting up API');
|
|
||||||
// const { default: APIManager } = API;
|
|
||||||
// this.#api = new APIManager(this, this.#options.api) as GalacticAPI;
|
|
||||||
// await this.#api.init();
|
|
||||||
// const now = Date.now();
|
|
||||||
// this.#logger.info(`API ready. Took ${now - start} ms`);
|
|
||||||
// start = now;
|
|
||||||
// }
|
|
||||||
|
|
||||||
this.#logger.status('Starting bot shards');
|
this.#logger.status('Starting bot shards');
|
||||||
// await this.shardingManager.spawn().catch((error) => {
|
|
||||||
// this.#logger.error(`Fatal error during shard spawning:\n${error.stack || inspect(error)}`);
|
|
||||||
// // eslint-disable-next-line no-process-exit
|
|
||||||
// process.exit(); // Prevent a boot loop when shards die due to an error in the client
|
|
||||||
// });
|
|
||||||
|
|
||||||
const { totalShards, token } = this.#shardingOptions;
|
const { totalShards, token } = this.#shardingOptions;
|
||||||
let shardCount = 0;
|
let shardCount = 0;
|
||||||
@ -133,7 +131,6 @@ class Controller extends EventEmitter
|
|||||||
throw new TypeError('Amount of shards must be an integer.');
|
throw new TypeError('Amount of shards must be an integer.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// const promises = [];
|
|
||||||
const retry: Shard[] = [];
|
const retry: Shard[] = [];
|
||||||
for (let i = 0; i < shardCount; i++)
|
for (let i = 0; i < shardCount; i++)
|
||||||
{
|
{
|
||||||
@ -148,9 +145,9 @@ class Controller extends EventEmitter
|
|||||||
this.logger.info('Retrying shard', i);
|
this.logger.info('Retrying shard', i);
|
||||||
retry.push(shard);
|
retry.push(shard);
|
||||||
}
|
}
|
||||||
// promises.push();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Retry failed spawns
|
||||||
for (const shard of retry)
|
for (const shard of retry)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -163,8 +160,6 @@ class Controller extends EventEmitter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// await Promise.all(promises);
|
|
||||||
|
|
||||||
this.#logger.status(`Shards spawned, spawned ${this.#shards.size} shards. Took ${Date.now() - start} ms`);
|
this.#logger.status(`Shards spawned, spawned ${this.#shards.size} shards. Took ${Date.now() - start} ms`);
|
||||||
|
|
||||||
this.#built = true;
|
this.#built = true;
|
||||||
@ -173,12 +168,11 @@ class Controller extends EventEmitter
|
|||||||
|
|
||||||
async shutdown ()
|
async shutdown ()
|
||||||
{
|
{
|
||||||
this.logger.info('Received SIGINT, shutting down');
|
this.logger.info('Received SIGINT or SIGTERM, shutting down');
|
||||||
setTimeout(process.exit, 90_000);
|
setTimeout(process.exit, 90_000);
|
||||||
const promises = this.shards
|
const promises = this.shards
|
||||||
.filter(shard => shard.ready)
|
.filter(shard => shard.ready)
|
||||||
.map(shard => shard.awaitShutdown()
|
.map(shard => shard.kill());
|
||||||
.then(() => shard.removeAllListeners()));
|
|
||||||
if (promises.length)
|
if (promises.length)
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
this.logger.status('Shutdown complete, goodbye');
|
this.logger.status('Shutdown complete, goodbye');
|
||||||
@ -406,11 +400,6 @@ class Controller extends EventEmitter
|
|||||||
return this.#logger;
|
return this.#logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
get api ()
|
|
||||||
{
|
|
||||||
return this.#api;
|
|
||||||
}
|
|
||||||
|
|
||||||
get shards ()
|
get shards ()
|
||||||
{
|
{
|
||||||
return this.#shards.clone();
|
return this.#shards.clone();
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import BaseClient from './Controller.js';
|
import BaseClient from './Controller.js';
|
||||||
import os from 'node:os';
|
import os from 'node:os';
|
||||||
import Shard from './shard/Shard.js';
|
import Shard from './Shard.js';
|
||||||
import { IPCMessage } from '../../@types/Shared.js';
|
import { IPCMessage } from '../../@types/Shared.js';
|
||||||
import djs, { GuildMessageManager } from 'discord.js';
|
import djs, { GuildMessageManager } from 'discord.js';
|
||||||
import DiscordClient from '../client/DiscordClient.js';
|
import DiscordClient from '../client/DiscordClient.js';
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import EventEmitter from 'node:events';
|
import EventEmitter from 'node:events';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { makePlainError, makeError, MakeErrorOptions } from 'discord.js';
|
|
||||||
import { Util } from '../../utilities/index.js';
|
|
||||||
import childProcess, { ChildProcess } from 'node:child_process';
|
import childProcess, { ChildProcess } from 'node:child_process';
|
||||||
|
import { makePlainError, makeError, MakeErrorOptions } from 'discord.js';
|
||||||
|
|
||||||
import { EnvObject, IPCMessage } from '../../../@types/Shared.js';
|
import Controller from './Controller.js';
|
||||||
import Controller from '../Controller.js';
|
import { Util } from '../utilities/index.js';
|
||||||
import { ShardOptions } from '../../../@types/Shard.js';
|
|
||||||
import { ClientOptions } from '../../../@types/Client.js';
|
import { ShardOptions } from '../../@types/Shard.js';
|
||||||
|
import { ClientOptions } from '../../@types/Client.js';
|
||||||
|
import { EnvObject, IPCMessage } from '../../@types/Shared.js';
|
||||||
|
|
||||||
const KillTO = 90 * 1000;
|
const KillTO = 90 * 1000;
|
||||||
|
|
||||||
@ -16,8 +17,8 @@ class Shard extends EventEmitter
|
|||||||
[key: string]: unknown;
|
[key: string]: unknown;
|
||||||
|
|
||||||
#id: number;
|
#id: number;
|
||||||
#manager: Controller;
|
#controller: Controller;
|
||||||
#env: EnvObject; // { [key: string]: string | boolean | number };
|
#env: EnvObject;
|
||||||
#ready: boolean;
|
#ready: boolean;
|
||||||
#clientOptions: ClientOptions;
|
#clientOptions: ClientOptions;
|
||||||
|
|
||||||
@ -38,10 +39,10 @@ class Shard extends EventEmitter
|
|||||||
#crashes: number[];
|
#crashes: number[];
|
||||||
#fatal: boolean;
|
#fatal: boolean;
|
||||||
|
|
||||||
constructor (manager: Controller, id: number, options: ShardOptions)
|
constructor (controller: Controller, id: number, options: ShardOptions)
|
||||||
{
|
{
|
||||||
super();
|
super();
|
||||||
this.#manager = manager;
|
this.#controller = controller;
|
||||||
this.#id = id;
|
this.#id = id;
|
||||||
|
|
||||||
this.#args = options.args ?? [];
|
this.#args = options.args ?? [];
|
||||||
@ -370,7 +371,7 @@ class Shard extends EventEmitter
|
|||||||
if (message._sFetchProp)
|
if (message._sFetchProp)
|
||||||
{
|
{
|
||||||
const resp = { _sFetchProp: message._sFetchProp, _sFetchPropShard: message._sFetchPropShard };
|
const resp = { _sFetchProp: message._sFetchProp, _sFetchPropShard: message._sFetchPropShard };
|
||||||
this.#manager.fetchClientValues(message._sFetchProp, message._sFetchPropShard).then(
|
this.#controller.fetchClientValues(message._sFetchProp, message._sFetchPropShard).then(
|
||||||
(results: unknown) => this.send({ ...resp, _result: results }),
|
(results: unknown) => this.send({ ...resp, _result: results }),
|
||||||
(error: Error) => this.send({ ...resp, _error: makePlainError(error) })
|
(error: Error) => this.send({ ...resp, _error: makePlainError(error) })
|
||||||
);
|
);
|
||||||
@ -380,7 +381,7 @@ class Shard extends EventEmitter
|
|||||||
if (message._sEval)
|
if (message._sEval)
|
||||||
{
|
{
|
||||||
const resp = { _sEval: message._sEval, _sEvalShard: message._sEvalShard };
|
const resp = { _sEval: message._sEval, _sEvalShard: message._sEvalShard };
|
||||||
this.#manager._performOnShards('eval', [ message._sEval ], message._sEvalShard).then(
|
this.#controller._performOnShards('eval', [ message._sEval ], message._sEvalShard).then(
|
||||||
(results: unknown) => this.send({ ...resp, _result: results }),
|
(results: unknown) => this.send({ ...resp, _result: results }),
|
||||||
(error: Error) => this.send({ ...resp, _error: makePlainError(error) })
|
(error: Error) => this.send({ ...resp, _error: makePlainError(error) })
|
||||||
);
|
);
|
||||||
@ -390,7 +391,7 @@ class Shard extends EventEmitter
|
|||||||
if (message._sRespawnAll)
|
if (message._sRespawnAll)
|
||||||
{
|
{
|
||||||
const { shardDelay, respawnDelay, timeout } = message._sRespawnAll;
|
const { shardDelay, respawnDelay, timeout } = message._sRespawnAll;
|
||||||
this.#manager.respawnAll({ shardDelay, respawnDelay, timeout }).catch(() =>
|
this.#controller.respawnAll({ shardDelay, respawnDelay, timeout }).catch(() =>
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
});
|
});
|
@ -5,8 +5,8 @@ import fs from 'node:fs';
|
|||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { inspect } from 'node:util';
|
import { inspect } from 'node:util';
|
||||||
|
|
||||||
import BaseClient from '../Controller.js';
|
import BaseClient from './Controller.js';
|
||||||
import { Command, CommandOption, CommandsDef } from '../../../@types/Shared.js';
|
import { Command, CommandOption, CommandsDef } from '../../@types/Shared.js';
|
||||||
|
|
||||||
type CommandHashTable = {
|
type CommandHashTable = {
|
||||||
global: string | null,
|
global: string | null,
|
@ -1,6 +0,0 @@
|
|||||||
import Shard from './Shard.js';
|
|
||||||
// import ShardingManager from './ShardingManager.js';
|
|
||||||
export {
|
|
||||||
Shard,
|
|
||||||
// ShardingManager
|
|
||||||
};
|
|
Loading…
Reference in New Issue
Block a user