Skip to content

Commit

Permalink
naming changes and add timeBounded timeout wrapper util (#40)
Browse files Browse the repository at this point in the history
* naming changes and add timeBounded timeout wrapper util

* updated exports
  • Loading branch information
sha1n authored Feb 25, 2022
1 parent cebeb98 commit 05587df
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 27 deletions.
43 changes: 26 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,19 @@ A collection of essential time related utilities.
- [About-Time](#about-time)
- [Install](#install)
- [Utilities & Features](#utilities--features)
- [Delay](#delay)
- [WithTimeout](#withtimeout)
- [Sleep](#sleep)
- [Stopwatch](#stopwatch)
- [Until / Eventually](#until--eventually)
- [delay](#delay)
- [timeoutAround](#timeoutaround)
- [timeBounded](#timebounded)
- [sleep](#sleep)
- [stopwatch](#stopwatch)
- [until / eventually](#until--eventually)
- [Retry](#retry)
- [RetryPolicy](#retrypolicy)
- [Simple retry policy](#simple-retry-policy)
- [Fixed retry policy](#fixed-retry-policy)
- [Exponential backoff retry policy](#exponential-backoff-retry-policy)
- [RetryAround](#retryaround)
- [Retriable](#retriable)
- [retryAround](#retryaround)
- [retriable](#retriable)


# Install
Expand All @@ -32,31 +33,39 @@ npm i @sha1n/about-time
```

# Utilities & Features
## Delay
## delay
```ts
// Execute a function with delay and return it's value
await delay(action, { time: 10 });
await delay(action, { time: 10, units: TimeUnit.Milliseconds });
await delay(action, { time: 10, units: TimeUnit.Milliseconds, unref: true });
```

## WithTimeout
## timeoutAround
```ts
// Execute a function and guards it with a specified timeout
await withTimeout(action, { time: 10 });
await withTimeout(action, { time: 10, units: TimeUnit.Milliseconds });
await withTimeout(action, { time: 10, units: TimeUnit.Milliseconds, unref: true });
await timeoutAround(action, { time: 10 });
await timeoutAround(action, { time: 10, units: TimeUnit.Milliseconds });
await timeoutAround(action, { time: 10, units: TimeUnit.Milliseconds, unref: true });
```

## Sleep
## timeBounded
Wraps a given function with `timeoutAround` with the specified arguments.
```ts
const timeBoundAction = timeBounded(action, options);
const result = await timeBoundAction();
```


## sleep
```ts
// Pause execution for a specified amount of time
await sleep(10);
await sleep(10, { units: TimeUnit.Seconds });
await sleep(10, { units: TimeUnit.Seconds, unref: true });
```

## Stopwatch
## stopwatch
```ts
// Measure time between actions
const elapsed = stopwatch();
Expand All @@ -70,7 +79,7 @@ const elapsed1 = elapsed(TimeUnit.Milliseconds);
const elapsed2 = elapsed(TimeUnit.Seconds);
```

## Until / Eventually
## until / eventually
```ts
// Wait for a condition to become true
await until(condition, { deadline: 10000 });
Expand Down Expand Up @@ -106,14 +115,14 @@ interval<sub>i</sub> = min(limit, (exponential<sup>i</sup> - 1) / 2)
const retryPolicy = exponentialBackoffRetryPolicy(/* count = */10, /* opts?: { exponential?: number, limit?: number, units?: TimeUnit }*/);
```

### RetryAround
### retryAround
Executes the given function with retries based on the specified policy and *optional* predicate.
The predicate provides control over which errors we want to retry on.
```ts
const result = await retryAround(action, retryPolicy, predicate);
```

### Retriable
### retriable
Wraps a given function with `retryAround` with the specified arguments.
```ts
const retriableAction = retriable(action, retryPolicy, predicate);
Expand Down
2 changes: 1 addition & 1 deletion index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export { TimeUnit, toMilliseconds } from './lib/timeunit';
export { withTimeout, sleep, delay, stopwatch, until, eventually } from './lib/utilities';
export { timeoutAround, timeBounded, sleep, delay, stopwatch, until, eventually } from './lib/utilities';
export {
RetryPolicy,
retryAround,
Expand Down
10 changes: 8 additions & 2 deletions lib/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ const eventually = until;
* @param options timer options
* @returns the action result
*/
async function withTimeout<T>(action: () => T | Promise<T>, options: TimerOptions): Promise<T> {
async function timeoutAround<T>(action: () => T | Promise<T>, options: TimerOptions): Promise<T> {
const promisedAction = new Promise<T>((resolve, reject) => {
try {
resolve(action());
Expand Down Expand Up @@ -169,4 +169,10 @@ async function withTimeout<T>(action: () => T | Promise<T>, options: TimerOption
return race;
}

export { withTimeout, sleep, delay, stopwatch, until, eventually };
function timeBounded<T>(action: () => T | Promise<T>, options: TimerOptions): () => Promise<T> {
return () => {
return timeoutAround(action, options);
};
}

export { timeoutAround, timeBounded, sleep, delay, stopwatch, until, eventually };
14 changes: 7 additions & 7 deletions test/withTimeout.spec.ts → test/timeout.spec.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,36 @@
import 'jest-extended';
import { TimeUnit } from '../lib/timeunit';
import { until, withTimeout } from '../lib/utilities';
import { until, timeBounded } from '../lib/utilities';
import { anError, aString } from './randoms';

describe('withTimeout', () => {
describe('timeoutAround/timeBounded', () => {
const expectedError = anError();
const expectedValue = aString();

test('should reject when the action rejects', async () => {
const action = () => Promise.reject(expectedError);

await expect(withTimeout(action, { time: 1, units: TimeUnit.Minute })).rejects.toThrow(expectedError);
await expect(timeBounded(action, { time: 1, units: TimeUnit.Minute })()).rejects.toThrow(expectedError);
});

test('should reject when the action throws', async () => {
const action = () => {
throw expectedError;
};

await expect(withTimeout(action, { time: 1, units: TimeUnit.Minute })).rejects.toThrow(expectedError);
await expect(timeBounded(action, { time: 1, units: TimeUnit.Minute })()).rejects.toThrow(expectedError);
});

test('should resolve to the action resolved value when resolves on time', async () => {
const action = () => Promise.resolve(expectedValue);

await expect(withTimeout(action, { time: 1, units: TimeUnit.Minute })).resolves.toEqual(expectedValue);
await expect(timeBounded(action, { time: 1, units: TimeUnit.Minute })()).resolves.toEqual(expectedValue);
});

test('should resolve to the action returned value when returns on time', async () => {
const action = () => expectedValue;

await expect(withTimeout(action, { time: 1, units: TimeUnit.Minute })).resolves.toEqual(expectedValue);
await expect(timeBounded(action, { time: 1, units: TimeUnit.Minute })()).resolves.toEqual(expectedValue);
});

// eslint-disable-next-line prettier/prettier
Expand All @@ -40,7 +40,7 @@ describe('withTimeout', () => {
await until(() => done);
};

await expect(withTimeout(longAction, { time: 1, units: TimeUnit.Millisecond })).rejects.toThrow(/Timeout/);
await expect(timeBounded(longAction, { time: 1, units: TimeUnit.Millisecond })()).rejects.toThrow(/Timeout/);
done = true;
});
});

0 comments on commit 05587df

Please sign in to comment.