Functional Weave
Code in Rust

monitor.heartbeat@1.0.0

impl/typescript.ts

1,396 bytes · the TypeScript implementation · view raw

import { type HeartbeatStatus } from "./monitor_heartbeat_types.ts";

function whole(name: string, v: number): void {
  if (!Number.isSafeInteger(v)) throw new RangeError(`${name} must be whole seconds, received ${v}`);
}

/**
 * New, up, late or down, as healthchecks.io names them. Up through the due
 * second itself, late through the last second of the grace time, down after.
 * A ping stamped in the future (clock skew between the job and the monitor)
 * is simply up: its due time is later still.
 */
export function heartbeatStatus(lastPingAt: number | null, now: number, intervalSeconds: number, graceSeconds: number): HeartbeatStatus {
  if (lastPingAt !== null) whole("lastPingAt", lastPingAt);
  whole("now", now);
  whole("intervalSeconds", intervalSeconds);
  whole("graceSeconds", graceSeconds);
  if (intervalSeconds < 1) throw new RangeError(`intervalSeconds must be at least 1, received ${intervalSeconds}`);
  if (graceSeconds < 0) throw new RangeError(`graceSeconds must not be negative, received ${graceSeconds}`);
  if (lastPingAt === null) return { state: "new", dueAt: null, downAt: null, overdueSeconds: 0 };
  const dueAt = lastPingAt + intervalSeconds;
  const downAt = dueAt + graceSeconds;
  if (now <= dueAt) return { state: "up", dueAt, downAt, overdueSeconds: 0 };
  return { state: now <= downAt ? "late" : "down", dueAt, downAt, overdueSeconds: now - dueAt };
}