diff --git a/packages/backend/toolchain/postgres/error.ts b/packages/backend/toolchain/postgres/error.ts index 3db04e1b..94c31440 100644 --- a/packages/backend/toolchain/postgres/error.ts +++ b/packages/backend/toolchain/postgres/error.ts @@ -24,27 +24,13 @@ export class CommandError extends InternalError { } } -export class CreateDatabaseError extends InternalError { - constructor(opts?: InternalErrorOpts) { - super("An error occurred while creating the database.", opts); - this.name = "CreateDatabaseError"; - } -} - export class DatabaseError extends InternalError { constructor(opts?: InternalErrorOpts) { - super("A general database error occurred.", opts); + super(`A general database error occurred: ${opts?.originalError ?? "?"}`, opts); this.name = "DatabaseError"; } } -export class DatabaseExistsError extends InternalError { - constructor(opts?: InternalErrorOpts) { - super("The database already exists.", opts); - this.name = "DatabaseExistsError"; - } -} - export class DatabaseInitializationError extends InternalError { constructor(opts?: InternalErrorOpts) { super("An error occurred during database initialization.", opts); @@ -66,13 +52,6 @@ export class DatabaseStopError extends InternalError { } } -export class DropDatabaseError extends InternalError { - constructor(opts?: InternalErrorOpts) { - super("An error occurred while dropping the database.", opts); - this.name = "DropDatabaseError"; - } -} - export interface InvalidUrlOpts extends InternalErrorOpts { url: string; } diff --git a/packages/backend/toolchain/postgres/manager.ts b/packages/backend/toolchain/postgres/manager.ts index 8d2ade9b..7ba5d0ed 100644 --- a/packages/backend/toolchain/postgres/manager.ts +++ b/packages/backend/toolchain/postgres/manager.ts @@ -1,10 +1,8 @@ import { - CreateDatabaseError, - DatabaseExistsError, + DatabaseError, DatabaseInitializationError, DatabaseStartError, DatabaseStopError, - DropDatabaseError, } from "./error.ts"; import { binaryDir, Settings } from "./settings.ts"; import { verbose } from "../term/status.ts"; @@ -81,8 +79,22 @@ async function isInitialized(manager: Manager): Promise { } async function isStarted(manager: Manager): Promise { + // Check if PID exists const pidFile = manager.settings.dataDir.concat("/postmaster.pid"); - return await exists(pidFile); + if (!await exists(pidFile)) return false; + + // Check if connectable + let client; + try { + client = await getClient(manager, BOOTSTRAP_DATABASE); + await client.queryObject("SELECT 1"); + } catch (_) { + return false; + } finally { + await client?.end(); + } + + return true; } async function install(manager: Manager): Promise { @@ -258,13 +270,14 @@ export async function getClient(manager: Manager, databaseName: string): Promise export async function createDatabase(manager: Manager, databaseName: S): Promise { verbose(`Creating database`, databaseName); - const client = await getClient(manager, BOOTSTRAP_DATABASE); + let client; try { + client = await getClient(manager, BOOTSTRAP_DATABASE); await client.queryObject(`CREATE DATABASE "${databaseName}"`); } catch (error) { - throw new CreateDatabaseError({ originalError: error as any }); + throw new DatabaseError({ originalError: error as any }); } finally { - await client.end(); + await client?.end(); } verbose(`Created database`, databaseName); @@ -273,30 +286,32 @@ export async function createDatabase(manager: Manager, databas export async function databaseExists(manager: Manager, databaseName: S): Promise { verbose(`Checking database`, databaseName); - const client = await getClient(manager, BOOTSTRAP_DATABASE); + let client; try { + client = await getClient(manager, BOOTSTRAP_DATABASE); const rows = await client.queryObject( "SELECT * FROM pg_database WHERE datname = $1", [databaseName], ); return rows.rowCount === 1; } catch (error) { - throw new DatabaseExistsError({ originalError: error as any }); + throw new DatabaseError({ originalError: error as any }); } finally { - await client.end(); + await client?.end(); } } export async function dropDatabase(manager: Manager, databaseName: S): Promise { verbose(`Dropping database`, databaseName); - const client = await getClient(manager, BOOTSTRAP_DATABASE); + let client; try { + client = await getClient(manager, BOOTSTRAP_DATABASE); await client.queryObject(`DROP DATABASE IF EXISTS "${databaseName}"`); } catch (error) { - throw new DropDatabaseError({ originalError: error as any }); + throw new DatabaseError({ originalError: error as any }); } finally { - await client.end(); + await client?.end(); } verbose(`Dropped database`, databaseName);