fix(server): run migrations after database checks (#5832)

* run migrations after checks

* optional migrations

* only run checks in server and e2e

* re-add migrations for microservices

* refactor

* move e2e init

* remove assert from migration

* update providers

* update microservices app service

* fixed logging

* refactored version check, added unit tests

* more version tests

* don't use mocks for sut

* refactor tests

* suggest image only if postgres is 14, 15 or 16

* review suggestions

* fixed regexp escape

* fix typing

* update migration
This commit is contained in:
Mert
2023-12-21 11:06:26 -05:00
committed by GitHub
parent 2790a46703
commit cc2dc12f6c
26 changed files with 383 additions and 136 deletions

View File

@@ -1,4 +1,4 @@
import { DataSource, QueryRunner } from 'typeorm';
import { DataSource } from 'typeorm';
import { PostgresConnectionOptions } from 'typeorm/driver/postgres/PostgresConnectionOptions';
const url = process.env.DB_URL;
@@ -18,58 +18,10 @@ export const databaseConfig: PostgresConnectionOptions = {
synchronize: false,
migrations: [__dirname + '/migrations/*.{js,ts}'],
subscribers: [__dirname + '/subscribers/*.{js,ts}'],
migrationsRun: true,
migrationsRun: false,
connectTimeoutMS: 10000, // 10 seconds
...urlOrParts,
};
// this export is used by TypeORM commands in package.json#scripts
export const dataSource = new DataSource(databaseConfig);
export async function databaseChecks() {
if (!dataSource.isInitialized) {
await dataSource.initialize();
}
await assertVectors(dataSource);
await enablePrefilter(dataSource);
await dataSource.runMigrations();
}
export async function enablePrefilter(runner: DataSource | QueryRunner) {
await runner.query(`SET vectors.enable_prefilter = on`);
}
export async function getExtensionVersion(extName: string, runner: DataSource | QueryRunner): Promise<string | null> {
const res = await runner.query(`SELECT extversion FROM pg_extension WHERE extname = $1`, [extName]);
return res[0]?.['extversion'] ?? null;
}
export async function getPostgresVersion(runner: DataSource | QueryRunner): Promise<string> {
const res = await runner.query(`SHOW server_version`);
return res[0]['server_version'].split('.')[0];
}
export async function assertVectors(runner: DataSource | QueryRunner) {
const postgresVersion = await getPostgresVersion(runner);
const expected = ['0.1.1', '0.1.11'];
const image = `tensorchord/pgvecto-rs:pg${postgresVersion}-v${expected[expected.length - 1]}`;
await runner.query('CREATE EXTENSION IF NOT EXISTS vectors').catch((err) => {
console.error(
'Failed to create pgvecto.rs extension. ' +
`If you have not updated your Postgres instance to an image that supports pgvecto.rs (such as '${image}'), please do so. ` +
'See the v1.91.0 release notes for more info: https://github.com/immich-app/immich/releases/tag/v1.91.0',
);
throw err;
});
const version = await getExtensionVersion('vectors', runner);
if (version != null && !expected.includes(version)) {
throw new Error(
`The pgvecto.rs extension version is ${version} instead of the expected version ${
expected[expected.length - 1]
}.` + `If you're using the 'latest' tag, please switch to '${image}'.`,
);
}
}