Comparing version 0.1.4 to 0.1.5
# Changelog | ||
## 0.1.5 - 2019-03-01 | ||
- **feat**: add `.dangerouslyUnref` methods for timeouts and retries ([#11](https://github.com/connor4312/cockatiel/issues/11), thanks to [@novemberborn](https://github.com/novemberborn)) | ||
## 0.1.4 - 2019-02-24 | ||
@@ -4,0 +8,0 @@ |
@@ -25,2 +25,7 @@ import { IBackoff, IExponentialBackoffOptions } from './backoff/Backoff'; | ||
backoff?: IBackoff<IRetryBackoffContext<unknown>>; | ||
/** | ||
* Whether to unreference the internal timer. This means the policy will not | ||
* keep the Node.js even loop active. Defaults to `false`. | ||
*/ | ||
unref?: boolean; | ||
} | ||
@@ -48,3 +53,3 @@ export declare class RetryPolicy implements IPolicy<IRetryContext> { | ||
readonly onGiveUp: import("./common/Event").Event<FailureReason<unknown>>; | ||
constructor(options: IRetryPolicyConfig); | ||
constructor(options: Readonly<IRetryPolicyConfig>); | ||
/** | ||
@@ -54,3 +59,3 @@ * Sets the number of retry attempts for the function. | ||
*/ | ||
attempts(count: number): this; | ||
attempts(count: number): RetryPolicy; | ||
/** | ||
@@ -60,16 +65,23 @@ * Sets the delay between retries. Can be a single duration, of a list of | ||
*/ | ||
delay(amount: number | ReadonlyArray<number>): this; | ||
delay(amount: number | ReadonlyArray<number>): RetryPolicy; | ||
/** | ||
* Sets the baackoff to use for retries. | ||
*/ | ||
delegate<S>(backoff: DelegateBackoffFn<IRetryBackoffContext<unknown>, S>): this; | ||
delegate<S>(backoff: DelegateBackoffFn<IRetryBackoffContext<unknown>, S>): RetryPolicy; | ||
/** | ||
* Uses an exponential backoff for retries. | ||
*/ | ||
exponential<S>(options: Partial<IExponentialBackoffOptions<S>>): this; | ||
exponential<S>(options: Partial<IExponentialBackoffOptions<S>>): RetryPolicy; | ||
/** | ||
* Sets the baackoff to use for retries. | ||
*/ | ||
backoff(backoff: IBackoff<IRetryBackoffContext<unknown>>): this; | ||
backoff(backoff: IBackoff<IRetryBackoffContext<unknown>>): RetryPolicy; | ||
/** | ||
* When retrying, a referenced timer is created. This means the Node.js event | ||
* loop is kept active while we're delaying a retried call. Calling this | ||
* method on the retry builder will unreference the timer, allowing the | ||
* process to exit even if a retry might still be pending. | ||
*/ | ||
dangerouslyUnref(): RetryPolicy; | ||
/** | ||
* Executes the given function with retries. | ||
@@ -81,2 +93,3 @@ * @param fn -- Function to run | ||
private composeBackoff; | ||
private derivePolicy; | ||
} |
@@ -8,3 +8,8 @@ import { ExponentialBackoff } from './backoff/Backoff'; | ||
import { execute } from './common/execute'; | ||
const delay = (duration) => new Promise(resolve => setTimeout(resolve, duration)); | ||
const delay = (duration, unref) => new Promise(resolve => { | ||
const timer = setTimeout(resolve, duration); | ||
if (unref) { | ||
timer.unref(); | ||
} | ||
}); | ||
export class RetryPolicy { | ||
@@ -60,2 +65,11 @@ constructor(options) { | ||
/** | ||
* When retrying, a referenced timer is created. This means the Node.js event | ||
* loop is kept active while we're delaying a retried call. Calling this | ||
* method on the retry builder will unreference the timer, allowing the | ||
* process to exit even if a retry might still be pending. | ||
*/ | ||
dangerouslyUnref() { | ||
return this.derivePolicy({ ...this.options, unref: true }); | ||
} | ||
/** | ||
* Executes the given function with retries. | ||
@@ -74,3 +88,3 @@ * @param fn -- Function to run | ||
const delayDuration = backoff.duration(); | ||
const delayPromise = delay(delayDuration); | ||
const delayPromise = delay(delayDuration, !!this.options.unref); | ||
// A little sneaky reordering here lets us use Sinon's fake timers | ||
@@ -94,6 +108,11 @@ // when we get an emission in our tests. | ||
} | ||
this.options = { ...this.options, backoff }; | ||
return this; | ||
return this.derivePolicy({ ...this.options, backoff }); | ||
} | ||
derivePolicy(newOptions) { | ||
const p = new RetryPolicy(newOptions); | ||
p.onGiveUp(evt => this.onGiveUpEmitter.emit(evt)); | ||
p.onRetry(evt => this.onRetryEmitter.emit(evt)); | ||
return p; | ||
} | ||
} | ||
//# sourceMappingURL=RetryPolicy.js.map |
import { expect, use } from 'chai'; | ||
import { stub, useFakeTimers } from 'sinon'; | ||
import { noJitterGenerator } from './backoff/Backoff'; | ||
import { runInChild } from './common/util.test'; | ||
import { Policy } from './Policy'; | ||
@@ -124,3 +125,30 @@ use(require('sinon-chai')); | ||
}); | ||
it('does not unref by default', async () => { | ||
const output = await runInChild(` | ||
Policy.handleAll() | ||
.retry() | ||
.attempts(1) | ||
.delay(1) | ||
.execute(() => { | ||
console.log('attempt'); | ||
throw new Error('oh no!'); | ||
}); | ||
`); | ||
expect(output).to.contain('oh no!'); | ||
}); | ||
it('unrefs as requested', async () => { | ||
const output = await runInChild(` | ||
Policy.handleAll() | ||
.retry() | ||
.dangerouslyUnref() | ||
.attempts(1) | ||
.delay(1) | ||
.execute(() => { | ||
console.log('attempt'); | ||
throw new Error('oh no!'); | ||
}); | ||
`); | ||
expect(output).to.equal('attempt'); | ||
}); | ||
}); | ||
//# sourceMappingURL=RetryPolicy.test.js.map |
@@ -20,2 +20,3 @@ import { CancellationToken } from './CancellationToken'; | ||
private readonly strategy; | ||
private readonly unref; | ||
private readonly timeoutEmitter; | ||
@@ -26,4 +27,12 @@ /** | ||
readonly onTimeout: import("./common/Event").Event<void>; | ||
constructor(duration: number, strategy: TimeoutStrategy); | ||
constructor(duration: number, strategy: TimeoutStrategy, unref?: boolean); | ||
/** | ||
* When timing out, a referenced timer is created. This means the Node.js | ||
* event loop is kept active while we're waiting for the timeout, as long as | ||
* the function hasn't returned. Calling this method on the timeout builder | ||
* will unreference the timer, allowing the process to exit even if a | ||
* timeout might still be happening. | ||
*/ | ||
dangerouslyUnref(): TimeoutPolicy; | ||
/** | ||
* Executes the given function. | ||
@@ -30,0 +39,0 @@ * @param fn -- Function to execute. Takes in a nested cancellation token. |
@@ -17,5 +17,6 @@ import { CancellationTokenSource } from './CancellationToken'; | ||
export class TimeoutPolicy { | ||
constructor(duration, strategy) { | ||
constructor(duration, strategy, unref = false) { | ||
this.duration = duration; | ||
this.strategy = strategy; | ||
this.unref = unref; | ||
this.timeoutEmitter = new EventEmitter(); | ||
@@ -29,2 +30,14 @@ /** | ||
/** | ||
* When timing out, a referenced timer is created. This means the Node.js | ||
* event loop is kept active while we're waiting for the timeout, as long as | ||
* the function hasn't returned. Calling this method on the timeout builder | ||
* will unreference the timer, allowing the process to exit even if a | ||
* timeout might still be happening. | ||
*/ | ||
dangerouslyUnref() { | ||
const t = new TimeoutPolicy(this.duration, this.strategy, true); | ||
t.onTimeout(() => this.timeoutEmitter.emit()); | ||
return t; | ||
} | ||
/** | ||
* Executes the given function. | ||
@@ -37,2 +50,5 @@ * @param fn -- Function to execute. Takes in a nested cancellation token. | ||
const timer = setTimeout(() => cts.cancel(), this.duration); | ||
if (this.unref) { | ||
timer.unref(); | ||
} | ||
try { | ||
@@ -39,0 +55,0 @@ if (this.strategy === TimeoutStrategy.Cooperative) { |
import { expect } from 'chai'; | ||
import { promisify } from 'util'; | ||
import { defer } from './common/defer'; | ||
import { runInChild } from './common/util.test'; | ||
import { TaskCancelledError } from './errors/TaskCancelledError'; | ||
@@ -23,3 +24,3 @@ import { Policy } from './Policy'; | ||
it('properly aggressively cancels', async () => { | ||
const policy = Policy.timeout(2, TimeoutStrategy.Aggressive); | ||
const policy = Policy.timeout(5, TimeoutStrategy.Aggressive); | ||
const verified = defer(); | ||
@@ -29,3 +30,3 @@ await expect(policy.execute(async ({ cancellation }) => { | ||
expect(cancellation.isCancellationRequested).to.be.false; | ||
await delay(3); | ||
await delay(5); | ||
expect(cancellation.isCancellationRequested).to.be.true; | ||
@@ -37,3 +38,20 @@ verified.resolve(undefined); | ||
}); | ||
it('does not unref by default', async () => { | ||
// this would timeout if the timers were referenced | ||
const output = await runInChild(` | ||
Policy.timeout(100, 'aggressive') | ||
.execute(() => new Promise(() => {})); | ||
`); | ||
expect(output).to.contain('Operation cancelled'); | ||
}); | ||
it('unrefs as requested', async () => { | ||
// this would timeout if the timers were referenced | ||
const output = await runInChild(` | ||
Policy.timeout(60 * 1000, 'aggressive') | ||
.dangerouslyUnref() | ||
.execute(() => new Promise(() => {})); | ||
`); | ||
expect(output).to.be.empty; | ||
}); | ||
}); | ||
//# sourceMappingURL=TimeoutPolicy.test.js.map |
@@ -25,2 +25,7 @@ import { IBackoff, IExponentialBackoffOptions } from './backoff/Backoff'; | ||
backoff?: IBackoff<IRetryBackoffContext<unknown>>; | ||
/** | ||
* Whether to unreference the internal timer. This means the policy will not | ||
* keep the Node.js even loop active. Defaults to `false`. | ||
*/ | ||
unref?: boolean; | ||
} | ||
@@ -48,3 +53,3 @@ export declare class RetryPolicy implements IPolicy<IRetryContext> { | ||
readonly onGiveUp: import("./common/Event").Event<FailureReason<unknown>>; | ||
constructor(options: IRetryPolicyConfig); | ||
constructor(options: Readonly<IRetryPolicyConfig>); | ||
/** | ||
@@ -54,3 +59,3 @@ * Sets the number of retry attempts for the function. | ||
*/ | ||
attempts(count: number): this; | ||
attempts(count: number): RetryPolicy; | ||
/** | ||
@@ -60,16 +65,23 @@ * Sets the delay between retries. Can be a single duration, of a list of | ||
*/ | ||
delay(amount: number | ReadonlyArray<number>): this; | ||
delay(amount: number | ReadonlyArray<number>): RetryPolicy; | ||
/** | ||
* Sets the baackoff to use for retries. | ||
*/ | ||
delegate<S>(backoff: DelegateBackoffFn<IRetryBackoffContext<unknown>, S>): this; | ||
delegate<S>(backoff: DelegateBackoffFn<IRetryBackoffContext<unknown>, S>): RetryPolicy; | ||
/** | ||
* Uses an exponential backoff for retries. | ||
*/ | ||
exponential<S>(options: Partial<IExponentialBackoffOptions<S>>): this; | ||
exponential<S>(options: Partial<IExponentialBackoffOptions<S>>): RetryPolicy; | ||
/** | ||
* Sets the baackoff to use for retries. | ||
*/ | ||
backoff(backoff: IBackoff<IRetryBackoffContext<unknown>>): this; | ||
backoff(backoff: IBackoff<IRetryBackoffContext<unknown>>): RetryPolicy; | ||
/** | ||
* When retrying, a referenced timer is created. This means the Node.js event | ||
* loop is kept active while we're delaying a retried call. Calling this | ||
* method on the retry builder will unreference the timer, allowing the | ||
* process to exit even if a retry might still be pending. | ||
*/ | ||
dangerouslyUnref(): RetryPolicy; | ||
/** | ||
* Executes the given function with retries. | ||
@@ -81,2 +93,3 @@ * @param fn -- Function to run | ||
private composeBackoff; | ||
private derivePolicy; | ||
} |
@@ -10,3 +10,8 @@ "use strict"; | ||
const execute_1 = require("./common/execute"); | ||
const delay = (duration) => new Promise(resolve => setTimeout(resolve, duration)); | ||
const delay = (duration, unref) => new Promise(resolve => { | ||
const timer = setTimeout(resolve, duration); | ||
if (unref) { | ||
timer.unref(); | ||
} | ||
}); | ||
class RetryPolicy { | ||
@@ -62,2 +67,11 @@ constructor(options) { | ||
/** | ||
* When retrying, a referenced timer is created. This means the Node.js event | ||
* loop is kept active while we're delaying a retried call. Calling this | ||
* method on the retry builder will unreference the timer, allowing the | ||
* process to exit even if a retry might still be pending. | ||
*/ | ||
dangerouslyUnref() { | ||
return this.derivePolicy({ ...this.options, unref: true }); | ||
} | ||
/** | ||
* Executes the given function with retries. | ||
@@ -76,3 +90,3 @@ * @param fn -- Function to run | ||
const delayDuration = backoff.duration(); | ||
const delayPromise = delay(delayDuration); | ||
const delayPromise = delay(delayDuration, !!this.options.unref); | ||
// A little sneaky reordering here lets us use Sinon's fake timers | ||
@@ -96,7 +110,12 @@ // when we get an emission in our tests. | ||
} | ||
this.options = { ...this.options, backoff }; | ||
return this; | ||
return this.derivePolicy({ ...this.options, backoff }); | ||
} | ||
derivePolicy(newOptions) { | ||
const p = new RetryPolicy(newOptions); | ||
p.onGiveUp(evt => this.onGiveUpEmitter.emit(evt)); | ||
p.onRetry(evt => this.onRetryEmitter.emit(evt)); | ||
return p; | ||
} | ||
} | ||
exports.RetryPolicy = RetryPolicy; | ||
//# sourceMappingURL=RetryPolicy.js.map |
@@ -6,2 +6,3 @@ "use strict"; | ||
const Backoff_1 = require("./backoff/Backoff"); | ||
const util_test_1 = require("./common/util.test"); | ||
const Policy_1 = require("./Policy"); | ||
@@ -127,3 +128,30 @@ chai_1.use(require('sinon-chai')); | ||
}); | ||
it('does not unref by default', async () => { | ||
const output = await util_test_1.runInChild(` | ||
Policy.handleAll() | ||
.retry() | ||
.attempts(1) | ||
.delay(1) | ||
.execute(() => { | ||
console.log('attempt'); | ||
throw new Error('oh no!'); | ||
}); | ||
`); | ||
chai_1.expect(output).to.contain('oh no!'); | ||
}); | ||
it('unrefs as requested', async () => { | ||
const output = await util_test_1.runInChild(` | ||
Policy.handleAll() | ||
.retry() | ||
.dangerouslyUnref() | ||
.attempts(1) | ||
.delay(1) | ||
.execute(() => { | ||
console.log('attempt'); | ||
throw new Error('oh no!'); | ||
}); | ||
`); | ||
chai_1.expect(output).to.equal('attempt'); | ||
}); | ||
}); | ||
//# sourceMappingURL=RetryPolicy.test.js.map |
@@ -20,2 +20,3 @@ import { CancellationToken } from './CancellationToken'; | ||
private readonly strategy; | ||
private readonly unref; | ||
private readonly timeoutEmitter; | ||
@@ -26,4 +27,12 @@ /** | ||
readonly onTimeout: import("./common/Event").Event<void>; | ||
constructor(duration: number, strategy: TimeoutStrategy); | ||
constructor(duration: number, strategy: TimeoutStrategy, unref?: boolean); | ||
/** | ||
* When timing out, a referenced timer is created. This means the Node.js | ||
* event loop is kept active while we're waiting for the timeout, as long as | ||
* the function hasn't returned. Calling this method on the timeout builder | ||
* will unreference the timer, allowing the process to exit even if a | ||
* timeout might still be happening. | ||
*/ | ||
dangerouslyUnref(): TimeoutPolicy; | ||
/** | ||
* Executes the given function. | ||
@@ -30,0 +39,0 @@ * @param fn -- Function to execute. Takes in a nested cancellation token. |
@@ -19,5 +19,6 @@ "use strict"; | ||
class TimeoutPolicy { | ||
constructor(duration, strategy) { | ||
constructor(duration, strategy, unref = false) { | ||
this.duration = duration; | ||
this.strategy = strategy; | ||
this.unref = unref; | ||
this.timeoutEmitter = new Event_1.EventEmitter(); | ||
@@ -31,2 +32,14 @@ /** | ||
/** | ||
* When timing out, a referenced timer is created. This means the Node.js | ||
* event loop is kept active while we're waiting for the timeout, as long as | ||
* the function hasn't returned. Calling this method on the timeout builder | ||
* will unreference the timer, allowing the process to exit even if a | ||
* timeout might still be happening. | ||
*/ | ||
dangerouslyUnref() { | ||
const t = new TimeoutPolicy(this.duration, this.strategy, true); | ||
t.onTimeout(() => this.timeoutEmitter.emit()); | ||
return t; | ||
} | ||
/** | ||
* Executes the given function. | ||
@@ -39,2 +52,5 @@ * @param fn -- Function to execute. Takes in a nested cancellation token. | ||
const timer = setTimeout(() => cts.cancel(), this.duration); | ||
if (this.unref) { | ||
timer.unref(); | ||
} | ||
try { | ||
@@ -41,0 +57,0 @@ if (this.strategy === TimeoutStrategy.Cooperative) { |
@@ -6,2 +6,3 @@ "use strict"; | ||
const defer_1 = require("./common/defer"); | ||
const util_test_1 = require("./common/util.test"); | ||
const TaskCancelledError_1 = require("./errors/TaskCancelledError"); | ||
@@ -26,3 +27,3 @@ const Policy_1 = require("./Policy"); | ||
it('properly aggressively cancels', async () => { | ||
const policy = Policy_1.Policy.timeout(2, TimeoutPolicy_1.TimeoutStrategy.Aggressive); | ||
const policy = Policy_1.Policy.timeout(5, TimeoutPolicy_1.TimeoutStrategy.Aggressive); | ||
const verified = defer_1.defer(); | ||
@@ -32,3 +33,3 @@ await chai_1.expect(policy.execute(async ({ cancellation }) => { | ||
chai_1.expect(cancellation.isCancellationRequested).to.be.false; | ||
await delay(3); | ||
await delay(5); | ||
chai_1.expect(cancellation.isCancellationRequested).to.be.true; | ||
@@ -40,3 +41,20 @@ verified.resolve(undefined); | ||
}); | ||
it('does not unref by default', async () => { | ||
// this would timeout if the timers were referenced | ||
const output = await util_test_1.runInChild(` | ||
Policy.timeout(100, 'aggressive') | ||
.execute(() => new Promise(() => {})); | ||
`); | ||
chai_1.expect(output).to.contain('Operation cancelled'); | ||
}); | ||
it('unrefs as requested', async () => { | ||
// this would timeout if the timers were referenced | ||
const output = await util_test_1.runInChild(` | ||
Policy.timeout(60 * 1000, 'aggressive') | ||
.dangerouslyUnref() | ||
.execute(() => new Promise(() => {})); | ||
`); | ||
chai_1.expect(output).to.be.empty; | ||
}); | ||
}); | ||
//# sourceMappingURL=TimeoutPolicy.test.js.map |
{ | ||
"name": "cockatiel", | ||
"version": "0.1.4", | ||
"version": "0.1.5", | ||
"description": "A resilience and transient-fault-handling library that allows developers to express policies such as Backoff, Retry, Circuit Breaker, Timeout, Bulkhead Isolation, and Fallback in a fluent and thread-safe manner. Inspired by .NET Polly.", | ||
@@ -18,4 +18,4 @@ "main": "dist/index.js", | ||
"test:fmt": "prettier --list-different \"src/**/*.ts\" \"*.md\"", | ||
"test:md": "remark -u validate-links -f readme.md", | ||
"fmt": "prettier --write \"src/**/*.ts\" \"*.md\" && npm run test:lint -- --fix", | ||
"test:md": "remark -f readme.md -q", | ||
"fmt": "remark readme.md -f -o readme.md && prettier --write \"src/**/*.ts\" \"*.md\" && npm run test:lint -- --fix", | ||
"compile": "rimraf dist && tsc && tsc -p tsconfig.esm.json", | ||
@@ -79,2 +79,3 @@ "watch": "rimraf dist && tsc --watch" | ||
"remark-cli": "^7.0.1", | ||
"remark-toc": "^7.0.0", | ||
"remark-validate-links": "^9.0.1", | ||
@@ -81,0 +82,0 @@ "rimraf": "^3.0.0", |
136
readme.md
@@ -9,5 +9,3 @@ # Cockatiel | ||
``` | ||
npm install --save cockatiel | ||
``` | ||
npm install --save cockatiel | ||
@@ -43,59 +41,65 @@ Then go forth with confidence: | ||
## Contents | ||
I recommend reading the [Polly wiki](https://github.com/App-vNext/Polly/wiki) for more information for details and mechanics around the patterns we provide. | ||
This table lists the API which Cockatiel provides. I recommend reading the [Polly wiki](https://github.com/App-vNext/Polly/wiki) for more information for details and mechanics around the patterns we provide. | ||
## Table of Contents | ||
- [x] Base [Policy](#policy) | ||
- [Policy.handleAll()](#policyhandleAll) | ||
- [Policy.handleType(ctor[, filter])](#policyhandletypector-filter) | ||
- [Policy.handleWhen(filter)](#policyhandlewhenfilter) | ||
- [Policy.handleResultType(ctor[, filter])](#policyhandleresulttypector-filter) | ||
- [Policy.handleResultWhen(filter)](#policyhandleresultwhenfilter) | ||
- [Policy.use(policy)](#policyusepolicy) | ||
- [Policy.wrap(...policies)](#policywrappolicies) | ||
- [Policy.noop](#policynoop) | ||
- [x] [Backoffs](#backoffs) | ||
- [ConstantBackoff](#ConstantBackoff) | ||
- [ExponentialBackoff](#ExponentialBackoff) | ||
- [IterableBackoff](#IterableBackoff) | ||
- [DelegateBackoff](#DelegateBackoff) | ||
- [CompositeBackoff](#CompositeBackoff) | ||
- [x] [CancellationToken](#cancellationtoken) | ||
- [new CancellationTokenSource([parent])](#new-cancellationtokensourceparent) | ||
- [cancellationTokenSource.token](#cancellationtokensourcetoken) | ||
- [cancellationTokenSource.cancel()](#cancellationtokensourcecancel) | ||
- [cancellationToken.isCancellationRequested](#cancellationtokeniscancellationrequested) | ||
- [cancellationToken.onCancellationRequested(callback)](#cancellationtokenoncancellationrequestedcallback) | ||
- [cancellationToken.cancelled()](#cancellationtokencancelledcancellationToken) | ||
- [x] [Events](#events) | ||
- [Event.toPromise(event[, cancellationToken])](#eventtopromiseevent-cancellationtoken) | ||
- [Event.once(event, callback)](#eventonceevent-callback) | ||
- [x] [Policy.retry](#policyretry) | ||
- [retry.execute(fn)](#retryexecutefn) | ||
- [retry.attempts(count)](#retryattemptscount) | ||
- [retry.delay(amount)](#retrydelayamount) | ||
- [retry.exponential(options)](#retryexponentialoptions) | ||
- [retry.delegate(fn)](#retrydelegatefn) | ||
- [retry.backoff(policy)](#retrybackoffpolicy) | ||
- [retry.onRetry(callback)](#retryonretrycallback) | ||
- [retry.onGiveUp(callback)](#retryongiveupcallback) | ||
- [x] [Policy.circuitBreaker](#policycircuitbreakeropenafter-breaker) | ||
- [ConsecutiveBreaker](#ConsecutiveBreaker) | ||
- [SamplingBreaker](#SamplingBreaker) | ||
- [breaker.execute(fn)](#breakerexecutefn) | ||
- [breaker.state](#breakerstate) | ||
- [breaker.onBreak(callback)](#breakeronbreakcallback) | ||
- [breaker.onReset(callback)](#breakeronresetcallback) | ||
- [breaker.isolate()](#breakerisolate) | ||
- [x] [Policy.timeout](#policytimeoutduration-strategy) | ||
- [timeout.execute(fn)](#timeoutexecutefn) | ||
- [timeout.onTimeout(callback)](#timeoutontimeoutcallback) | ||
- [x] [Policy.bulkhead](#policybulkheadlimit-queue) | ||
- [bulkhead.execute(fn)](#bulkheadexecutefn) | ||
- [bulkhead.onReject(callback)](#bulkheadonrejectcallback) | ||
- [bulkhead.executionSlots](#bulkheadexecutionslots) | ||
- [bulkhead.queueSlots](#bulkheadqueueslots) | ||
- [x] [Policy.fallback](#policyfallbackvalueorfactory) | ||
- [fallback.execute(fn)](#fallbackexecutefn) | ||
- [fallback.onFallback(callback)](#fallbackonfallbackcallback) | ||
- [`Policy`](#policy) | ||
- [`Policy.handleAll()`](#policyhandleall) | ||
- [`Policy.handleType(ctor[, filter])`](#policyhandletypector-filter) | ||
- [`policy.orType(ctor[, filter])`](#policyortypector-filter) | ||
- [`Policy.handleWhen(filter)`](#policyhandlewhenfilter) | ||
- [`policy.orWhen(filter)`](#policyorwhenfilter) | ||
- [`Policy.handleResultType(ctor[, filter])`](#policyhandleresulttypector-filter) | ||
- [`policy.orResultType(ctor[, filter])`](#policyorresulttypector-filter) | ||
- [`Policy.handleResultWhen(filter)`](#policyhandleresultwhenfilter) | ||
- [`policy.orWhenResult(filter)`](#policyorwhenresultfilter) | ||
- [`Policy.wrap(...policies)`](#policywrappolicies) | ||
- [`Policy.use(policy)`](#policyusepolicy) | ||
- [`Policy.noop`](#policynoop) | ||
- [Backoffs](#backoffs) | ||
- [ConstantBackoff](#constantbackoff) | ||
- [ExponentialBackoff](#exponentialbackoff) | ||
- [IterableBackoff](#iterablebackoff) | ||
- [DelegateBackoff](#delegatebackoff) | ||
- [CompositeBackoff](#compositebackoff) | ||
- [`CancellationToken`](#cancellationtoken) | ||
- [`new CancellationTokenSource([parent])`](#new-cancellationtokensourceparent) | ||
- [`cancellationTokenSource.token`](#cancellationtokensourcetoken) | ||
- [`cancellationTokenSource.cancel()`](#cancellationtokensourcecancel) | ||
- [`cancellationToken.isCancellationRequested`](#cancellationtokeniscancellationrequested) | ||
- [`cancellationToken.onCancellationRequested(callback)`](#cancellationtokenoncancellationrequestedcallback) | ||
- [`cancellationToken.cancelled([cancellationToken])`](#cancellationtokencancelledcancellationtoken) | ||
- [Events](#events) | ||
- [`Event.toPromise(event[, cancellationToken])`](#eventtopromiseevent-cancellationtoken) | ||
- [`Event.once(event, callback)`](#eventonceevent-callback) | ||
- [`Policy.retry()`](#policyretry) | ||
- [`retry.execute(fn)`](#retryexecutefn) | ||
- [`retry.attempts(count)`](#retryattemptscount) | ||
- [`retry.delay(amount)`](#retrydelayamount) | ||
- [`retry.exponential(options)`](#retryexponentialoptions) | ||
- [`retry.delegate(fn)`](#retrydelegatefn) | ||
- [`retry.backoff(policy)`](#retrybackoffpolicy) | ||
- [`retry.dangerouslyUnref()`](#retrydangerouslyunref) | ||
- [`retry.onRetry(callback)`](#retryonretrycallback) | ||
- [`retry.onGiveUp(callback)`](#retryongiveupcallback) | ||
- [`Policy.circuitBreaker(openAfter, breaker)`](#policycircuitbreakeropenafter-breaker) | ||
- [`ConsecutiveBreaker`](#consecutivebreaker) | ||
- [`SamplingBreaker`](#samplingbreaker) | ||
- [`breaker.execute(fn)`](#breakerexecutefn) | ||
- [`breaker.state`](#breakerstate) | ||
- [`breaker.onBreak(callback)`](#breakeronbreakcallback) | ||
- [`breaker.onReset(callback)`](#breakeronresetcallback) | ||
- [`breaker.isolate()`](#breakerisolate) | ||
- [`Policy.timeout(duration, strategy)`](#policytimeoutduration-strategy) | ||
- [`timeout.dangerouslyUnref()`](#timeoutdangerouslyunref) | ||
- [`timeout.execute(fn)`](#timeoutexecutefn) | ||
- [`timeout.onTimeout(callback)`](#timeoutontimeoutcallback) | ||
- [`Policy.bulkhead(limit[, queue])`](#policybulkheadlimit-queue) | ||
- [`bulkhead.execute(fn)`](#bulkheadexecutefn) | ||
- [`bulkhead.onReject(callback)`](#bulkheadonrejectcallback) | ||
- [`bulkhead.executionSlots`](#bulkheadexecutionslots) | ||
- [`bulkhead.queueSlots`](#bulkheadqueueslots) | ||
- [`Policy.fallback(valueOrFactory)`](#policyfallbackvalueorfactory) | ||
- [`fallback.execute(fn)`](#fallbackexecutefn) | ||
- [`fallback.onFallback(callback)`](#fallbackonfallbackcallback) | ||
@@ -610,2 +614,14 @@ ## `Policy` | ||
### `retry.dangerouslyUnref()` | ||
When retrying, a referenced timer is created. This means the Node.js event loop is kept active while we're delaying a retried call. Calling this method on the retry builder will unreference the timer, allowing the process to exit even if a retry might still be pending: | ||
```ts | ||
const response1 = await Policy.handleAll() // handle all errors | ||
.retry() // get a RetryBuilder | ||
.dangerouslyUnref() // unreference the timer | ||
.attempts(3) // retry three times, with no delay | ||
.execute(() => getJson('https://example.com')); | ||
``` | ||
### `retry.onRetry(callback)` | ||
@@ -786,2 +802,6 @@ | ||
### `timeout.dangerouslyUnref()` | ||
When timing out, a referenced timer is created. This means the Node.js event loop is kept active while we're waiting for the timeout, as long as the function hasn't returned. Calling this method on the timeout builder will unreference the timer, allowing the process to exit even if a timeout might still be happening. | ||
### `timeout.execute(fn)` | ||
@@ -788,0 +808,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
424503
268
6537
914
23
2
2