Files
suaveplan/packages/foundation/timing/timing/README.md
2026-05-27 23:47:53 +01:00

11 KiB

@suaveplan/timing - Timing and scheduling utilities — stopwatch, throttle, debounce, scheduler, decay, timer, countdown, vector clock

Summary

Timing and scheduling utilities for application-layer time management. The package covers measurement (stopwatch with lap recording), rate control (throttle and debounce with leading/trailing edge and maxWait), value decay (exponential and linear curves), delayed-task scheduling with drain/dispose lifecycle, repeating interval timers, countdowns with pause/resume, and vector clocks for distributed happens-before ordering. All stateful primitives accept an injectable Clock so they can be driven deterministically in tests using FakeClock from @suaveplan/testing.

Documentation tree

  • decay — (no submodules)
    • decay — (no submodules)
  • errors — (no submodules)
  • otel — (no submodules)
  • scheduler — (no submodules)
  • stopwatch — (no submodules)
  • throttle — (no submodules)
    • once — once wraps a function so that it executes exactly once and caches the result for every subsequent call. It is the low…
      • once — once wraps a function so that it executes exactly once and caches the result for every subsequent call. It is the low…
    • rate-limit — rateLimit wraps a function so that at most maxCalls invocations of the underlying fn are permitted inside any sli…
      • rate-limit — rateLimit wraps a function so that at most maxCalls invocations of the underlying fn are permitted inside any sli…
    • times — times wraps a function so it runs for the first n invocations and becomes a no-op thereafter. It is the right primi…
      • times — times wraps a function so it runs for the first n invocations and becomes a no-op thereafter. It is the right primi…
    • throttle — (no submodules)
  • timer — (no submodules)
    • timer — (no submodules)
  • vector-clock — (no submodules)
- [decay](./src/decay/decay.md) — _(no submodules)_- [errors](./src/errors/timing-error.md) — _(no submodules)_- [timing-error](./src/errors/timing-error.md) — _(no submodules)_- [otel](./src/otel/timing-otel.md) — _(no submodules)_- [timing-otel](./src/otel/timing-otel.md) — _(no submodules)_- [scheduler](./src/scheduler/scheduler.md) — _(no submodules)_- [scheduler](./src/scheduler/scheduler.md) — _(no submodules)_- [stopwatch](./src/stopwatch/stopwatch.md) — _(no submodules)_- [stopwatch](./src/stopwatch/stopwatch.md) — _(no submodules)_- [throttle](./src/throttle/throttle.md) — _(no submodules)_- [throttle](./src/throttle/throttle.md) — _(no submodules)_- [timer](./src/timer/timer.md) — _(no submodules)_- [timer](./src/timer/timer.md) — _(no submodules)_- [vector-clock](./src/vector-clock/vector-clock.md) — _(no submodules)_- [vector-clock](./src/vector-clock/vector-clock.md) — _(no submodules)_- [decay](./src/decay/decay.md) — _(no submodules)_- [errors](./src/errors/timing-error.md) — _(no submodules)_- [timing-error](./src/errors/timing-error.md) — _(no submodules)_- [otel](./src/otel/timing-otel.md) — _(no submodules)_- [timing-otel](./src/otel/timing-otel.md) — _(no submodules)_- [scheduler](./src/scheduler/scheduler.md) — _(no submodules)_- [scheduler](./src/scheduler/scheduler.md) — _(no submodules)_- [stopwatch](./src/stopwatch/stopwatch.md) — _(no submodules)_- [stopwatch](./src/stopwatch/stopwatch.md) — _(no submodules)_- [throttle](./src/throttle/throttle.md) — _(no submodules)_- [throttle](./src/throttle/throttle.md) — _(no submodules)_- [timer](./src/timer/timer.md) — _(no submodules)_- [timer](./src/timer/timer.md) — _(no submodules)_- [vector-clock](./src/vector-clock/vector-clock.md) — _(no submodules)_- [vector-clock](./src/vector-clock/vector-clock.md) — _(no submodules)_- [decay](./src/decay/decay.md) — _(no submodules)_- [errors](./src/errors/timing-error.md) — _(no submodules)_- [timing-error](./src/errors/timing-error.md) — _(no submodules)_- [otel](./src/otel/timing-otel.md) — _(no submodules)_- [timing-otel](./src/otel/timing-otel.md) — _(no submodules)_- [scheduler](./src/scheduler/scheduler.md) — _(no submodules)_- [scheduler](./src/scheduler/scheduler.md) — _(no submodules)_- [stopwatch](./src/stopwatch/stopwatch.md) — _(no submodules)_- [stopwatch](./src/stopwatch/stopwatch.md) — _(no submodules)_- [throttle](./src/throttle/throttle.md) — _(no submodules)_- [throttle](./src/throttle/throttle.md) — _(no submodules)_- [timer](./src/timer/timer.md) — _(no submodules)_- [timer](./src/timer/timer.md) — _(no submodules)_- [vector-clock](./src/vector-clock/vector-clock.md) — _(no submodules)_- [vector-clock](./src/vector-clock/vector-clock.md) — _(no submodules)_- [decay](./src/decay/decay.md) — _(no submodules)_- [errors](./src/errors/timing-error.md) — _(no submodules)_ - [timing-error](./src/errors/timing-error.md) — _(no submodules)_- [otel](./src/otel/timing-otel.md) — _(no submodules)_ - [timing-otel](./src/otel/timing-otel.md) — _(no submodules)_- [scheduler](./src/scheduler/scheduler.md) — _(no submodules)_ - [scheduler](./src/scheduler/scheduler.md) — _(no submodules)_- [stopwatch](./src/stopwatch/stopwatch.md) — _(no submodules)_ - [stopwatch](./src/stopwatch/stopwatch.md) — _(no submodules)_- [throttle](./src/throttle/throttle.md) — _(no submodules)_ - [throttle](./src/throttle/throttle.md) — _(no submodules)_- [timer](./src/timer/timer.md) — _(no submodules)_ - [timer](./src/timer/timer.md) — _(no submodules)_- [vector-clock](./src/vector-clock/vector-clock.md) — _(no submodules)_ - [vector-clock](./src/vector-clock/vector-clock.md) — _(no submodules)_

Install

bun add @suaveplan/timing

Quick Start

import {
  createStopwatch,
  throttle,
  createCountdown,
  createVectorClock,
} from "@suaveplan/timing";

// Measure elapsed time with lap splits.
const sw = createStopwatch();
sw.start();
// ... work ...
const lap = sw.lap();   // { index: 1, split: <ms since last lap>, elapsed: <total ms> }
sw.stop();
console.log("total ms:", sw.elapsed);

// Throttle an expensive resize handler to fire at most once per 200 ms.
const onResize = throttle(() => recalculateLayout(), 200, { leading: true, trailing: true });
window.addEventListener("resize", onResize);

// Countdown that calls onTick every second for 30 seconds.
const countdown = createCountdown({ durationMs: 30_000, intervalMs: 1_000 }, () => {
  console.log("tick");
});
countdown.start();

// Vector clock for two distributed nodes.
const nodeA = createVectorClock({ nodeId: "A" });
const nodeB = createVectorClock({ nodeId: "B" });
nodeA.increment();
nodeB.merge(nodeA.snapshot());

Modules

Module Path
stopwatch — createStopwatch, lap recording, accumulated elapsed time src/stopwatch/stopwatch.md
throttle — throttle, debounce with leading/trailing/maxWait src/throttle/throttle.md
rate-limit — rateLimit, RATE_LIMITED sentinel, sliding-window cap src/throttle/rate-limit/rate-limit.md
once — once, run-and-cache with throw-and-retry src/throttle/once/once.md
times — times, run for first N then no-op src/throttle/times/times.md
decay — createDecay, exponential and linear decay curves src/decay/decay.md
scheduler — createScheduler, delayed async tasks, drain, dispose src/scheduler/scheduler.md
timer — createTimer (interval), createCountdown (pause/resume) src/timer/timer.md
vector-clock — createVectorClock, vectorClockCompare, happens-before ordering src/vector-clock/vector-clock.md
timing-error — TimingError, TIMING_CODES src/errors/timing-error.md
timing-otel — OpenTelemetry span/event helpers src/otel/timing-otel.md