如何调试悬挂式承诺,而不是使用node-postgres解决Postgres查询?

时间:2019-04-19 14:04:13

标签: javascript node.js postgresql

我正在使用“ pg”(node-postgres)在带有Node app的Postgres DB上执行一些基本的CRUD操作。进行此特定查询时似乎有些问题-整个应用程序挂起,就像Promise永远无法解决一样。执行将在此时停止,并且不会引发错误。

在我稍稍更改数据库结构并重构代码(使其更具模块化等)之前,整个工作正常。数据库已建立并连接(使用Cloud9的Ubuntu 14.04 LTS容器),其他查询成功检查了该数据库是否存在。 失败的查询(“从清单中选择*”)通常可以正常工作-在psql CLI中键入该查询时,应得到0行的结果。因此,我最好的猜测是,异步/等待逻辑中的某些内容不正确。

// This part executes without issues
const initDB = async () => {
    try {
        await client.connect();
        console.log('Client connected to db ...');

        const checkTable = await client.query("SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'inventory')");
        if (!checkTable.rows[0].exists) {
            const table = await client.query('CREATE TABLE inventory (prod_id serial PRIMARY KEY, product_name VARCHAR (50), category TEXT, description TEXT, price REAL, width INT, depth INT, height INT, checksum TEXT, history REAL ARRAY)');
        }
    } catch (err) {
         console.log("Error initializing db.", err);   
    }
};

// This part fails
Promise.all([getProductData(productsUrlBase)]).then(async (values) => {
       // checksum = ...
       try {
          console.log('This logs on the console');
          const check = await client.query('SELECT * FROM inventory WHERE checksum=$1', [checksum]);
          console.log(check.rows, 'if this is empty, INSERT in DB!'); // Never logs on the console. App doesn't throw error, either.
    } catch (err) {
        console.log('Query error - checking / inserting items: ', err);
    }   
});
Postgres log file:
2019-04-19 12:18:53 UTC LOG:  database system was interrupted; last known up at 2019-04-19 08:39:56 UTC
2019-04-19 12:18:54 UTC LOG:  database system was not properly shut down; automatic recovery in progress
2019-04-19 12:18:54 UTC LOG:  record with zero length at 0/17A3BF8
2019-04-19 12:18:54 UTC LOG:  redo is not required
2019-04-19 12:18:54 UTC LOG:  MultiXact member wraparound protections are now enabled
2019-04-19 12:18:54 UTC LOG:  database system is ready to accept connections
2019-04-19 12:18:54 UTC LOG:  autovacuum launcher started
2019-04-19 12:18:54 UTC LOG:  incomplete startup packet

我希望至少得到Error,但是什么也没发生。您可以看到Postgres服务器日志-在我看来,那里似乎没有任何重大问题。

这是完整的GitHub回购。问题部分在./data-handlers/update.js

1 个答案:

答案 0 :(得分:1)

您的代码中有一些小问题,但除此之外,做得很好。

1)正确返回或等待承诺:
-https://github.com/kboeff/price-checker/blob/master/app.js#L63

-https://github.com/kboeff/price-checker/blob/master/data-handlers/update.js#L12

2)通过await client.connect()连接node-postgres,再次阅读文档是值得的

3)错误的循环=> https://github.com/kboeff/price-checker/blob/master/data-handlers/update.js#L18

4),该部分仍位于for循环内,该循环旨在遍历对象属性,但应位于“针对每个记录”循环https://github.com/kboeff/price-checker/blob/master/data-handlers/update.js#L28-L53

5)查询$9 https://github.com/kboeff/price-checker/blob/master/data-handlers/update.js#L36

中的值占位符缺失

您确定要一次触发所有这些查询吗?也许同步会更好。在谈论性能时,也许您应该将postgres类型的UUID用于校验和操作。

这是一个使用md5作为校验和的工作示例:

const { Client } = require('pg');
const priceAlert = require('./price-alert');
const getProductData = require('./get-product-data');
const crypto = require('crypto');

const client = new Client;

const updateDB = async (productsUrlBase, category) => {
    // connect to db
    await client.connect();
    const records = await getProductData(productsUrlBase);

    for (const record of records) {

        let checksum = '';

        for (let key in record){
            if (record.hasOwnProperty(key)) {
                if (key !== 'price') {
                    checksum += record[key] || '';
                }
            }
        }

        try {
            const md5Checksum = crypto.createHash('md5').update(checksum).digest("hex");
            const check = await client.query('SELECT * FROM inventory WHERE checksum=$1', [md5Checksum]);
            console.log(check, 'if this is empty, INSERT in DB!'); // DEBUG
            // Record not found in db, add.
            let arrLit = '{' + record.price +'}';

            if (check.rows.length === 0) {
                let rows = await client.query("INSERT INTO inventory(product_name, category, description, price, width, depth, height, checksum, history) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", [record.name, category, record.description, record.price, record.width, record.depth, record.height, md5Checksum, arrLit]);
                console.log(rows, 'INSERTED to DB.'); // DEBUG
            } else {
                // compare prices, signal for changes!
                let item = check.rows[0];
                // console.log(item);
                if (item.price !== record.price) {
                    priceAlert(item, record.price);
                    let formattedPrice = parseFloat(Math.round(record.price * 100) / 100).toFixed(2);
                    let txt = "UPDATE inventory SET price=" + formattedPrice + ", history = history||ARRAY[cast(" + formattedPrice +"as real)] WHERE checksum='" + checksum + "::uuid'";
                    let updatePrice = await client.query(txt);
                    console.log(updatePrice);

                }
            }
        } catch (err) {
            console.log('Query error - checking / inserting items: ', typeof record.price, err);
        }
    }

};

module.exports = updateDB;

此示例的列清单.checksum必须为UUID类型
alter table inventory add column checksum uuid;

PS:例如,也许还会在app.js第64行添加process.exit();