我有兩種進程。一個人應該寫一個文件,其他人應該讀它,如果它被改變。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
和只讀,如果它不同。