Skip to content

Commit

Permalink
Implement using pg_try_advisory_lock for db-migrations to be able to …
Browse files Browse the repository at this point in the history
…run multiple instances again

So we now always do db-migrate at the startup of the program. This way, we are sure that the database in the program is compatible with the queries in the program. However, these migrations are not necessarily safe to run in parallel, so in this commit I added a setup to ensure that the db-migrations are not run in parallel even when we start multiple instances of the program.
  • Loading branch information
Francis Duvivier committed Dec 4, 2024
1 parent bde959a commit a6af53e
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 13 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
"build": "tsc",
"swagger": "tsoa spec-and-routes",
"dev": "node --import tsx --watch src/index.ts",
"docker-compose-test:up": "docker compose -f compose.test.yml up -d",
"docker-compose-test:down": "docker compose -f compose.test.yml down",
"backup": "docker exec -it badgehub-api-db-1 /usr/bin/pg_dump --username badgehub badgehub -f /var/backup/data-backup-`date +\"%Y-%m-%dT%H:%m\"`.sql",
"test": "vitest --coverage.enabled true",
"db-migrate:up": "db-migrate up",
Expand Down
2 changes: 1 addition & 1 deletion process.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"interpreter_args": "--import tsx",
"name": "badgehub",
"exec_mode": "cluster",
"instances": 1,
"instances": 4,
"error_file": "./logs/error.log",
"out_file": "./logs/access.log",
"combine_logs": true
Expand Down
10 changes: 10 additions & 0 deletions src/db/connectionPool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,13 @@ export const getPool = () => {
}
return pool;
};

export const getClient = () => {
return new pg.Client({
host: POSTGRES_HOST,
database: POSTGRES_DB,
user: POSTGRES_USER,
password: POSTGRES_PASSWORD,
port: POSTGRES_PORT,
});
};
36 changes: 24 additions & 12 deletions src/db/migrations.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,31 @@
import { exec } from "node:child_process";
import { getClient } from "@db/connectionPool";

const MIGRATION_LOCK_ID = 108;

export async function runMigrations() {
// This code runs the npm script 'db-migrate:up' to make sure all migrations are done
console.log(`Waiting for db-migrations lock [${MIGRATION_LOCK_ID}]`);
const dbClient = getClient();
await dbClient.connect();
await dbClient.query(`SELECT pg_advisory_lock($1)`, [MIGRATION_LOCK_ID]);
console.log("Running migrations via child process");
return new Promise<void>((resolve, reject) => {
exec("npm run db-migrate:up", (error, stdout, stderr) => {
stdout && console.log(stdout);
stderr && console.error(stderr);
if (error) {
console.error(`Error running migrations: ${error}`);
reject(error);
} else {
resolve();
}
console.log("Migrations done");
try {
return await new Promise<void>((resolve, reject) => {
exec("npm run db-migrate:up", (error, stdout, stderr) => {
stdout && console.log(stdout);
stderr && console.error(stderr);
if (error) {
console.error(`Error running migrations: ${error}`);
reject(error);
} else {
resolve();
}
console.log("Migrations done");
});
});
});
} finally {
await dbClient.end();
console.log("released db-migrations");
}
}

0 comments on commit a6af53e

Please sign in to comment.