【发布时间】:2019-11-21 04:20:42
【问题描述】:
如有必要,我可以缩短我的帖子
我使用 pg-promise 事务来插入“设备”及其所有部分(如系统、磁盘等)。交易有效...但只是第一次。之后,我的服务器无法再与数据库交互(既不能插入也不能选择)。
这是包含这些步骤的 pg-monitor 输出
2019 年 7 月 11 日星期四 14:26:57 GMT+0200 (GMT+02:00):服务器正在监听 9000 14:27:11 连接(隐藏@隐藏);使用次数:0 14:27:11 插入 "public"."roles"("name") values('Test') 返回 * 14:27:11 断开连接(隐藏@隐藏) 14:27:15 连接(隐藏@隐藏);使用次数:1 14:27:15 插入 "public"."roles"("name") values('Test2') 返回 * 14:27:15 断开连接(隐藏@隐藏) 14:27:18 连接(隐藏@隐藏);使用次数:2 14:27:18 tx(插入新设备)/开始 14:27:18 tx(插入新设备):开始 14:27:18 tx(插入新设备):插入“公共”。“设备”(“制造商”)值(“HP”)返回* 14:27:18 tx(Insert-New-Device): 插入“public”.“systems”(“deviceid”,,"distributionid","archid","smanufacturer") values(15,3,2,'Microsoft公司') 返回 * 14:27:18 tx(插入新设备):提交 14:27:18 tx(插入新设备)/结束;持续时间:0.046,成功:真 14:27:18 断开连接(隐藏@隐藏) 14:27:20 连接(隐藏@隐藏);使用次数:3 14:27:20 tx(插入-新设备)/开始 14:27:20 tx(插入新设备):保存点 level_1 14:27:20 错误:SAVEPOINT 只能在事务块中使用 tx(插入新设备):保存点 level_1 14:27:20 tx(插入新设备)/结束;持续时间:0.011,成功:假 14:27:20 断开连接(隐藏@隐藏)错误
-
devices.add扔错误:SAVEPOINT 只能在交易块中使用
-
roles.add扔错误:查询已释放或丢失的连接
编辑:发现问题
问题出在我的存储库中。在 pg-promise-demo 中,每个 repos 都导出类,因此 DB 初始化使用扩展事件中的 new 关键字来创建它们。
我的回购不是课程。我试图将它们更改为类并且它可以工作
之前(不工作)
./db/repos/devices.js
'use strict';
var Database = null, pgp = null, Collections = null;
async function add(params) {
return Database.tx('Insert-New-Device', async t => {
let system = null;
const query = pgp.helpers.insert(params.data.device, Collections.insert) + " RETURNING *";
let device = await t.one(query);
// if a system is present, insert with diviceId and return
if(params.data.system) {
params.data.system.deviceid = device.deviceid;
system = await t.systems.InsertOne(params);
}
return {device, system};
})
.catch(ex => {
throw ex;
});
}
function createColumnsets() { /* hidden for brevity */ }
// rpc methods
const expose = {
'devices.insert': add
}
const DevicesRepository = {
expose, // expose methods as "rpc methods"
InsertOne: add // internal use (by another repo for example : Database.devices.InsertOne())
};
module.exports = (db, pgpLib) => {
Database = db;
pgp = pgpLib;
Collections = createColumnsets();
return DevicesRepository;
}
./db/index.js.js
'use strict';
const promise = require('bluebird');
const repos = {
Roles: require('./repos/roles'),
Systems: require('./repos/systems'),
Devices: require('./repos/devices')
}
const config = require('./conf');
const initOptions = {
promiseLib: promise,
extend(obj, dc) {
obj.roles = repos.Roles(obj, pgp);
obj.systems = repos.Systems(obj, pgp);
obj.devices = repos.Devices(obj, pgp);
}
};
const pgp = require('pg-promise')(initOptions);
const monitor = require('pg-monitor');
monitor.attach(initOptions);
const db = pgp(config);
const methods = Object.assign({}, db.roles.expose, db.systems.expose, db.devices.expose );
module.exports = {
methods
}
现在(正常工作)
devices.js
'use strict';
class RolesRepository {
constructor(db, pgp) {
this.Database = db;
this.pgp = pgp;
this.Collections = createColumnsets(pgp);
this.expose = {
'roles.insert': this.InsertOne.bind(this)
}
}
makeInsertQuery(role) {
return this.pgp.helpers.insert(role, this.Collections.insert);
}
async InsertOne(params) {
let query = this.makeInsertQuery(params.data);
if(params.return) query += " RETURNING *";
return this.Database.any(query)
.then(data => { return data; })
.catch(ex => { throw ex; });
}
}
function createColumnsets(pgp) { /* hidden for brevity */ }
module.exports = RolesRepository
./db/index.js
'use strict';
const promise = require('bluebird');
//const repos = require('./repos'); // ./repos/index.js
const repos = {
Roles: require('./roles'),
Systems: require('./systems'),
Devices: require('./devices'),
};
const config = { /* hidden */ };
const initOptions = {
promiseLib: promise,
extend(obj, dc) {
obj.roles = new repos.Roles(obj, pgp);
obj.systems = new repos.Systems(obj, pgp);
obj.devices = new repos.Devices(obj, pgp);
}
};
const pgp = require('pg-promise')(initOptions);
const monitor = require('pg-monitor');
monitor.attach(initOptions);
const db = pgp(config);
// expose db methods as rpc call
const methods = Object.assign({},
db.roles.expose,
db.systems.expose,
db.devices.expose,
);
module.exports = {
methods
}
【问题讨论】:
-
您是如何设法让库在事务之外执行保存点的?您的代码没有显示它。图书馆肯定不会这样做,这将违反所有逻辑。如果您可以创建步骤/示例来重现问题,那么您应该针对 pg-promise 库打开一个问题。
-
我不认为我要求库这样做(我不想这样做)我可以在我的帖子中添加这些文件:服务器创建、数据库初始化、repos 方法展示,...或者我可以直接打开一个问题并提供它们吗?
-
好吧,你已经设法破坏了库中多年来一直保持 100% 运行的部分。这就是为什么我很好奇你是怎么做到的。一定是非常不寻常的事情。因为库的逻辑绝对不允许它在事务之外执行保存点。
标签: node.js transactions pg-promise