From 5e2b07a9a1694cad1847f788ec70fe3bb4275eb9 Mon Sep 17 00:00:00 2001 From: Adam Davis Date: Wed, 15 Jul 2020 11:42:49 +0100 Subject: [PATCH] fs.openSync for option sync:true --- README.md | 3 +- index.js | 12 +++- test.js | 166 +++++++++++++++++++++++++++++++++++------------------- 3 files changed, 120 insertions(+), 61 deletions(-) diff --git a/README.md b/README.md index 8e985b7..2c86ec1 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,8 @@ The options are: required to be full before flushing. * `sync`: perform writes synchronously (similar to `console.log`). -A `SonicBoom` instance will emit the `'ready'` event when a file descriptor is available. +For `sync:false` a `SonicBoom` instance will emit the `'ready'` event when a file descriptor is available. +For `sync:true` the file descriptor will be available when the instance is created, before the `ready` event is fired. ### SonicBoom#write(string) diff --git a/index.js b/index.js index 1341575..93d0290 100644 --- a/index.js +++ b/index.js @@ -20,7 +20,8 @@ function openFile (file, sonic) { sonic._opening = true sonic._writing = true sonic.file = file - fs.open(file, 'a', (err, fd) => { + + function fileOpened (err, fd) { if (err) { sonic.emit('error', err) return @@ -42,7 +43,14 @@ function openFile (file, sonic) { if (len > 0 && len > sonic.minLength && !sonic.destroyed) { actualWrite(sonic) } - }) + } + + if (sonic.sync) { + const fd = fs.openSync(file, 'a') + fileOpened(null, fd) + } else { + fs.open(file, 'a', fileOpened) + } } function SonicBoom (opts) { diff --git a/test.js b/test.js index 1575d92..5699cb6 100644 --- a/test.js +++ b/test.js @@ -46,9 +46,15 @@ function buildTests (test, sync) { const fd = fs.openSync(dest, 'w') const stream = new SonicBoom({ fd, sync }) - stream.on('ready', () => { + const onReady = () => { t.pass('ready emitted') - }) + } + + if (sync) { + onReady() + } else { + stream.on('ready', onReady) + } t.ok(stream.write('hello world\n')) t.ok(stream.write('something else\n')) @@ -129,9 +135,15 @@ function buildTests (test, sync) { const dest = file() const stream = new SonicBoom({ dest, sync }) - stream.on('ready', () => { + const onReady = () => { t.pass('ready emitted') - }) + } + + if (sync) { + onReady() + } else { + stream.on('ready', onReady) + } t.ok(stream.write('hello world\n')) t.ok(stream.write('something else\n')) @@ -216,9 +228,15 @@ function buildTests (test, sync) { const dest = file() const stream = new SonicBoom({ dest, minLength: 4096, sync }) - stream.on('ready', () => { + const onReady = () => { t.pass('ready emitted') - }) + } + + if (sync) { + onReady() + } else { + stream.on('ready', onReady) + } t.ok(stream.write('hello world\n')) t.ok(stream.write('something else\n')) @@ -256,9 +274,15 @@ function buildTests (test, sync) { const fd = fs.openSync(dest, 'w') const stream = new SonicBoom({ fd, minLength: 4096, sync }) - stream.on('ready', () => { + const onReady = () => { t.pass('ready emitted') - }) + } + + if (sync) { + onReady() + } else { + stream.on('ready', onReady) + } t.ok(stream.write('hello world\n')) t.ok(stream.write('something else\n')) @@ -291,22 +315,29 @@ function buildTests (test, sync) { fs.renameSync(dest, after) stream.reopen() - stream.once('ready', () => { - t.pass('ready emitted') - t.ok(stream.write('after reopen\n')) - - stream.on('drain', () => { - fs.readFile(after, 'utf8', (err, data) => { + const onDrain = () => { + fs.readFile(after, 'utf8', (err, data) => { + t.error(err) + t.equal(data, 'hello world\nsomething else\n') + fs.readFile(dest, 'utf8', (err, data) => { t.error(err) - t.equal(data, 'hello world\nsomething else\n') - fs.readFile(dest, 'utf8', (err, data) => { - t.error(err) - t.equal(data, 'after reopen\n') - stream.end() - }) + t.equal(data, 'after reopen\n') + stream.end() }) }) - }) + } + + const onReady = () => { + t.pass('ready emitted') + t.ok(stream.write('after reopen\n')) + stream.on('drain', onDrain) + } + + stream.once('ready', onReady) + + if (sync) { + onReady() + } }) }) @@ -321,31 +352,43 @@ function buildTests (test, sync) { const after = dest + '-moved' - stream.once('ready', () => { + const innerOnReady = () => { + t.pass('ready emitted') + t.ok(stream.write('after reopen\n')) + stream.flush() + + stream.on('drain', () => { + fs.readFile(after, 'utf8', (err, data) => { + t.error(err) + t.equal(data, 'hello world\nsomething else\n') + fs.readFile(dest, 'utf8', (err, data) => { + t.error(err) + t.equal(data, 'after reopen\n') + stream.end() + }) + }) + }) + } + + const onReady = () => { t.pass('drain emitted') stream.flush() fs.renameSync(dest, after) stream.reopen() - stream.once('ready', () => { - t.pass('ready emitted') - t.ok(stream.write('after reopen\n')) - stream.flush() + if (sync) { + innerOnReady() + } else { + stream.once('ready', innerOnReady) + } + } - stream.on('drain', () => { - fs.readFile(after, 'utf8', (err, data) => { - t.error(err) - t.equal(data, 'hello world\nsomething else\n') - fs.readFile(dest, 'utf8', (err, data) => { - t.error(err) - t.equal(data, 'after reopen\n') - stream.end() - }) - }) - }) - }) - }) + if (sync) { + onReady() + } else { + stream.once('ready', onReady) + } }) test('reopen if not open', (t) => { @@ -370,8 +413,7 @@ function buildTests (test, sync) { const dest = file() const stream = new SonicBoom({ dest, minLength: 4096, sync }) - - stream.once('ready', () => { + const onReady = () => { t.pass('ready emitted') const after = dest + '-moved' stream.reopen(after) @@ -384,7 +426,13 @@ function buildTests (test, sync) { }) }) stream.end() - }) + } + + if (sync) { + onReady() + } else { + stream.once('ready', onReady) + } }) test('end after 2x reopen', (t) => { @@ -393,7 +441,7 @@ function buildTests (test, sync) { const dest = file() const stream = new SonicBoom({ dest, minLength: 4096, sync }) - stream.once('ready', () => { + const onReady = () => { t.pass('ready emitted') stream.reopen(dest + '-moved') const after = dest + '-moved-moved' @@ -407,7 +455,13 @@ function buildTests (test, sync) { }) }) stream.end() - }) + } + + if (sync) { + onReady() + } else { + stream.once('ready', onReady) + } }) test('end if not ready', (t) => { @@ -443,8 +497,7 @@ function buildTests (test, sync) { t.pass('drain emitted') stream.reopen(after) - - stream.once('ready', () => { + const onReady = () => { t.pass('ready emitted') t.ok(stream.write('after reopen\n')) @@ -459,7 +512,13 @@ function buildTests (test, sync) { }) }) }) - }) + } + + if (sync) { + onReady() + } else { + stream.once('ready', onReady) + } }) }) @@ -525,7 +584,7 @@ test('retry on EAGAIN', (t) => { }) test('retry on EAGAIN (sync)', (t) => { - t.plan(7) + t.plan(6) const fakeFs = Object.create(fs) fakeFs.writeSync = function (fd, buf, enc, cb) { @@ -543,10 +602,6 @@ test('retry on EAGAIN (sync)', (t) => { const fd = fs.openSync(dest, 'w') const stream = new SonicBoom({ fd, minLength: 0, sync: true }) - stream.on('ready', () => { - t.pass('ready emitted') - }) - t.ok(stream.write('hello world\n')) t.ok(stream.write('something else\n')) @@ -582,7 +637,6 @@ test('write buffers that are not totally written', (t) => { const dest = file() const fd = fs.openSync(dest, 'w') const stream = new SonicBoom({ fd, minLength: 0, sync: false }) - stream.on('ready', () => { t.pass('ready emitted') }) @@ -604,7 +658,7 @@ test('write buffers that are not totally written', (t) => { }) test('write buffers that are not totally written with sync mode', (t) => { - t.plan(9) + t.plan(8) const fakeFs = Object.create(fs) fakeFs.writeSync = function (fd, buf, enc) { @@ -623,10 +677,6 @@ test('write buffers that are not totally written with sync mode', (t) => { const fd = fs.openSync(dest, 'w') const stream = new SonicBoom({ fd, minLength: 0, sync: true }) - stream.on('ready', () => { - t.pass('ready emitted') - }) - t.ok(stream.write('hello world\n')) t.ok(stream.write('something else\n'))