Added support for database updates/migration, added guild access timestamps

This commit is contained in:
Essem 2022-02-18 23:05:41 -06:00
parent 55f6271cd9
commit c568423870
No known key found for this signature in database
GPG key ID: 7D497397CC3A2A8C
5 changed files with 106 additions and 39 deletions

View file

@ -1,5 +1,5 @@
import { prefixCache, disabledCmdCache, disabledCache, commands } from "../collections.js";
import { error, log } from "../logger.js";
import * as logger from "../logger.js";
import Postgres from "pg";
const connection = new Postgres.Pool({
@ -7,10 +7,74 @@ const connection = new Postgres.Pool({
statement_timeout: 10000
});
const psqlUpdates = [
"", // reserved
"CREATE TABLE settings ( id smallint PRIMARY KEY, version integer NOT NULL, CHECK(id = 1) );\nALTER TABLE guilds ADD COLUMN accessed timestamp;"
];
// INSERT INTO settings (id, version) VALUES(1, $1)
export async function setup(ipc) {
let version;
try {
version = (await connection.query("SELECT version FROM settings WHERE id = 1")).rows[0].version;
} catch {
version = 0;
}
if (version < (psqlUpdates.length - 1)) {
logger.warn(`Migrating PostgreSQL database, which is currently at version ${version}...`);
await connection.query("BEGIN");
try {
while (version < (psqlUpdates.length - 1)) {
version++;
logger.warn(`Running version ${version} update script (${psqlUpdates[version]})...`);
await connection.query(psqlUpdates[version]);
}
await connection.query("COMMIT");
await connection.query("INSERT INTO settings (id, version) VALUES (1, $1) ON CONFLICT (id) DO NOTHING", [psqlUpdates.length - 1]);
} catch (e) {
logger.error(`PostgreSQL migration failed: ${e}`);
await connection.query("ROLLBACK");
logger.error("Unable to start the bot, quitting now.");
throw ipc.totalShutdown();
}
}
let counts;
try {
counts = await connection.query("SELECT * FROM counts");
} catch {
counts = { rows: [] };
}
if (!counts.rows[0]) {
for (const command of commands.keys()) {
await connection.query("INSERT INTO counts (command, count) VALUES ($1, $2)", [command, 0]);
}
} else {
const exists = [];
for (const command of commands.keys()) {
const count = await connection.query("SELECT * FROM counts WHERE command = $1", [command]);
if (!count.rows[0]) {
await connection.query("INSERT INTO counts (command, count) VALUES ($1, $2)", [command, 0]);
}
exists.push(command);
}
for (const { command } of counts.rows) {
if (!exists.includes(command)) {
await connection.query("DELETE FROM counts WHERE command = $1", [command]);
}
}
}
}
export async function getGuild(query) {
return (await connection.query("SELECT * FROM guilds WHERE guild_id = $1", [query])).rows[0];
}
export async function updateTime(time, guild) {
await connection.query("UPDATE guilds SET accessed = $1 WHERE guild_id = $2", [time, guild]);
}
export async function setPrefix(prefix, guild) {
await connection.query("UPDATE guilds SET prefix = $1 WHERE guild_id = $2", [prefix, guild.id]);
prefixCache.set(guild.id, prefix);
@ -93,7 +157,7 @@ export async function addGuild(guild) {
try {
await connection.query("INSERT INTO guilds (guild_id, prefix, disabled, disabled_commands) VALUES ($1, $2, $3, $4)", [guild.id, process.env.PREFIX, [], []]);
} catch (e) {
error(`Failed to register guild ${guild.id}: ${e}`);
logger.error(`Failed to register guild ${guild.id}: ${e}`);
}
return await this.getGuild(guild.id);
}
@ -101,41 +165,11 @@ export async function addGuild(guild) {
export async function fixGuild(guild) {
const guildDB = await connection.query("SELECT exists(SELECT 1 FROM guilds WHERE guild_id = $1)", [guild.id]);
if (!guildDB.rows[0].exists) {
log(`Registering guild database entry for guild ${guild.id}...`);
logger.log(`Registering guild database entry for guild ${guild.id}...`);
return await this.addGuild(guild);
}
}
export async function setup() {
let counts;
try {
counts = await connection.query("SELECT * FROM counts");
} catch {
counts = { rows: [] };
}
if (!counts.rows[0]) {
for (const command of commands.keys()) {
await connection.query("INSERT INTO counts (command, count) VALUES ($1, $2)", [command, 0]);
}
} else {
const exists = [];
for (const command of commands.keys()) {
const count = await connection.query("SELECT * FROM counts WHERE command = $1", [command]);
if (!count.rows[0]) {
await connection.query("INSERT INTO counts (command, count) VALUES ($1, $2)", [command, 0]);
}
exists.push(command);
}
for (const { command } of counts.rows) {
if (!exists.includes(command)) {
await connection.query("DELETE FROM counts WHERE command = $1", [command]);
}
}
}
}
export async function stop() {
await connection.end();
}

View file

@ -4,7 +4,32 @@ import * as logger from "../logger.js";
import sqlite3 from "better-sqlite3";
const connection = sqlite3(process.env.DB.replace("sqlite://", ""));
export async function setup() {
const sqliteUpdates = [
"", // reserved
"ALTER TABLE guilds ADD COLUMN accessed int" // CREATE TABLE settings ( version int );\n
];
export async function setup(ipc) {
let version = connection.pragma("user_version", { simple: true });
if (version < (sqliteUpdates.length - 1)) {
logger.warn(`Migrating SQLite database at ${process.env.DB}, which is currently at version ${version}...`);
connection.prepare("BEGIN TRANSACTION").run();
try {
while (version < (sqliteUpdates.length - 1)) {
version++;
logger.warn(`Running version ${version} update script (${sqliteUpdates[version]})...`);
connection.prepare(sqliteUpdates[version]).run();
}
connection.pragma(`user_version = ${version}`); // insecure, but the normal templating method doesn't seem to work here
connection.prepare("COMMIT").run();
} catch (e) {
logger.error(`SQLite migration failed: ${e}`);
connection.prepare("ROLLBACK").run();
logger.error("Unable to start the bot, quitting now.");
ipc.totalShutdown();
}
}
let counts;
try {
counts = connection.prepare("SELECT * FROM counts").all();
@ -58,6 +83,10 @@ export async function fixGuild(guild) {
}
}
export async function updateTime(time, guild) {
connection.prepare("UPDATE guilds SET accessed = ? WHERE guild_id = ?").run(Math.floor(time / 1000), guild);
}
export async function addCount(command) {
connection.prepare("UPDATE counts SET count = count + 1 WHERE command = ?").run(command);
}