Проверить соединение с PG-обещанием при запуске приложения

Я создаю экспресс-приложение, которое подключается к базе данных postgres с помощью модуля pg-promise.

Я хотел бы убедиться, что соединение с базой данных будет успешным при запуске сервера приложений. Другими словами, если соединение с базой данных терпит неудачу, я хотел бы сделать ошибку.

Мой файл server.js выглядит следующим образом:

const express = require("express");

const databaseConfig= {
  "host": "localhost",
  "port": 5432,
  "database": "library_app",
  "user": "postgres"
};

const pgp = require("pg-promise")({});
const db = pgp(databaseConfig);

const app = express();
const port = 5000;

app.listen(port, (err) => {
  console.log(`running server on port: ${port}`);
});

Текущая конфигурация запустит экспресс-сервер независимо от того, является ли соединение с базой данных действительным, что не является поведением, которое я бы хотел.

Я пробовал просматривать документы, но не смог найти решение. Я также пробовал const db = pgp(databaseConfig).catch((err) => { // blow up });, но это не сработало, потому что pgp не возвращает обещание.

Ответы

Ответ 1

Я автор pg-promise;) И это не первый раз, когда задают этот вопрос, поэтому я даю это подробное объяснение здесь.

Когда вы создаете экземпляр нового объекта базы данных следующим образом:

const db = pgp(connection);

... все, что он делает - создает объект, но он не пытается подключиться. Библиотека построена поверх пула соединений, и только фактические методы запроса запрашивают соединение из пула.

Из официальной документации:

Объект db представляет собой протокол базы данных с ленивым подключением к базе данных, то есть только фактические методы запроса получают и освобождают соединение. Следовательно, вы должны создать только один глобальный/общий db объект для каждой детали подключения.

Однако вы можете попросить библиотеку подключиться без выполнения какого-либо запроса, используя метод connect, как показано ниже.

И хотя этот метод больше не является рекомендуемым способом для цепочки запросов, с тех пор, как была введена поддержка Tasks (как более безопасная подход), он по-прежнему удобен для проверки соединения в целом.

Я скопировал пример из своего собственного сообщения: https://github.com/vitaly-t/pg-promise/issues/81

Ниже приведен пример выполнения этого двумя способами в одно и то же время, поэтому вы можете выбрать любой подходящий вам подход.

const initOptions = {
    // global event notification;
    error: (error, e) => {
        if (e.cn) {
            // A connection-related error;
            //
            // Connections are reported back with the password hashed,
            // for safe errors logging, without exposing passwords.
            console.log('CN:', e.cn);
            console.log('EVENT:', error.message || error);
        }
    }
};

const pgp = require('pg-promise')(initOptions);

// using an invalid connection string:
const db = pgp('postgresql://userName:[email protected]:port/database');

db.connect()
    .then(obj => {
        obj.done(); // success, release the connection;
    })
    .catch(error => {
        console.log('ERROR:', error.message || error);
    });

Выходы:

CN: postgresql://userName:########@host:port/database EVENT: getaddrinfo ENOTFOUND host host:5432 ERROR: getaddrinfo ENOTFOUND host host:5432

Каждая ошибка в библиотеке сначала регистрируется через глобальный error обработчик событий, и только тогда сообщение об ошибке сообщается в соответствующем .catch.

Alternative

Вместо того, чтобы устанавливать соединение вручную, вы можете просто выполнить тип запроса, который всегда будет успешным для действительного соединения, например следующего:

db.proc('version')
    .then(data => {
        // SUCCESS
        // data.version =
        // 'PostgreSQL 9.5.1, compiled by Visual C++ build 1800, 64-bit'
    })
    .catch(error => {
        // connection-related error
    });

Ссылки API: