我有两种进程。一个人应该写一个文件,其他人应该读它,如果它被改变。nodejs:原子文件替换操作,一次只触发一次观察者
我发现fs.watch
得到通知阅读过程,如果他们必须重新加载文件。
要写入文件,我可以使用fs.writeFile
。
但我不确定,如果这是原子替换。如果文件很大,将会触发watch
几次?
什么是正确的方法,将其作为原子操作?
仅供参考:在目标系统上运行Linux。而大型文件被写入
fs.watch
的change
事件多次触发:
我有两种进程。一个人应该写一个文件,其他人应该读它,如果它被改变。nodejs:原子文件替换操作,一次只触发一次观察者
我发现fs.watch
得到通知阅读过程,如果他们必须重新加载文件。
要写入文件,我可以使用fs.writeFile
。
但我不确定,如果这是原子替换。如果文件很大,将会触发watch
几次?
什么是正确的方法,将其作为原子操作?
仅供参考:在目标系统上运行Linux。而大型文件被写入
fs.watch
的change
事件多次触发:
一些测试后,我得到了这个结果。问题是,你无法看到,最后一个发现,写入操作已经完成。
解决方案是:在同一目录中写一个临时文件,比使用link
和unlink
用新的替换旧文件。
在代码中它可能看起来像这样:
var fs = require("fs");
var path = require("path");
var consts = require('constants');
/**
* write given date in temp file and replace the dstpath with that.
*
* @author Tobias Lindig
*
* @param {string} dstpath destination path
* @param {string} data [description]
*
* @throws {Error} If fs operations failed.
*/
function atomicWrite(dstpath, data) {
// build a unique temp path
var dir = path.dirname(dstpath);
var tempName = [
'temp',
process.pid,
(Math.random() * 0x1000000000).toString(36),
new Date().getTime()
].join('-');
var tempPath = path.join(dir, tempName);
var tempOptions = {
encoding: 'utf8',
mode: 420, // aka 0644 in Octal
flags: consts.O_CREAT | consts.O_TRUNC | consts.O_RDWR | consts.O_EXCL
};
//local function to remove temp file
var fn_removeTempFileSync = function() {
try {
fs.unlinkSync(tempPath);
} catch (ex) {
// ignore fail, may be file was not created.
}
};
try {
fs.writeFileSync(tempPath, data, tempOptions);
// remove possible old version of file
// because fs.link can not overwrite existing dstpath.
if (fs.existsSync(dstpath)) {
fs.unlinkSync(dstpath);
}
//copy temp file to destination path
fs.linkSync(tempPath, dstpath);
fn_removeTempFileSync();
} catch (ex) {
fn_removeTempFileSync();
throw ex;
}
}
现在fs.watch
火灾的文件( “dstpath”)的事件change
一次。
那理论。
但在现实世界中,不幸的是,change
事件并未在任何情况下触发,有的时候它错过了。所以我也看过rename
事件。
的事件会在这个顺序:
rename
//不断,如果文件被删除 rename
//不断,文件被创建 change
//一些时间,文件被创建
阅读该文件只有一次,我会员文件的mtime
和只读,如果它不同。