Pg-promise : 交易问题
Pg-promise : transaction issue
我对 pg-promise 与生成器的交易感到奇怪。
这就是我想要的:
- 获取或注册用户 (getOrRegisterUser)
- 做批处理(4 个插入生成器)
- 最后,使用 getOrRegisterCurrentParkingIfProvided generator
的结果进行最后一次插入(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 ».',
有什么办法可以解决吗?我试过这样的交易:https://github.com/vitaly-t/pg-promise#nested-transactions or https://github.com/vitaly-t/pg-promise#synchronous-transactions 但在某些未知情况下我仍然在某处出错。
谢谢
PS:我知道这些生成器的实现是无罪的,所以...
编辑:如果你真的想看代码
let squel = require('squel');
// squel with PostgresSQL syntax
let squelPostgres = squel.useFlavour('postgres');
注册新手机:
// 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);
}
问题出在 ES6-Generator 函数中 registerNewPhones
:
return t.any(findPhonesForUserQuery)...
它不是 yield
承诺结果,这是 ES6 生成器函数所必需的。
即它必须是:
return yield t.any(findPhonesForUserQuery)...
我对 pg-promise 与生成器的交易感到奇怪。
这就是我想要的:
- 获取或注册用户 (getOrRegisterUser)
- 做批处理(4 个插入生成器)
- 最后,使用 getOrRegisterCurrentParkingIfProvided generator 的结果进行最后一次插入(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 ».',
有什么办法可以解决吗?我试过这样的交易:https://github.com/vitaly-t/pg-promise#nested-transactions or https://github.com/vitaly-t/pg-promise#synchronous-transactions 但在某些未知情况下我仍然在某处出错。
谢谢
PS:我知道这些生成器的实现是无罪的,所以...
编辑:如果你真的想看代码
let squel = require('squel');
// squel with PostgresSQL syntax
let squelPostgres = squel.useFlavour('postgres');
注册新手机:
// 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);
}
问题出在 ES6-Generator 函数中 registerNewPhones
:
return t.any(findPhonesForUserQuery)...
它不是 yield
承诺结果,这是 ES6 生成器函数所必需的。
即它必须是:
return yield t.any(findPhonesForUserQuery)...