使用pg-promise在启动应用程序时验证数据库连接

39

我正在构建一个使用pg-promise模块连接到Postgres数据库的Express应用程序。

我希望确保在启动应用程序服务器时数据库连接成功。换句话说,如果与数据库的连接失败,我想抛出一个错误。

我的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}`);
});

当前配置会启动Express服务器,无论数据库连接是否有效,这不是我想要的行为。

我尝试查阅文档,但没有找到解决方案。我还尝试了

const db = pgp(databaseConfig).catch((err) => { // blow up });

但是那并没有奏效,因为 pgp 不会返回一个 Promise。


答案在这里:https://github.com/vitaly-t/pg-promise/issues/81 - vitaly-t
2个回答

85

我是 pg-promise 的作者 ;) 这不是第一次被问到这个问题,所以我在这里详细解释一下。

当你像这样实例化一个新的数据库对象:

const db = pgp(connection);

这个库只是创建对象,但不会尝试连接数据库。该库是在连接池的基础上构建的,只有实际查询方法才会从池中请求连接。

来自官方文档

对象 db 表示数据库协议,采用懒惰的数据库连接方式,即只有实际查询方法才会获取和释放连接。因此,您应该针对每个连接详情只创建一个全局/共享 db 对象。

但是,您可以通过调用方法connect强制进行连接,如下所示。虽然该方法不推荐用于链接查询(应使用任务),但它非常适合检查一般性的连接。

我从自己的帖子中复制了示例

以下是同时使用两种方法的示例,因此您可以选择更喜欢哪种方法。

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:password@host:port/database');
    
db.connect()
    .then(obj => {
        // Can check the server version here (pg-promise v10.1.0+):
        const serverVersion = obj.client.serverVersion;

        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处理程序中报告错误。

更新

连接测试和一步获取服务器版本的现代方法:

// tests connection and returns Postgres server version,
// if successful; or else rejects with connection error:
async function testConnection() {
    const c = await db.connect(); // try to connect
    c.done(); // success, release connection
    return c.client.serverVersion; // return server version
}

链接


2
当回答被写下时,还没有连接池这个概念。当前发布的版本是5.9.5,仍然使用驱动程序v5.1,它没有外部可以共享的池,只有一个全局内部池。只有6.x版本使用了最新的带有连接池的驱动程序,可以通过 db.$pool 访问。 - vitaly-t
1
@retorquere,pg-promise的6.x版本已经发布,你可以通过db.$pool访问新的池对象;) - vitaly-t
@vitaly-t,感谢您解释e.cn和在连接错误时抛出事件。我在这里提出了一个类似的问题:https://stackoverflow.com/questions/46243680/rebuilding-connections-in-nodejs-pg-promise,涉及丢弃到副本的失败连接。 - Cmag
1
@ManoharReddyPoreddy pg-promise 不会进行任何文件日志记录。 - vitaly-t
1
@ManoharReddyPoreddy 但是 pg-monitor 是一个独立的库,超出了这个问题的范围。 - vitaly-t
显示剩余7条评论

0
作为替代方案,直到我升级了pg-promise包,这些都对我没有用。

1
软件包更新与这一切有什么关系?没有任何细节,它是一个完全毫无价值的补充。 - vitaly-t

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接