Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pg-promise : transaction issue

I got something strange with pg-promise with a transaction with generators.
This is what I want :

  1. Get or register a user (getOrRegisterUser)
  2. Do batch stuff (4 inserts generator)
  3. Finally , do the last insert (generator registerCall) with the result of getOrRegisterCurrentParkingIfProvided generator

Here is my code :

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

I got this error message at the second generator (registerNewPhones) :

severity: 'ERREUR',
code: '23503',
detail: 'La clé (customer)=(3) n\'est pas présente dans la table « users ».',

Any way to solve this ? I tried transactions like this : https://github.com/vitaly-t/pg-promise#nested-transactions or https://github.com/vitaly-t/pg-promise#synchronous-transactions but with some unknown circumstances I still got error somewhere.

Thanks

PS: I know that the implementation of these generators aren't guilty so ...

EDIT: if you really want to see the code

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

}

and the generator 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);
}
like image 301
jy95 Avatar asked Dec 11 '25 02:12

jy95


1 Answers

The issue is within the ES6-Generator function registerNewPhones:

return t.any(findPhonesForUserQuery)...

it doesn't yield the promise result, which is required for ES6 Generator functions.

i.e. it must be:

return yield t.any(findPhonesForUserQuery)...
like image 183
vitaly-t Avatar answered Dec 13 '25 14:12

vitaly-t



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!