在knex查询构建器结果上同步处理

时间:2016-06-28 15:02:07

标签: javascript node.js promise knex.js

我正在编写一个批处理来构建一些日志类型条目。它将是我的API的一个单独的应用程序,它只会执行这一项任务。现在,我有一个Express API,其中包含一个logMsg传递到的端点。这些来自许多用户,每个用户每10秒左右发送一个。为了保持移动,我在logMsg上做了几个简单的操作,并将它粘贴到我的Postgres DB中。

现在我想迭代这些消息以构建一些logEntries,以便我可以更轻松地计算活动期间所花费的时间。每个logMsg在进入时,都有一个活动(或缺少一个),一个用户和一个时间戳。 LogEntry具有user,activity,startTime和endTime。这样,API应用程序可以更轻松地计算用户或活动为一组用户执行/不执行活动所花费的时间。

所以我想设置一个批处理作业,它抓取一些n个未处理的点,将它们标记为正在处理中,然后处理它们,然后将它们标记为完整。我遇到麻烦的地方就是把事情做好。

let activityLogJob = new CronJob('30 * * * * *', function() {

  return knex
    .raw() //grab a chunk of rows and mark as In Progress
    .then((processingRows) => {
        _.forEach(logMsgs, (msg) => {
            console.log('message id:', msg.id);
            return knex.select() //latest log entry for msg.user
                .then((logEntry) => {
                    if (logEntry) {
                        if (logEntry.activity_id !== msg.activity_id) {
                            console.log('new activity started. end old one');
                            return knex.transaction( (trx) => {
                                trx
                                .update() //logEntry.endTime = msg.startTime
                                .then((update) => {
                                    trx
                                    .insert(); //create new logEntry for new activity
                                });
                            });
                        }
                    } else {
                        console.log('first log entry for user');
                        knex
                        .insert(); //create new logEntry since we don't have one for the user
                    }
                })
                .then((result) => {
                    console.log('finished msg :', msg.id);
                    knex
                    .update(); //set msg.status = LOGGED
                })
                .catch((err) => {
                    logger.error("ERROR: ", err);
                });
        });     
    });

}, null, true);

所以我在上面的代码中看到的是它可以很好地抓取所有行,但是当它实际处理它们时会变得很奇怪。日志语句显示如下:

message 1
first log entry for user
message 2
first log entry for user
...
message n
first log entry for user

finished message 1
finished message 2
...
finished message n

所以我认为这里有两个问题 1.它永远不会找到现有的LogEntry并且每次都会创建一个新的LogEntry。感觉就像在处理完所有消息之后插件都没有发生 我原本期望日志语句更像是

message 1
first entry for user
finished message 1
message 2
first entry for user
finished message 2
...

我很确定我的问题是我还没有正确地绕着承诺包裹我的脑袋。

1 个答案:

答案 0 :(得分:0)

您需要返回嵌套在另一个承诺的回调中的所有承诺。如果你不这样做,那么嵌套承诺的结果就不会通过链传递。这应该有助于您的邮件同步。

return knex
.raw() //grab a chunk of rows and mark as In Progress
.then((processingRows) => {
    _.forEach(logMsgs, (msg) => {
        console.log('message id:', msg.id);
        return knex.select() //latest log entry for msg.user
            .then((logEntry) => {
                if (logEntry) {
                    if (logEntry.activity_id !== msg.activity_id) {
                        console.log('new activity started. end old one');
                        return knex.transaction( (trx) => {
                            return trx #####
                            .update() //logEntry.endTime = msg.startTime
                            .then((update) => {
                                return trx #####
                                .insert(); //create new logEntry for new activity
                            });
                        });
                    }
                } else {
                    console.log('first log entry for user');
                    return knex #####
                    .insert(); //create new logEntry since we don't have one for the user
                }
            })
            .then((result) => {
                console.log('finished msg :', msg.id);
                return knex #####
                .update(); //set msg.status = LOGGED
            })
            .catch((err) => {
                logger.error("ERROR: ", err);
            });
    });     
});