1.3.1 • Published 2 years ago

@webinmove/nyuma v1.3.1

Weekly downloads
-
License
MIT
Repository
github
Last release
2 years ago

Nyuma

Continuous Integration Coverage Status npm version Dependency Status

Description

Nyuma means "back" in Swahili. It is an async retry implementation with fibonacci or exponential strategy.

Motivation

All the backoff implementation I came accross where missing on key feature: a maximum overall time option.

Installation

$ npm install @webinmove/nyuma

Usage

Basic real life

const { fibonacci } = require('@webinmove/nyuma');
const fetch = require('node-fetch');

const main = async () => {
  const nyuma = fibonacci({ initialDelay: 100, maxTime: 60000 });

  try {
    // Here we'll only retry on real network error
    const response = await nyuma.start(() =>
      fetch('https://api.github.com/repos/webinmove/nyuma')
    );
    console.log(await response.json());
  } catch (err) {
    // Couldn't get the response in less than a minute...
    console.error(err);
  }
};

main();

With another strategy and more options

const { exponential } = require('@webinmove/nyuma');
const fetch = require('node-fetch');

const main = async () => {
  const nyuma = exponential({
    initialDelay: 100,
    maxDelay: 10000,
    maxRetries: 3,
    maxTime: 60000,
    maxTimeError: 'First fetch was too long',
    factor: 3
  });

  try {
    const body = await nyuma
      .retryHook(({ error, retryCount, lastDelay, duration }) =>
        console.log('Retry with:', { error, retryCount, lastDelay, duration })
      )
      .failHook(({ reason, retryCount, lastDelay, duration }) =>
        console.log('Failed with:', { reason, retryCount, lastDelay, duration })
      )
      .start(async () => {
        const response = await fetch('https://api.github.com/repos/webinmove/nyuma');
        if (response.status >= 400) {
          throw new Error(`Call responded with status ${response.status}`);
        }

        return response.json();
      });

    console.log(body);
  } catch (err) {
    // Couldn't get the response in less than a minute or 5 retries...
    console.error(err);
  }
};

main();

Using base classes

const { Nyuma, ExponentialStrategy } = require('@webinmove/nyuma');

const fetch = require('node-fetch');

const main = async () => {
  const strategy = new ExponentialStrategy({ factor: 3 });
  const nyuma = new Nyuma({
    strategy,
    initialDelay: 100,
    maxDelay: 10000,
    maxRetries: 3,
    maxTime: 60000
  });

  nyuma.failHook(({ reason, retryCount, lastDelay, duration }) =>
    console.log({ reason, retryCount, lastDelay, duration })
  );

  try {
    const body = await nyuma.start(async () => {
      const response = await fetch('https://api.github.com/repos/webinmove/nyuma');
      if (response.status >= 400) {
        throw new Error(`Call responded with status ${response.status}`);
      }

      return response.json();
    });

    console.log(body);
  } catch (err) {
    // Couldn't get the response in less than a minute or 5 retries...
    console.error(err);
  }
};

main();

API

fibonacci(params)

Returns a Nyuma instance initialized with the fibonacci strategy and the params.

params

  • initialDelay: delay in ms for the first retry (required)
  • maxDelay: maximum delay can reach before a retry (optional, default Infinity)
  • maxRetries: maximum retries before throwing the last error encounter (optional, default Infinity)
  • maxTime: maximum time for the first try and all retries before throwing the last error encounter or a specific error if the first try was too long (optional, default Infinity)
  • maxTimeError: error message in case the first try was too long (optional, dafault "First try reached max time")

Note: you should specify at least a maxRetries or a maxTime

exponential(params)

Returns a Nyuma instance initialized with the exponential strategy and the params.

params

  • factor: exponential factor used to compute the delays (optional, default 2)
  • initialDelay: delay in ms for the first retry (required)
  • maxDelay: maximum delay can reach before a retry (optional, default Infinity)
  • maxRetries: maximum retries before throwing the last error encounter (optional, default Infinity)
  • maxTime: maximum time for the first try and all retries before throwing the last error encounter or a specific error if the first try was too long (optional, default Infinity)
  • maxTimeError: error message in case the first try was too long (optional, dafault "First try reached max time")

Note: you should specify at least a maxRetries or a maxTime

Class Nyuma

constructor(params)

Returns a Nyuma instance initialized with the params.

params

  • strategy: a strategy instance (optional, default exponentialStrategy)
  • initialDelay: delay in ms for the first retry (required)
  • maxDelay: maximum delay can reach before a retry (optional, default Infinity)
  • maxRetries: maximum retries before throwing the last error encounter (optional, default Infinity)
  • maxTime: maximum time for the first try and all retries before throwing the last error encounter or a specific error if the first try was too long (optional, default Infinity)
  • maxTimeError: error message in case the first try was too long (optional, dafault "First try reached max time")

Note: you should specify at least a maxRetries or a maxTime

start(fn)

Start the retry process retruning a promise of the fn result.

  • fn: a function that will be retry until sucess or a maximum reached (required)

When called this function will have 2 arguments:

  • retryCount: number of retry already done
  • lastDelay: delay between the previous retry and the current

exemple:

const { Nyuma, FibonacciStrategy } = require('@webinmove/nyuma');

const main = async () => {
  const strategy = new FibonacciStrategy();
  const nyuma = new Nyuma({ strategy, initialDelay: 10, maxRetries: 10 });

  await nyuma.start(async (retryCount, lastDelay) => {
    console.log(`${retryCount} ${lastDelay} ms`);
    throw new Error('Try again!');
  }
  );
};

main();

will output:

0 0 ms
1 10 ms
2 10 ms
3 20 ms
4 30 ms
5 50 ms
6 80 ms
7 130 ms
8 210 ms
9 340 ms
10 550 ms
(node:51869) UnhandledPromiseRejectionWarning: Error: Try again!

failHook(fn)

Set a function on fail hook function.

  • fn: a function that will be called on fail.

When called this function will have 1 argument:

  • params: object containing
    • reason: string with the fail reason (e.g. "Maximum retry reached" or "Maximum time reached")
    • retryCount: number of retry done until fail
    • lastDelay: last retry delay in ms
    • duration: overall duration before fail in ms

Class ExponentialStrategy

constructor(params)

Returns a ExponentialStrategy instance initialized with the params.

params

  • factor: the multiplicator factor, should be >= 1 (optional, default 2)

next()

Retruns the next iteration of the exponential sequence (e.g.: 1, 2, 4, 8, ...).

Class FibonacciStrategy

constructor()

Returns a FibonacciStrategy instance initialized with the params.

next()

Retruns the next iteration of the fibonacci sequence (e.g.: 1, 1, 2, 3, 5, 8, ...).

Npm scripts

Running code formating

$ npm run format

Running tests

$ npm run test:spec

Running lint tests

$ npm run test:lint

Running coverage tests

$ npm run test:cover

This will create a coverage folder with all the report in coverage/index.html

Running all tests

$ npm test

Note: that's the one you want to use most of the time

Reporting bugs and contributing

If you want to report a bug or request a feature, please open an issue. If want to help us improve nyuma, fork and make a pull request. Please use commit format as described here. And don't forget to run npm run format before pushing commit.

1.3.1

2 years ago

1.3.0

4 years ago

1.2.0

4 years ago

1.1.1

4 years ago

1.0.4

4 years ago

1.0.3

4 years ago

1.0.2

4 years ago

1.0.1

4 years ago

1.0.0

4 years ago