Common TypeScript utilities (sleep, semaphore, queues, heaps, exponential backoff)
npm install @dcrosstech/dct-ts-utilsA small collection of TypeScript-first async and data-structure utilities,
designed to simple and extendible; focused primarily on clean and simple
implementations without prerequisites, and simple usese.
This package is ESM-only.
---
- Cancellable sleep() with remaining-time inspection
- Weighted semaphore with optional priority scheduling
- FIFO and stable priority queues
- Binary heap implementation
- Exponential backoff executor with:
- randomized exponential delay (Ethernet-style windowing)
- retry-state propagation
- explicit terminal failure control
---
npm install @dcrosstech/dct-ts-utils
---
You can import from the package root:
import { Semaphore, sleep } from "@dcrosstech/dct-ts-utils";
Or import individual modules directly
import { Semaphore } from "@dcrosstech/dct-ts-utils/semaphore";
import { sleep } from "@dcrosstech/dct-ts-utils/sleep";
import { executeWithExponentialBackoff } from "@dcrosstech/dct-ts-utils/retry";
---
A cancellable async sleep primitive.
import { sleep } from "@dcrosstech/dct-ts-utils";
const s = sleep(1000);
setTimeout(() => {
s.cancel();
}, 100);
try {
await s;
} catch (e) {
// sleep was cancelled
}
Available helpers:
- cancel(reason?)
- hasCompleted()
- remainingTime()
---
A weighted semaphore that runs functions without requiring explicit acquire/release calls.
import { Semaphore } from "@dcrosstech/dct-ts-utils";
const sem = new Semaphore(2);
await Promise.all([
sem.run(async () => {
// runs immediately
}),
sem.run(async () => {
// runs immediately
}),
sem.run(async () => {
// queued until capacity is available
}),
]);
With weights and priority scheduling:
const sem = new Semaphore(3, { usePriorityQueue: true });
sem.run(workA, { weight: 2, priority: 10 });
sem.run(workB, { weight: 1, priority: 0 });
The semaphore:
- never bypasses the queue head (prevents starvation)
- supports dynamic capacity changes
- allows negative transient counts when adjusting capacity
---
Minimal FIFO queue abstraction.
import { FifoQueue } from "@dcrosstech/dct-ts-utils";
const q = new FifoQueue
q.enqueue(1);
q.enqueue(2);
q.dequeue(); // 1
q.dequeue(); // 2
---
A priority queue with FIFO ordering among equal-priority elements.
import { StablePriorityQueue } from "@dcrosstech/dct-ts-utils";
const q = new StablePriorityQueue
q.enqueue("low", 10);
q.enqueue("high", 0);
q.enqueue("also-high", 0);
q.dequeue(); // "high"
q.dequeue(); // "also-high"
q.dequeue(); // "low"
---
An array-backed binary heap with a custom comparator.
import { BinaryHeap } from "@dcrosstech/dct-ts-utils";
const heap = new BinaryHeap
heap.push(3);
heap.push(1);
heap.push(2);
heap.pop(); // 1
heap.pop(); // 2
---
Retry an operation with randomized exponential backoff.
import {
executeWithExponentialBackoff,
RetryError,
TerminalError
} from "@dcrosstech/dct-ts-utils/retry";
await executeWithExponentialBackoff(
{
quantumMs: 10,
maxRetries: 5
},
async (state) => {
if (state.transientFailure) {
throw new RetryError("retrying", nextState(state));
}
if (state.fatalFailure) {
throw new TerminalError("fatal error");
}
return state.result;
},
initialState
);
Supports:
- unbounded or capped retries
- Ethernet-style randomized backoff windows
- state propagation between retries
- terminal error substitution on retry exhaustion
---
This prevents starvation and preserves ordering guarantees.
---
- On retry n, choose a random integer in [0 .. factor^k - 1]
- Multiply by a fixed time quantum
- Enforce minimum and optional maximum delay
This avoids thundering-herd behavior while remaining simple and predictable.
---
- Node.js ≥ 16
- ESM-only (no require() support)
- TypeScript typings included
---
ISC
---
David Cross
https://git.dcrosstech.com/public/dct-ts-utils