Compare commits

..

2 Commits

Author SHA1 Message Date
68512ec871
controller tweaks 2023-05-09 03:15:22 +03:00
268c3421dd
start and stop commands 2023-05-09 03:15:05 +03:00
3 changed files with 116 additions and 29 deletions

View File

@ -94,12 +94,7 @@ class Controller extends EventEmitter {
const { const {
projectName, projectName,
shardCount = 1, shardCount = 1,
shardOptions = {},
serverOptions = {} as ServerOptions, serverOptions = {} as ServerOptions,
logger = {},
discord = {},
databases = {},
rabbitConfig = {} as BrokerOptions
} = this.#_options; } = this.#_options;
this.#_logger.info(`Spawning ${shardCount} shards`); this.#_logger.info(`Spawning ${shardCount} shards`);
@ -124,22 +119,12 @@ class Controller extends EventEmitter {
process.stdin.on('data', (data) => { process.stdin.on('data', (data) => {
const raw = data.toString('utf-8'); const raw = data.toString('utf-8');
const words = raw.split(' ').map(word => word.trim()); const words = raw.split(' ').map(word => word.trim());
this._handleStdin(words); this.#handleStdin(words);
}); });
const promises = []; const promises = [];
for (let i = 0; i < shardCount; i++) { for (let i = 0; i < shardCount; i++) {
const shard = new Shard(this, i, { const shard = this.createShard();
serverOptions: {
...serverOptions, logger, discord, databases, rabbitConfig
},
...shardOptions,
env: this.#_options.env,
path: this.#_serverFilePath
});
this.#_logger.attach(shard);
this._setListeners(shard);
this.#_shards.set(i, shard);
promises.push(shard.spawn()); promises.push(shard.spawn());
// setTimeout(() => { // setTimeout(() => {
@ -150,16 +135,47 @@ class Controller extends EventEmitter {
await Promise.all(promises); await Promise.all(promises);
this.emit('built'); this.emit('built');
} }
_handleMessage (shard: Shard, msg: IPCMessage) { createShard () {
const ids = this.shards.map(s => s.id);
const id = ids.length ? Math.max(...ids) + 1 : 0;
const shard = new Shard(this, id, this.shardOptions);
this.shards.set(shard.id, shard);
this.#_logger.attach(shard);
this.#setListeners(shard);
return shard;
}
get shardOptions () {
const {
shardOptions = {},
serverOptions = {} as ServerOptions,
logger = {},
discord = {},
databases = {},
rabbitConfig = {} as BrokerOptions
} = this.#_options;
return {
serverOptions: {
...serverOptions, logger, discord, databases, rabbitConfig
},
...shardOptions,
env: this.#_options.env,
path: this.#_serverFilePath
};
}
#handleMessage (shard: Shard, msg: IPCMessage) {
if (msg._logger) if (msg._logger)
return; return;
this.#_logger.debug(`Message from ${shard.id}: ${inspect(msg)}`); this.#_logger.debug(`Message from ${shard.id}: ${inspect(msg)}`);
} }
_setListeners (shard: Shard) { #setListeners (shard: Shard) {
shard.on('death', () => this.#_logger.info(`Shard ${shard.id} has died`)); shard.on('death', () => this.#_logger.info(`Shard ${shard.id} has died`));
shard.on('fatal', ({ message }) => this.#_logger.warn(`Shard ${shard.id} has died fatally: ${message}`)); shard.on('fatal', ({ message }) => this.#_logger.warn(`Shard ${shard.id} has died fatally: ${message}`));
shard.on('shutdown', () => this.#_logger.info(`Shard ${shard.id} is shutting down gracefully`)); shard.on('shutdown', () => this.#_logger.info(`Shard ${shard.id} is shutting down gracefully`));
@ -169,10 +185,10 @@ class Controller extends EventEmitter {
shard.on('error', (err) => this.#_logger.error(`Shard ${shard.id} ran into an error:\n${err.stack}`)); shard.on('error', (err) => this.#_logger.error(`Shard ${shard.id} ran into an error:\n${err.stack}`));
shard.on('warn', (msg) => this.#_logger.warn(`Warning from shard ${shard.id}: ${msg}`, { broadcast: true })); shard.on('warn', (msg) => this.#_logger.warn(`Warning from shard ${shard.id}: ${msg}`, { broadcast: true }));
shard.on('message', (msg) => this._handleMessage(shard, msg)); shard.on('message', (msg) => this.#handleMessage(shard, msg));
} }
async _handleStdin (words: string[]) { async #handleStdin (words: string[]) {
words = words.filter(word => word.length); words = words.filter(word => word.length);
if (!words.length) if (!words.length)
@ -195,7 +211,8 @@ class Controller extends EventEmitter {
if (rest.args.help) { if (rest.args.help) {
if (command.help) if (command.help)
return command.help; // eslint-disable-next-line no-console
return console.log(command.help);
return this.#_logger.info(`Help for ${command.name} unavailable at this time`); return this.#_logger.info(`Help for ${command.name} unavailable at this time`);
} }

View File

@ -1,6 +1,6 @@
import BaseCommand from "../BaseCommand.js"; import BaseCommand from "../BaseCommand.js";
import Controller from "../Controller.js"; import Controller from "../Controller.js";
import { OptionType } from '@navy.gif/commandparser'; import { ArgsResult, OptionType } from '@navy.gif/commandparser';
class StartCommand extends BaseCommand { class StartCommand extends BaseCommand {
@ -12,12 +12,44 @@ class StartCommand extends BaseCommand {
aliases: [ 's' ], aliases: [ 's' ],
flag: true, flag: true,
type: OptionType.INTEGER type: OptionType.INTEGER
}, {
name: 'amount',
type: OptionType.INTEGER
}] }]
}); });
} }
execute (_message: unknown, _args?: unknown): Promise<unknown> { async execute ({ args }: { subcommand: string, args: ArgsResult }): Promise<string> {
throw new Error("Method not implemented."); const { shard, amount } = args;
const { shards } = this.controller;
const n = amount?.value as number || 0;
let id = -1;
if (shard)
id = shard.value as number;
let out = '';
if (id >= 0) {
const s = shards.get(id);
if (!s)
return `Shard ${id} doesn't exist`;
if (s.ready)
return `Shard ${id} is already running`;
await s.spawn();
out += `Started shard ${id}`;
}
if (n > 0) {
for (let i = 0; i < n; i++) {
const s = this.controller.createShard();
await s.spawn(true);
}
out += `\nSpawned ${n} shards`;
}
return out;
} }
} }

View File

@ -1,15 +1,53 @@
import { ArgsResult, OptionType } from "@navy.gif/commandparser";
import BaseCommand from "../BaseCommand.js"; import BaseCommand from "../BaseCommand.js";
import Controller from "../Controller.js"; import Controller from "../Controller.js";
class StopCommand extends BaseCommand { class StopCommand extends BaseCommand {
constructor (controller: Controller) { constructor (controller: Controller) {
super(controller, { super(controller, {
name: 'stop' name: 'stop',
options: [{
name: 'shard',
type: OptionType.INTEGER,
flag: true,
}, {
name: 'all',
flag: true,
type: OptionType.BOOLEAN,
valueOptional: true,
defaultValue: true
}, {
name: 'prune',
flag: true,
type: OptionType.BOOLEAN,
valueOptional: true,
defaultValue: true
}]
}); });
} }
async execute (_message: unknown, _args?: unknown) { async execute ({ args }: { subcommand: string, args: ArgsResult }) {
// const id = args.shard?.value;
const all = args.all?.value || false;
const prune = args.prune?.value || false;
if (typeof id !== 'number' && !all)
return `Must supply either --all or --shard option`;
const { shards } = this.controller;
const targets = all ? shards : shards.filter(shard => shard.id === id);
const ids = targets.map(s => s.id);
for (const shard of targets.values()) {
await shard.kill();
if (prune)
shards.delete(shard.id);
}
let out = `Stopped ${all ? `all shards (${ids.join(', ')})` : `shard ${id}`}.`;
if (prune)
out += ' Pruned stopped shards';
return out;
} }
} }