From 83bb22cd032da93735b43d1599b29219806407f5 Mon Sep 17 00:00:00 2001 From: isaacs Date: Mon, 2 Aug 2021 16:21:35 -0700 Subject: [PATCH] WriteEntry backpressure --- lib/write-entry.js | 28 ++++++++++++++++++++++------ test/write-entry.js | 18 +++++++++++++++++- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/lib/write-entry.js b/lib/write-entry.js index 1a77f769..c47ef9ce 100644 --- a/lib/write-entry.js +++ b/lib/write-entry.js @@ -24,6 +24,8 @@ const OPENFILE = Symbol('openfile') const ONOPENFILE = Symbol('onopenfile') const CLOSE = Symbol('close') const MODE = Symbol('mode') +const AWAITDRAIN = Symbol('awaitDrain') +const ONDRAIN = Symbol('ondrain') const warner = require('./warn-mixin.js') const winchars = require('./winchars.js') const stripAbsolutePath = require('./strip-absolute-path.js') @@ -226,7 +228,7 @@ const WriteEntry = warner(class WriteEntry extends MiniPass { this.pos = 0 this.remain = this.stat.size this.length = this.buf.length - this[READ](this.stat.size) + this[READ]() } [READ] () { @@ -278,13 +280,23 @@ const WriteEntry = warner(class WriteEntry extends MiniPass { const writeBuf = this.offset === 0 && bytesRead === this.buf.length ? this.buf : this.buf.slice(this.offset, this.offset + bytesRead) - this.remain -= bytesRead - this.blockRemain -= bytesRead - this.pos += bytesRead - this.offset += bytesRead + this.remain -= writeBuf.length + this.blockRemain -= writeBuf.length + this.pos += writeBuf.length + this.offset += writeBuf.length + + const flushed = this.write(writeBuf) + if (!flushed) + this[AWAITDRAIN](() => this[ONDRAIN]()) + else + this[ONDRAIN]() + } - this.write(writeBuf) + [AWAITDRAIN] (cb) { + this.once('drain', cb) + } + [ONDRAIN] () { if (!this.remain) { if (this.blockRemain) this.write(Buffer.alloc(this.blockRemain)) @@ -338,6 +350,10 @@ class WriteEntrySync extends WriteEntry { } } + [AWAITDRAIN] (cb) { + cb() + } + [CLOSE] (cb) { fs.closeSync(this.fd) cb() diff --git a/test/write-entry.js b/test/write-entry.js index 7e6f5904..5354a66e 100644 --- a/test/write-entry.js +++ b/test/write-entry.js @@ -229,6 +229,22 @@ t.test('zero-byte file', t => { }) }) +t.test('zero-byte file, but close fails', t => { + const poop = new Error('poop') + t.tearDown(mutateFS.fail('close', poop)) + + const ws = new WriteEntry('files/1024-bytes.txt', { cwd: fixtures }) + + ws.on('end', _ => + t.fail('should not get an end, because the close fails')) + + ws.on('error', er => { + t.match(er, { message: 'poop' }) + t.end() + }) + ws.resume() +}) + t.test('hardlinks', t => { const h1 = 'hardlink-1' const h2 = 'hardlink-2' @@ -573,7 +589,7 @@ t.test('read overflow expectation', t => { new WriteEntry(f, { cwd: files, maxReadSize: 2 }).on('error', er => { t.match(er, expect) t.end() - }) + }).resume() }) t.test('short reads', t => {