Pg-promise插入/事务在异步队列中不起作用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Pg-promise插入/事务在异步队列中不起作用相关的知识,希望对你有一定的参考价值。

我发现了许多与使用pg-promise和await / async相关的东西,但没有任何东西可以解决我的async(node / npm包)问题,特别是async.queue和pg-promise查询之间的交互。

我的问题:我需要异步进行几百万次计算(匹配得分),并在postgres数据库中的同一异步过程中提交结果。我的主要过程是一个承诺,首先计算表中两个记录的所有可能的不同组合,并一次将它们分成一千对的块。

这些数千对(即[[0,1],[0,2],...,[0,1000]]的块是我的块的第一个索引'内容'的数组被馈送到异步的实例。队列首先执行匹配分数的计算然后执行db记录。

几个小时让我头疼的部分是,无论是使用插入语句还是事务,db提交都不起作用。我确实知道我用于数据库部分的功能,因为我已经使用它们编写了手动测试。

我的主要代码如下:

'use strict';
const promise     = require('bluebird');
const initOptions = {
    promiseLib: promise
};
const pgp         = require('pg-promise')(initOptions);
const cn          = {connexion parameters...};
const db          = pgp(cn);
const async       = require('async');

var mainPromise = (db, php, param) => {

    return new Promise(resolve => {
        //some code computing the chunksArray using param
        ...
        var q = async.queue((chunk, done) => {

            var scores = performScoresCalculations(chunk);
            //scores is an array containing the 1000 scores for any chunk of a 1000 pairs
            performDbCommitting(db, scores);
            //commit those scores to the db using pg-promise
            done();

        }, 10);
        q.drain = () => {
            resolve(arr);
            //admittedly not quite sure about that part, haven't used async.queue much so far
        }
        q.push(chunksArray);
    )}.catch(err => {
        console.error(err);
    });

};

现在我的分数数组看起来像这样:

[{column1:'value1_0',column2:'value2_0',...,columnN:'valueN_0'},...,{column1:'value1_999',column2:'value2_999',column3:'value3_999'}],其中有一千条记录。

我的performDbCommitting函数如下:

var performDbCommitting = (db, pgp, scores) => {

    console.log('test1');
    //displays 'test1', as expected
    var query = pgp.helpers.insert(scores, ['column1', 'column2', 'column3'], 'myScoreTable');
    console.log(query);
    //display the full content of the query, as expected
    db.any(query).then(data => {
        console.log('test2');
        //nothing is displayed
        console.log(data);
        //nothing is displayed
        return;
    }).catch(err => {
        console.error(err);
    });

}

所以这是我的问题:

  • 当“手动”执行测试时,DbCommitting工作完美,我甚至尝试了一个带有交易的版本,同样的工作完美无瑕,
  • 当在async.queue中使用时,performDbCommitting中的所有内容似乎都在db.any(query)调用之前工作,正如console.log在此之前正确显示信息所证明的那样,
  • 没有错误被抛出,chunksArray上的计算按预期继续按1000组进行,
  • 如果我检查任何数组(chunk,chunksArray,得分等),一切都是应该的,长度是正确的,它们的内容也是如此。

当与async.queue一起使用时,pg-promise似乎并不想在数据库中一次推送我的1000条记录,这就是我被困住的地方。我毫不费力地想象我的错误在于它,这是我第一次使用async.queue,特别是混合了bluebird有希望和pg-promise。

非常感谢您提前花时间阅读本文,并在可能的情况下阐明这个问题。

答案

您的mainPromise不会等待performDBCommitting完成:

应该是这样的:

//commit those scores to the db using pg-promise
performDbCommitting(db, scores).then(()=>{done();});

并且执行DBCommitting也需要返回承诺:

return db.any(query).then(data => {
    console.log('test2');
    //nothing is displayed
    console.log(data);
    //nothing is displayed
    return null;
}).catch(err => {
    console.error(err);
    return null;
});

以上是关于Pg-promise插入/事务在异步队列中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

事务注释在 Spring Boot 中不起作用

事务在 laravel 中不起作用

事务注释在 Spring Boot 2.1.3 中不起作用

异步 Web 请求在 WCF 中不起作用

Console.log 在异步函数中不起作用

数据库事务在控制器 codeigniter 中不起作用