Should fix graceful exits

This commit is contained in:
Erik 2024-03-28 11:34:53 +02:00
parent de8c0a0880
commit 88c7c3fbde
4 changed files with 80 additions and 70 deletions

View File

@ -67,7 +67,7 @@ class DiscordClient extends Client
this.#logger.error(`Unhandled rejection:\n${err?.stack || err}`); this.#logger.error(`Unhandled rejection:\n${err?.stack || err}`);
}); });
// process.on('message', this.#handleMessage.bind(this)); process.on('message', this.#handleMessage.bind(this));
process.on('SIGINT', () => this.shutdown()); process.on('SIGINT', () => this.shutdown());
process.on('SIGTERM', () => this.shutdown()); process.on('SIGTERM', () => this.shutdown());
@ -115,6 +115,12 @@ class DiscordClient extends Client
process.exit(code); process.exit(code);
} }
#handleMessage (message: IPCMessage)
{
if (message._shutdown)
this.shutdown();
}
async sendSplitMessage (message: Message, text: string, opts: MessageReplyOptions) async sendSplitMessage (message: Message, text: string, opts: MessageReplyOptions)
{ {
const words = text.split(' '); const words = text.split(' ');

View File

@ -59,19 +59,47 @@ class MusicPlayer implements Initialisable
this.#player.on('error', (err) => this.#logger.error(err)); this.#player.on('error', (err) => this.#logger.error(err));
} }
get ready () async initialise ()
{ {
return this.#ready; if (this.ready)
return;
this.#logger.info('Initialising music player');
if (fs.existsSync(cachePath))
{
const rawConfig = fs.readFileSync(cachePath, { encoding: 'utf-8' });
const config = JSON.parse(rawConfig);
this.#volume = config.volume;
this.#queue = config.queue;
}
await this.#library.initialise();
this.#shuffleList = this.#library.getShufflePlaylist();
this.#initialiseVoiceChannels();
this.#ready = true;
this.playNext();
} }
get library () stop (): void | Promise<void>
{ {
return this.#library; this.#ready = false;
} this.#logger.info('Stopping music player');
this.#logger.info('Disconnecting all guilds');
for (const [ guildId, { connection, subscription }] of this.#connections)
{
this.#logger.debug(`Disconnecting ${guildId}`);
subscription.unsubscribe();
connection.disconnect();
}
this.#library.stop();
get queue () const config = {
{ volume: this.#volume,
return Object.freeze(this.#queue); queue: this.#queue
};
fs.writeFileSync(cachePath, JSON.stringify(config));
} }
async request (keyword: string) async request (keyword: string)
@ -178,61 +206,6 @@ class MusicPlayer implements Initialisable
} }
get volume ()
{
return this.#volume * 100;
}
set volume (vol: number)
{
vol /= 100;
this.#volume = vol;
this.#currentResource.volume?.setVolume(vol);
}
stop (): void | Promise<void>
{
this.#ready = false;
this.#logger.info('Stopping music player');
this.#logger.info('Disconnecting all guilds');
for (const [ guildId, { connection, subscription }] of this.#connections)
{
this.#logger.debug(`Disconnecting ${guildId}`);
subscription.unsubscribe();
connection.disconnect();
}
this.#library.stop();
const config = {
volume: this.#volume,
queue: this.#queue
};
fs.writeFileSync(cachePath, JSON.stringify(config));
}
async initialise ()
{
if (this.ready)
return;
this.#logger.info('Initialising music player');
if (fs.existsSync(cachePath))
{
const rawConfig = fs.readFileSync(cachePath, { encoding: 'utf-8' });
const config = JSON.parse(rawConfig);
this.#volume = config.volume;
this.#queue = config.queue;
}
await this.#library.initialise();
this.#shuffleList = this.#library.getShufflePlaylist();
this.#initialiseVoiceChannels();
this.#ready = true;
this.playNext();
}
#initialiseVoiceChannels () #initialiseVoiceChannels ()
{ {
for (const config of this.#options.guilds) for (const config of this.#options.guilds)
@ -322,6 +295,33 @@ class MusicPlayer implements Initialisable
// return; // return;
} }
get volume ()
{
return this.#volume * 100;
}
set volume (vol: number)
{
vol /= 100;
this.#volume = vol;
this.#currentResource.volume?.setVolume(vol);
}
get ready ()
{
return this.#ready;
}
get library ()
{
return this.#library;
}
get queue ()
{
return Object.freeze(this.#queue);
}
} }
export default MusicPlayer; export default MusicPlayer;

View File

@ -52,8 +52,8 @@ class Controller
this.#ready = false; this.#ready = false;
this.#exiting = false; this.#exiting = false;
process.on('SIGINT', this.shutdown.bind(this)); process.on('SIGINT', () => this.shutdown('SIGINT'));
process.on('SIGTERM', this.shutdown.bind(this)); process.on('SIGTERM', () => this.shutdown('SIGTERM'));
} }
async build () async build ()
@ -234,7 +234,7 @@ class Controller
return { shardList, totalShards, execArgv }; return { shardList, totalShards, execArgv };
} }
async shutdown () async shutdown (type: string)
{ {
if (this.#exiting) if (this.#exiting)
return; return;
@ -243,8 +243,13 @@ class Controller
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 =>
.then(() => shard.removeAllListeners())); {
if (type === 'SIGTERM')
return shard.kill();
return shard.awaitShutdown()
.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');

View File

@ -206,7 +206,6 @@ class Shard extends EventEmitter
}); });
this.send({ _shutdown: true }); this.send({ _shutdown: true });
}); });
} }
return Promise.resolve(); return Promise.resolve();