我正在尝试使用 before/after Mocha 挂钩创建然后删除 SQLite 数据库。使用Node.js SQLite 库,我在调用 时收到“错误:EBUSY:资源繁忙或锁定...” fs.unlinkSync(DB_PATH)。
之后我可以删除该文件,因此与 Node.js SQLite 库不释放文件描述符有关。如何在同一个程序中创建然后关闭数据库连接并删除数据库文件,或者在删除文件之前程序必须退出吗?代码(Windows 10,Node.js v6.10.0):
var sqlite3 = require('sqlite3');
var fs = require('fs');
var childProc = require('child_process');
before(function() {
childProc.execSync("sqlite3 ./test_db_data/test_db.sqlite3 < ./load_data/sql/init_model.sql").toString()
});
after(function() {
fs.unlinkSync(DB_PATH);
});
describe('tests', function() {
var db;
before(function(done) {
// set up database
new Promise(function(resolve, reject) {
console.log("Running promise");
db = new sqlite3.Database(DB_PATH, sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE, function(err) {
if (err) {
throw new Error("Couldn't create test database.");
}
resolve();
});
}).then(function() {
server = app.start(DB_PATH, done);
}, function(err) {
console.log("Error opening database");
done(err);
});
});
after(function(done) {
//stop server
server.close();
// delete database
db.close(function(err) {
if (!err) {
done();
} else {
console.log(err);
throw new Error("Couldn't close database connection.");
}
});
});
Run Code Online (Sandbox Code Playgroud)
虽然.close()保证数据库本身在回调时出于读/写目的“关闭”,但不能保证操作系统立即释放文件锁。
处理这个问题最简单的方法就是循环unlink直到成功:
const fs = require("fs/promises");
...
/**
* Because we're going to have to "wait for a timeout loop"
* we can't mark this function as an async function, but it is.
* It instead explicitly returns the promise that "async" normally
* takes care of for you.
*/
function deleteDatabaseFile(db, filepath, maxRetries = 10) {
return new Promise((resolve, reject) => {
const deleteDB = async (retry = 0) => {
// Make sure we have a safety net: if ten unlink attempts
// fail in a row, something has *actually* going wrong.
if (retry > maxRetries)
return reject(new Error(`Could not delete ${filepath}`));
if (db) await db.close();
db = false;
// Try to delete the file. If we can't, schedule a retry "very soon".
try {
await fs.unlink(filepath);
resolve();
} catch (e) {
setTimeout(() => deleteDB(retry + 1), 100);
}
};
// and off we go.
deleteDB();
});
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1177 次 |
| 最近记录: |