Skip to content

Commit

Permalink
feat(tasks): add timeout task
Browse files Browse the repository at this point in the history
  • Loading branch information
rafamel committed Apr 7, 2021
1 parent 95a0e18 commit df676d6
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/tasks/schedule/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './sleep';
export * from './timeout';
53 changes: 53 additions & 0 deletions src/tasks/schedule/timeout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Task, Context } from '../../definitions';
import { isCancelled } from '../../utils/is-cancelled';
import { run } from '../../utils/run';
import { raises } from '../exception/raises';
import { log } from '../stdio/log';
import { Empty } from 'type-core';
import { into } from 'pipettes';

/**
* Timeout for a `task`, in milliseconds.
* Will error on timeout unless an `alternate` task is provided.
* @returns Task
*/
export function timeout(
ms: number,
task: Task,
alternate: Task | Empty
): Task.Async {
return async (ctx: Context): Promise<void> => {
if (ms < 0) {
into(ctx, log('debug', 'Timeout disabled:', ms));
return run(task, ctx);
}

const params = {
ms: Math.max(ms, 0),
alternate: alternate || raises('Task timeout')
};

into(ctx, log('debug', 'Task timeout set at', params.ms));

if (params.ms <= 0) return run(params.alternate, ctx);
let didTimeout = false;
let timeout: NodeJS.Timeout | null = null;
await run(task, {
...ctx,
cancellation: Promise.race([
new Promise<void>((resolve) => {
timeout = setTimeout(() => {
into(ctx, log('debug', 'Task timeout'));
didTimeout = true;
resolve();
}, params.ms);
}),
ctx.cancellation.finally(() => timeout && clearTimeout(timeout))
])
});

if (timeout) clearTimeout(timeout);
if (await isCancelled(ctx)) return;
if (didTimeout) return run(params.alternate, ctx);
};
}

0 comments on commit df676d6

Please sign in to comment.