Update gitignore (sorry)

This commit is contained in:
olcxja 2026-05-10 14:02:17 +02:00
commit cca8b02fea
6604 changed files with 1219661 additions and 4 deletions

View file

@ -0,0 +1,65 @@
import { AlwaysDelay } from "./always.delay";
import { IBackOffOptions, getSanitizedOptions } from "../../options";
describe(AlwaysDelay.name, () => {
let options: IBackOffOptions;
let delay: AlwaysDelay;
function initClass() {
delay = new AlwaysDelay(options);
}
beforeEach(() => {
options = getSanitizedOptions({});
initClass();
jest.useFakeTimers();
});
it(`when calling #apply, the delay is equal to the starting delay`, async () => {
const spy = jest.fn();
delay.apply().then(spy);
jest.runTimersToTime(options.startingDelay);
await Promise.resolve();
expect(spy).toHaveBeenCalledTimes(1);
});
it(`when the attempt number is 1, when calling #apply,
the delay is equal to the starting delay multiplied by the time multiple`, async () => {
delay.setAttemptNumber(1);
const spy = jest.fn();
delay.apply().then(spy);
jest.runTimersToTime(options.startingDelay * options.timeMultiple);
await Promise.resolve();
expect(spy).toHaveBeenCalledTimes(1);
});
it(`when the attempt number is 2, when calling #apply,
the delay is equal to the starting delay multiplied by the time multiple raised by the attempt number`, async () => {
const attemptNumber = 2;
delay.setAttemptNumber(attemptNumber);
const spy = jest.fn();
delay.apply().then(spy);
jest.runTimersToTime(
options.startingDelay * Math.pow(options.timeMultiple, attemptNumber)
);
await Promise.resolve();
expect(spy).toHaveBeenCalledTimes(1);
});
it(`when the #maxDelay is less than #startingDelay, when calling #apply,
the delay is equal to the #maxDelay`, async () => {
options.maxDelay = options.startingDelay - 1;
const spy = jest.fn();
delay.apply().then(spy);
jest.runTimersToTime(options.maxDelay);
await Promise.resolve();
expect(spy).toHaveBeenCalledTimes(1);
});
});

View file

@ -0,0 +1,3 @@
import { Delay } from "../delay.base";
export class AlwaysDelay extends Delay {}

View file

@ -0,0 +1,34 @@
import { IDelay } from "./delay.interface";
import { IBackOffOptions } from "../options";
import { JitterFactory } from "../jitter/jitter.factory";
export abstract class Delay implements IDelay {
protected attempt = 0;
constructor(private options: IBackOffOptions) {}
public apply() {
return new Promise(resolve => setTimeout(resolve, this.jitteredDelay));
}
public setAttemptNumber(attempt: number) {
this.attempt = attempt;
}
private get jitteredDelay() {
const jitter = JitterFactory(this.options);
return jitter(this.delay);
}
private get delay() {
const constant = this.options.startingDelay;
const base = this.options.timeMultiple;
const power = this.numOfDelayedAttempts;
const delay = constant * Math.pow(base, power);
return Math.min(delay, this.options.maxDelay);
}
protected get numOfDelayedAttempts() {
return this.attempt;
}
}

View file

@ -0,0 +1,18 @@
import { IBackOffOptions } from "../options";
import { SkipFirstDelay } from "./skip-first/skip-first.delay";
import { AlwaysDelay } from "./always/always.delay";
import { IDelay } from "./delay.interface";
export function DelayFactory(options: IBackOffOptions, attempt: number): IDelay {
const delay = initDelayClass(options);
delay.setAttemptNumber(attempt);
return delay;
}
function initDelayClass(options: IBackOffOptions) {
if (!options.delayFirstAttempt) {
return new SkipFirstDelay(options);
}
return new AlwaysDelay(options);
}

View file

@ -0,0 +1,4 @@
export interface IDelay {
apply: () => Promise<unknown>;
setAttemptNumber: (attempt: number) => void;
}

View file

@ -0,0 +1,15 @@
import { Delay } from "../delay.base";
export class SkipFirstDelay extends Delay {
public async apply() {
return this.isFirstAttempt ? true : super.apply();
}
private get isFirstAttempt() {
return this.attempt === 0;
}
protected get numOfDelayedAttempts() {
return this.attempt - 1;
}
}