fs-write-stream-atomic
Advanced tools
Comparing version 1.0.0 to 1.0.1
39
index.js
@@ -36,13 +36,33 @@ var fs = require('graceful-fs') | ||
function cleanup (er) { | ||
fs.unlink(this.__atomicTmp, function () { | ||
fs.WriteStream.prototype.emit.call(this, 'error', er) | ||
}.bind(this)) | ||
} | ||
function cleanupSync (er) { | ||
try { | ||
fs.unlinkSync(this.__atomicTmp) | ||
} finally { | ||
return fs.WriteStream.prototype.emit.call(this, 'error', er) | ||
} | ||
} | ||
// When we *would* emit 'close' or 'finish', instead do our stuff | ||
WriteStream.prototype.emit = function (ev) { | ||
if (this.__atomicDidStuff || (ev !== 'close' && ev !== 'finish')) | ||
if (ev === 'error') | ||
return cleanupSync(this) | ||
if (ev !== 'close' && ev !== 'finish') | ||
return fs.WriteStream.prototype.emit.apply(this, arguments) | ||
atomicDoStuff.call(this, function (er) { | ||
if (er) | ||
this.emit('error', er) | ||
else | ||
this.emit(ev) | ||
}.bind(this)) | ||
if (ev === 'finish') { | ||
atomicDoStuff.call(this, function (er) { | ||
if (er) | ||
cleanup.call(this, er) | ||
else | ||
fs.WriteStream.prototype.emit.call(this, 'finish') | ||
}.bind(this)) | ||
} | ||
// close will be emitted later, once we do the rename | ||
} | ||
@@ -68,3 +88,6 @@ | ||
function moveIntoPlace (cb) { | ||
fs.rename(this.__atomicTmp, this.__atomicTarget, cb) | ||
fs.rename(this.__atomicTmp, this.__atomicTarget, function (er) { | ||
cb(er) | ||
fs.WriteStream.prototype.emit.call(this, 'close') | ||
}.bind(this)) | ||
} |
{ | ||
"name": "fs-write-stream-atomic", | ||
"version": "1.0.0", | ||
"version": "1.0.1", | ||
"description": "Like `fs.createWriteStream(...)`, but atomic.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -8,3 +8,3 @@ # fs-write-stream-atomic | ||
First rule of debugging: **It's always a write condition.** | ||
First rule of debugging: **It's always a race condition.** | ||
@@ -11,0 +11,0 @@ ## USAGE |
@@ -16,3 +16,4 @@ var test = require('tap').test | ||
var s = writeStream(target) | ||
s.on('finish', verifier) | ||
s.on('finish', verifier('finish')) | ||
s.on('close', verifier('close')) | ||
streams.push(s) | ||
@@ -22,4 +23,10 @@ } | ||
var verifierCalled = 0 | ||
function verifier () { | ||
if (++verifierCalled < n) return | ||
function verifier (ev) { return function () { | ||
if (ev === 'close') | ||
t.equal(this.__emittedFinish, true) | ||
else { | ||
this.__emittedFinish = true | ||
t.equal(ev, 'finish') | ||
} | ||
// make sure that one of the atomic streams won. | ||
@@ -36,5 +43,9 @@ var res = fs.readFileSync(target, 'utf8') | ||
t.similar(res, resExpr) | ||
t.end() | ||
} | ||
// should be called once for each close, and each finish | ||
if (++verifierCalled === n * 2) { | ||
t.end() | ||
} | ||
}} | ||
// now write something to each stream. | ||
@@ -41,0 +52,0 @@ streams.forEach(function (stream, i) { |
7154
152