xresilient

raw JSON →
0.8.2 verified Sat Apr 25 auth: no javascript

Builds regenerative, resumable Node.js readable streams that automatically retry on failure. Version 0.8.2 – stable, with TypeScript definitions included. Unlike manual retry logic or generic stream wrappers, xresilient tracks bytes read and supports range headers for resumable HTTP downloads. The stream can retry a user-supplied generator function a configurable number of times (default 5), emitting 'retry' and 'error' events. It extends stream.ReadableOptions, allowing custom destroyer functions and seamless integration with Node's stream pipeline. Suitable for fetching large files over unreliable networks.

error TypeError: xresilient is not a function
cause CommonJS require returns an object with default property in some bundlers.
fix
Use const xresilient = require('xresilient').default instead of require('xresilient').
error Error [ERR_STREAM_DESTROYED]: Cannot call write after a stream was destroyed
cause The underlying stream was destroyed but the generator function returned a stale stream.
fix
Ensure the generator creates a new stream each invocation, and avoid reusing destroyed streams.
error Unhandled 'error' event in xresilient stream
cause No error listener attached; errors after retries are exhausted propagate unhandled.
fix
Add retriableStream.on('error', ...) to handle final errors.
gotcha The generator function must return a Readable stream; returning a destroyed or ended stream triggers retries or ends the resilient stream.
fix Ensure fn always returns a valid, non-ended Readable stream unless you intend to end the resilient stream.
gotcha The 'error' event is only emitted after all retries are exhausted. Early errors do not surface directly.
fix Listen to the 'retry' event to be notified of errors during retries, or check retryCount in the generator.
gotcha If the underlying stream emits a 'close' event prematurely, the retry logic may not trigger because it's not an 'error' event.
fix Wrap the stream to convert 'close' into 'error' if needed, or rely only on 'error' events.
npm install xresilient
yarn add xresilient
pnpm add xresilient

Creates a resumable stream that re-fetches a file with Range header on error, piping to disk.

import xresilient from 'xresilient';
import request from 'request';
import fs from 'fs';

const retriableStream = xresilient(
  function returnStream({ bytesRead, retryCount }) {
    console.log(`Retry #${retryCount}, bytes so far: ${bytesRead}`);
    return request.get('https://example.com/file.bin', {
      headers: { Range: `bytes=${bytesRead}-` },
    });
  },
  { retries: 3 }
);

retriableStream.pipe(fs.createWriteStream('file.bin'));

retriableStream.on('retry', (slice) => {
  console.log('Retrying...', slice);
});

retriableStream.on('error', (err) => {
  console.error('Failed after retries:', err.message);
});