feat: Move database migration execution from update command to post-restart ready event.

This commit is contained in:
syntaxbullet
2025-12-18 17:29:37 +01:00
parent 1d650bb2c7
commit 71fefb3a14
2 changed files with 50 additions and 33 deletions

View File

@@ -70,44 +70,34 @@ export const update = createCommand({
if (confirmation.customId === "confirm_update") {
await confirmation.update({
embeds: [createWarningEmbed("Applying updates and restarting...", "Update In Progress")],
embeds: [createWarningEmbed("Applying updates and restarting...\nThe bot will run database migrations on next startup.", "Update In Progress")],
components: []
});
const { stdout } = await execAsync(`git reset --hard origin/${branch}`);
// Run DB Migrations
await confirmation.editReply({
embeds: [createWarningEmbed("Updating database schema...", "Running Migrations")],
components: []
});
let migrationOutput = "";
try {
const { stdout: dbOut } = await execAsync("bun run db:push:local");
migrationOutput = dbOut;
} catch (dbErr: any) {
migrationOutput = `Migration Failed: ${dbErr.message}`;
console.error("Migration Error:", dbErr);
// We continue with restart even if migration fails?
// Probably safer to try, or should we abort?
// For now, let's log it and proceed, as code might depend on it but maybe it was a no-op partial fail.
}
await interaction.followUp({
flags: MessageFlags.Ephemeral,
embeds: [createSuccessEmbed(`Git Reset Output:\n\`\`\`\n${stdout}\n\`\`\`\nDB Migration Output:\n\`\`\`\n${migrationOutput}\n\`\`\`\nRestarting process...`, "Update Successful")]
});
// Write context for post-restart notification
// Write context BEFORE reset, because reset -> watcher restart
await writeFile(".restart_context.json", JSON.stringify({
channelId: interaction.channelId,
userId: interaction.user.id,
timestamp: Date.now()
timestamp: Date.now(),
runMigrations: true
}));
// Trigger restart
const { stdout } = await execAsync(`git reset --hard origin/${branch}`);
// In case we are not running with a watcher, or if no files were changed (unlikely given log check),
// we might need to manually trigger restart.
// But if files changed, watcher kicks in here or slightly after.
// If we are here, we can try to force a touch or just exit.
// Trigger restart just in case watcher didn't catch it or we are in a mode without watcher (though update implies source change)
try {
await appendFile("src/index.ts", " ");
} catch (err) {
console.error("Failed to touch triggers:", err);
}
// The process should die now or soon.
// We do NOT run migrations here anymore.
} else {
await confirmation.update({

View File

@@ -20,12 +20,39 @@ const event: Event<Events.ClientReady> = {
// Validate context freshness (e.g., ignore if older than 5 minutes)
if (Date.now() - context.timestamp < 5 * 60 * 1000) {
const channel = await c.channels.fetch(context.channelId);
if (channel && channel.isSendable()) {
let migrationOutput = "";
let success = true;
if (context.runMigrations) {
try {
const { exec } = await import("child_process");
const { promisify } = await import("util");
const execAsync = promisify(exec);
// Send intermediate update if possible, though ready event should be fast.
// Maybe just run it and report result.
const { stdout: dbOut } = await execAsync("bun run db:push:local");
migrationOutput = dbOut;
} catch (dbErr: any) {
success = false;
migrationOutput = `Migration Failed: ${dbErr.message}`;
console.error("Migration Error:", dbErr);
}
}
if (context.runMigrations) {
await channel.send({
embeds: [createSuccessEmbed(`Bot is back online!\n\n**DB Migration Output:**\n\`\`\`\n${migrationOutput}\n\`\`\``, success ? "Update Successful" : "Update Completed with/Errors")]
});
} else {
await channel.send({
embeds: [createSuccessEmbed("Bot is back online! Redeploy successful.", "System Online")]
});
}
}
}
await unlink(".restart_context.json");
} catch (error) {