fix(read-chunk): handle already errored streams

This commit is contained in:
Julien Fontanet
2023-04-08 10:52:28 +02:00
parent 4d55c5ae48
commit 955ef6806c
3 changed files with 38 additions and 2 deletions

View File

@@ -18,7 +18,9 @@ const assert = require('assert')
* @returns {Promise<Buffer|string|unknown|null>} - A Promise that resolves to the read chunk if available, or null if end of stream is reached.
*/
const readChunk = (stream, size) =>
stream.closed || stream.readableEnded
stream.errored != null
? Promise.reject(stream.errored)
: stream.closed || stream.readableEnded
? Promise.resolve(null)
: new Promise((resolve, reject) => {
if (size !== undefined) {
@@ -98,7 +100,9 @@ exports.readChunkStrict = async function readChunkStrict(stream, size) {
* @returns {Promise<number>} A Promise that resolves to the number of bytes actually skipped. If the end of the stream is reached before all bytes are skipped, the Promise resolves to the number of bytes that were skipped before the end of the stream was reached. The Promise is rejected if there is an error while reading from the stream.
*/
async function skip(stream, size) {
return size === 0 || stream.closed || stream.readableEnded
return stream.errored != null
? Promise.reject(stream.errored)
: size === 0 || stream.closed || stream.readableEnded
? Promise.resolve(0)
: new Promise((resolve, reject) => {
let left = size

View File

@@ -18,6 +18,32 @@ const rejectionOf = promise =>
error => error
)
const makeErrorTests = fn => {
it('rejects if the stream errors', async () => {
const error = new Error()
const stream = makeStream([])
const pError = rejectionOf(fn(stream, 10))
stream.destroy(error)
assert.strict(await pError, error)
})
// only supported for Node >= 18
if (process.versions.node.split('.')[0] >= 18) {
it('rejects if the stream has already errored', async () => {
const error = new Error()
const stream = makeStream([])
await new Promise(resolve => {
stream.once('error', resolve).destroy(error)
})
assert.strict(await rejectionOf(fn(stream, 10)), error)
})
}
}
describe('readChunk', () => {
it('rejects if size is less than or equal to 0', async () => {
const error = await rejectionOf(readChunk(makeStream([]), 0))
@@ -29,6 +55,8 @@ describe('readChunk', () => {
assert.strictEqual(error.code, 'ERR_ASSERTION')
})
makeErrorTests(readChunk)
it('returns null if stream is empty', async () => {
assert.strictEqual(await readChunk(makeStream([])), null)
})
@@ -83,6 +111,8 @@ describe('readChunkStrict', function () {
})
describe('skip', function () {
makeErrorTests(skip)
it('returns 0 if size is 0', async () => {
assert.strictEqual(await skip(makeStream(['foo']), 0), 0)
})

View File

@@ -16,6 +16,7 @@
- [Plugins/usage-report] Compute stats on configured period instead of the whole year (PR [#6723](https://github.com/vatesfr/xen-orchestra/pull/6723))
- [Backup] Fix `Invalid parameters` when deleting `speed limit` value (PR [#6768](https://github.com/vatesfr/xen-orchestra/pull/6768))
- [Delta Backup] Restoring a backup with memory must create a suspended VM [#5061](https://github.com/vatesfr/xen-orchestra/issues/5061) (PR [#6774](https://github.com/vatesfr/xen-orchestra/pull/6774))
- [Backup] Show original error instead of `stream has ended without data`
### Packages to release
@@ -33,6 +34,7 @@
<!--packages-start-->
- @vates/read-chunk patch
- xo-web patch
- xo-server minor
- xo-server-usage-report patch