Examples

Fleet Monitor

Real-time service health monitoring. Six parallel health check signals fan out from an init signal and converge into an aggregate report. Triggered on a recurring 60-second interval.

broadcasts/full-health-check.ts

import { broadcast } from "station-broadcast";import { initHealthCheck } from "../signals/init-health-check.js";import { checkApi } from "../signals/check-api.js";import { checkDatabase } from "../signals/check-database.js";import { checkRedis } from "../signals/check-redis.js";import { checkQueue } from "../signals/check-queue.js";import { checkDisk } from "../signals/check-disk.js";import { checkMemory } from "../signals/check-memory.js";import { aggregateReport } from "../signals/aggregate-report.js"; export const fullHealthCheck = broadcast("full-health-check")  .input(initHealthCheck)  .then(checkApi, checkDatabase, checkRedis, checkQueue, checkDisk, checkMemory)  .then(aggregateReport)  .onFailure("continue")  .timeout(30_000)  .build();

signals/check-api.ts

import { signal, z } from "station-signal"; export const checkApi = signal("check-api")  .output(z.object({    service: z.string(),    healthy: z.boolean(),    latencyMs: z.number(),    checkedAt: z.string(),  }))  .every("5s")  .run(async () => {    const latencyMs = 20 + Math.floor(Math.random() * 80);    await new Promise((r) => setTimeout(r, latencyMs));     if (Math.random() < 0.1) {      throw new Error(`API responded with 503 (latency: ${latencyMs}ms)`);    }     console.log(`[check-api] OK ${latencyMs}ms`);    return {      service: "api-gateway",      healthy: true,      latencyMs,      checkedAt: new Date().toISOString(),    };  });

runner.ts

import path from "node:path";import { SignalRunner, ConsoleSubscriber } from "station-signal";import { BroadcastRunner, ConsoleBroadcastSubscriber } from "station-broadcast";import { SqliteAdapter } from "station-adapter-sqlite";import { BroadcastSqliteAdapter } from "station-adapter-sqlite/broadcast";import { fullHealthCheck } from "./broadcasts/full-health-check.js"; const DB_PATH = path.join(import.meta.dirname, "jobs.db"); const signalRunner = new SignalRunner({  signalsDir: path.join(import.meta.dirname, "signals"),  adapter: new SqliteAdapter({ dbPath: DB_PATH }),  subscribers: [new ConsoleSubscriber()],  maxConcurrent: 8,}); const broadcastRunner = new BroadcastRunner({  signalRunner,  adapter: new BroadcastSqliteAdapter({ dbPath: DB_PATH }),  subscribers: [new ConsoleBroadcastSubscriber()],}); broadcastRunner.register(fullHealthCheck); console.log("Fleet monitor started.");console.log("6 recurring health checks running at different intervals.");console.log(`Data persisted in ${DB_PATH}`);console.log("Open Station to watch real-time service health.\n"); // Trigger a full health check broadcast every 60 secondssetInterval(async () => {  const id = await fullHealthCheck.trigger({    label: `scheduled-${Date.now().toString(36)}`,  });  console.log(`\n[broadcast] Triggered full health check: ${id}\n`);}, 60_000); // Also trigger one immediately after startupsetTimeout(async () => {  const id = await fullHealthCheck.trigger({ label: "startup-check" });  console.log(`\n[broadcast] Triggered startup health check: ${id}\n`);}, 1000); signalRunner.start();broadcastRunner.start();

onFailure("continue") keeps checking remaining services even if one health check throws. Each check signal also runs independently on its own .every() interval. The broadcast adds a coordinated sweep that fans out all six checks in parallel and funnels results into a single aggregate report. Use setInterval to trigger the broadcast periodically.

Run it: pnpm --filter example-fleet-monitor start


← All examples