Pg-promise:交易问题

时间:2017-03-07 11:08:33

标签: sql node.js transactions pg-promise

pg-promise与发电机的交易让我感到奇怪 这就是我想要的:

  1. 获取或注册用户(getOrRegisterUser)
  2. 批量生产(4个插入生成器)
  3. 最后,使用getOrRegisterCurrentParkingIfProvided generator的结果进行最后一次插入(生成器registerCall)
  4. 这是我的代码:

    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 ».',
    

    有什么方法可以解决这个问题?我试过这样的交易:https://github.com/vitaly-t/pg-promise#nested-transactionshttps://github.com/vitaly-t/pg-promise#synchronous-transactions但是在某些未知的情况下我仍然在某个地方出错。

    由于

    PS:我知道这些发电机的实施并非如此......

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

    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);
    }
    

1 个答案:

答案 0 :(得分:1)

问题出在ES6-Generator功能registerNewPhones

return t.any(findPhonesForUserQuery)...

它不会yield承诺结果,这是ES6 Generator功能所必需的。

即。它一定是:

return yield t.any(findPhonesForUserQuery)...