npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

dread

v2.3.0

Published

yet another retry library

Downloads

168

Readme

dread

When you just know things will fail

Usage

const dread = require('dread');

The most basic, batteries-included example:

// this will retry 10 times with fully randomized and truncated exponential backoff
dread(function() {
  // do stuff
});

You can also provide options to override retry logic:

dread({ attempts: 3 }, function() {
  // same as above, but with only 3 attempts just for this task
});

You can also provide options as the only argument, which returns a reconfigured instance of dread:

const retry = dread({ attempts: 3 });

retry(function() {
  // this is a task, 3 attempts
})
retry(function() {
  // this is a different task, still 3 attempts
});
dread(function() {
  // this still uses the default configuratiopn
});

The order that you provide arguments does not matter - you can call dread(task, options) or dread(options, task).

Options

The default configuration is equivalent to:

dread({
  attempts: 10,
  condition: dread.prop('retryable'),
  backoff: dread.exp(),
  timeout: undefined,
});

attempts

The number of attempts inclusive of the first one

// fewer attempts than default
dread({ attempts: 5 });

You can also call it retries instead, but note this is not inclusive. So dread({ attempts: 5}) is the same as dread({ retries: 4 })

condition

A function Error => Boolean that determines whether or not to retry a failed attempt.

You can provide any function you want, including async.

dread exports helpers:

  • dread.prop(name) rery if err.prop is truthy
  • dread.code(String) retry if err.code === String
  • dread.is(Class) retry if err instanceof Class
  • dread.always() always retry every error

backoff

A function (Integer, Error) => Integer that returns the amount of time to wait before the next attempt.

You can provide any function you want, including async. The Error is provided in case you want to have different retry periods for different error cases, or, as in the case of aws-sdk, it already provides a backoff duration on its errors.

dread exports a helper:

// this is the default - a fully randomized, truncated exponential value
dread.exp({
    base: Number(100),
    factor: Number(2),
    limit: Number(10000),
    jitter: JitterType.FULL
});

jitter may be one of:

  • JitterType.NONE the full backoff value is used
  • JitterType.FULL a randomized value between 0 and the full backoff
  • JitterType.HALF a randomized valued between full backoff / 2 and full backoff

timeout

dread supports a timeout for the entire operation

const retry = dread({ timeout: 10000 });
// the operation will timeout after 10 seconds
// regardless of the number of attempts or how long the current attempt takes
retry(function() {
  // ...
});

Attempt Object

Your task is invoked with an attempt object as the only argument.

dread(attempt => {
  console.log('attempt number', attempt.number);
  attempt.cancel('things are going haywire!'); // will retry
});

number

number is the number of the current attempt (1, 2, 3, etc.) - it can also be accessed via the property attempt.attempt, which seems like a strange name, but it's so that you can destructure it like:

dread(({ attempt }) => {
  logger.info({ attempt }, 'trying something'); // { attempt: 1, msg: 'trying something' }
});

timeout(value)

// this attempt will timeout after 1 second, inclusive of the backoff delay
attempt.timeout(5000);
// you could also set a timeout based on the attempt nuber
attempt.timeout(attempt.number * 2000);

Setting a timeout after an attempt has succeeded has no effect;

cancel(reason)

You can cancel an attempt manually by calling attempt.cancel(reason) optionally providing either an Error or a String, which will be used as the error message.

dread(attempt => {
  // will reject with new Error('Cancelled')
  attempt.cancel();
  // will reject with new Error('Try again')
  attempt.cancel('Try again');
  // will reject with MyCustomError
  attempt.cancel(new MyCustomError());
});

Calling cancel after an attempt has succeeded has no effect.