Pg-promise: 事务问题

3

我在使用带有生成器事务的pg-promise时遇到了一些奇怪的问题。
这是我想要的:

  1. 获取或注册用户(getOrRegisterUser)
  2. 执行批量操作(4个插入生成器)
  3. 最后,使用getOrRegisterCurrentParkingIfProvided生成器的结果执行最后一个插入(generator registerCall)

这是我的代码:

db.tx(function (t) {
            return t.task.call(params, getOrRegisterUser).then(function (user) {
                params.masterId = user.id; // NOTICE : MY USER ID DATABASE
                return t.batch([
                    t.task.call(params, registerNewPhones),
                    t.task.call(params, registerNewPlate),
                    t.task.call(params, registerNewSubscriptions),
                    t.task.call(params, getOrRegisterCurrentParkingIfProvided)
                ]).then(function (result) {
                    params.ParkingId = (result[3] !== undefined) ? result[3].id : null;
                    return t.task.call(params, registerCall);
                })
            });
}).then(function () {
    // job done
    resolve();
}).catch(function (err) {
    console.log(err);
    reject(err);
});

我在第二个生成器(registerNewPhones)中收到了以下错误信息:
severity: 'ERREUR',
code: '23503',
detail: 'La clé (customer)=(3) n\'est pas présente dans la table « users ».',

有没有什么方法可以解决这个问题?我尝试了像嵌套事务或者同步事务这样的交易,但是在某些未知情况下,我仍然会在某个地方出错。

谢谢

附:我知道这些生成器的实现并不是罪魁祸首...

编辑:如果你真的想看代码

let squel = require('squel');
// squel with PostgresSQL syntax
let squelPostgres = squel.useFlavour('postgres');

registerNewPhones :

// Register all new phones numbers for user
function * registerNewPhones(t) {

    let params = t.ctx.context;

    let findPhonesForUserQuery = squelPostgres
        .select()
        .from("HELPDESK.phones")
        .field("number")
        .where("customer = ?", params.masterId)
        .toString();

    let registerPhoneForUser = squelPostgres
        .insert()
        .into("HELPDESK.phones")
        .set("customer", params.masterId);

    // find the already known phone number(s) for this user
    return t.any(findPhonesForUserQuery).then(function (result) {

        // data
        let phones = (params.hasOwnProperty("phones") ? params.phones : []);

        let alreadyRegisteredPhones = result.map(function (element) {
            return element.number;
        });

        // filter data

        let phonesToRegister = phones.filter(function (aPhoneNumber) {
            return alreadyRegisteredPhones.indexOf(aPhoneNumber) == -1;
        });

        // create queries
        let queries = phonesToRegister.map(function (phone) {
            return db.none(
                registerPhoneForUser
                    .clone()
                    .set("number", phone)
                    .toString()
            );
        });
        return t.batch(queries);
    });

}

以及生成器 getOrRegisterUser:

function * getOrRegisterUser(t) {

    let params = t.ctx.context;

    // QUERIES:
    let findUserQuery = squelPostgres
        .select()
        .from("HELPDESK.users")
        .field("id")
        .where("registered_id = ?", params.userId)
        .toString();

    let insertUserQuery = squelPostgres
        .insert()
        .into("HELPDESK.users")
        .setFields({
            name: params.userName,
            registered_id: params.userId,
            typeOfAccount: 'BASIC',
            email: params.email
        })
        .returning('id')
        .toString();

    let user = yield t.oneOrNone(findUserQuery);
    return yield user || t.one(insertUserQuery);
}

如果你连“registerNewPhones”的实现都不展示,我们怎么知道是什么导致了错误呢? :) 另外为什么你会过度使用数据库任务也不清楚。从技术角度来看,事务并不需要任何内部任务,在事务内部它们的价值不大。 - vitaly-t
你需要至少发布 getOrRegisterUserregisterNewPhones 两个函数的代码,这样才能看到你是如何出现错误的。然而,考虑到错误是数据库级别的,你的数据库逻辑很可能是问题的根源。 - vitaly-t
我刚刚添加了。正如您所看到的,我使用了squel。 - jy95
我可以看到你的 registerNewPhones 函数中的一个明显问题,它没有产生任何结果。你必须用 return yield t.any( 替换 return t.any( - vitaly-t
混合使用生成器似乎让我犯了很多错误 :( ... 你能否给出一个答案(这样我就可以感谢你的帮助)?这种情况(t.any().then() - jy95
显示剩余4条评论
1个回答

2
问题出现在 ES6-Generator 函数 registerNewPhones 中:
return t.any(findPhonesForUserQuery)...

它不能产生 ES6 Generator 函数所需的 Promise 结果。

也就是说,它必须是:

return yield t.any(findPhonesForUserQuery)...

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