为基于云的API编写测试套件。我需要使用虚假用户数据为数据库建立种子 - 部分数据来自API服务器 - (在使用伪造的用户详细信息注册后,从API服务器接收API密钥和密钥)
当尝试使用带有节点的sqlite3将记录写入文件时,我尝试以一种天真的方式编写逻辑,没有任何错误检查 - 但它失败了许多SQLITE_BUSY数据库锁定错误。
然后我添加了代码以便在出现错误的情况下重试,但是不够 - 最终导致损坏的表格,所以我按照freenode上#node.js的建议添加了事务。
现在,它有效。然而问题是它很慢 - 大约50个记录需要5分钟。此外,我需要传入大约number_of_users * 2
的重试参数,以便成功完成该过程,否则它将失败。有些事情是不正确的,但我不能把它钉死。 SQLite3的性能不能这么慢。
有什么问题?
TestController.prototype.connectToDb = function () {
var db = new sqlite3.Database(this.dbpath);
return db;
}
TestController.prototype.writeUserToLocalDatabase = function (retries,username,useremail,password,api_key,api_secret, callback_after_all_users_have_been_added) {
var dbase = this.connectToDb();
var controller = this;
if (retries < 0) {
console.log("Bailing out of writeUserToLocalDatabase after max retry attempts");
return;
}
dbase.run("BEGIN TRANSACTION");
//console.log("Try #"+retries);
var stmt = dbase.prepare("insert into user_table values(?,?,?,?,?)", function(err) {
if(err !== null) {
console.log("Error when trying to write user to database in prepare! "+err);
dbase.run("ROLLBACK");
dbase.close(function(err){if(err !== null) {console.log("Close failed in in prepare "+err);}});
controller.writeUserToLocalDatabase(--retries,username,useremail,password,api_key,api_secret, callback_after_all_users_have_been_added);
}
});
stmt.run(username,useremail,password,api_key,api_secret, function(err) {
if(err !== null) {
//console.log("Error when trying to write user to database in run! "+err);
stmt.finalize();
dbase.run("ROLLBACK");
dbase.close(function(err){if(err !== null) {console.log("Close failed in in run "+err);}});
controller.writeUserToLocalDatabase(--retries,username,useremail,password,api_key,api_secret, callback_after_all_users_have_been_added);
}
else {
stmt.finalize(function(err) {
if(err !== null && err !== undefined) {
console.log("Error when trying to write user to database in finalize ! "+err);
dbase.run("ROLLBACK");
dbase.close(function(err){if(err !== null) {console.log("Close failed in in finalize "+err);}});
controller.writeUserToLocalDatabase(--retries,username,useremail,password,api_key,api_secret, callback_after_all_users_have_been_added);
}
else {
dbase.run("COMMIT");
controller.appendToUserFile(useremail,password,api_key,api_secret);
controller.pending_db_writes_for_user--;
if (controller.pending_db_writes_for_user <= 0) {
console.log("Finished writing all users, now invoking db.close with callback");
dbase.close(callback_after_all_users_have_been_added);
}
else {
console.log("Remaining users to add: "+controller.pending_db_writes_for_user);
dbase.close(function(err){if(err !== null) {console.log("Close failed in after adding user "+err);}});
}
}
});
}
});
}
更新:我能获得理智表现的唯一方法是使用async.queue限制sqlite3写入,队列大小为1。