/** * Bus subscriber error triage — the visibility half of F-E2E-021. * * Every wicked-bus seam in the daemon (the interactive relay / draft / edit / demo / chat seams, the * project bridge, the QE gate feed) reports its subscriber errors through its `log` option, which * `createServer` wires to `app.log.warn`. The `/diagnostics` error ring only folds ERROR-level lines * ({@link ../api/diagnostics.ts}), so when six subscribers died with `SQLITE_CORRUPT` and logged it * every 2 s for hours, `recentErrors` stayed `[]` and the Health rail stayed green — a dead bus that * nothing in the product disclosed. * * {@link busSubscriberErrorReporter} gives each seam one `onError` that keeps the seam's own warn * line for ordinary handler/poll errors and ESCALATES a connection-fatal error — the subscriber's * view of the database is gone (`SQLITE_CORRUPT` / `SQLITE_NOTADB` / `SQLITE_IOERR*` from the driver, * or wicked-bus's own `WB-014 SUBSCRIBER_DB_UNUSABLE` classification of the same) — to `logError` * on the first occurrence and then every {@link ESCALATE_EVERY} consecutive repeats, carrying the * count. The outage reaches the ring without the ring becoming the outage's log spam; the warn * cadence in between is unchanged, so an operator tailing the log still sees every tick. */ /** SQLite result codes that mean the handle's view of the database is unusable, not one failed call. */ export declare const CONNECTION_FATAL_SQLITE: RegExp; /** Escalate the 1st, 30th, 60th … consecutive connection-fatal error to `logError` (≈ once a minute at a 2 s poll). */ export declare const ESCALATE_EVERY = 30; /** The seams' usual poll cadence; a seam passes its own so the outage window scales with it. */ export declare const DEFAULT_POLL_INTERVAL_MS = 2000; /** A fatal error more than this many poll intervals after the previous one starts a NEW outage (the count resets). */ export declare const NEW_OUTAGE_AFTER_POLLS = 2; /** * Is `err` a connection-fatal bus error — the driver's own code, or wicked-bus's WB-014 wrapper * (`error: 'WB-014'` / `code: 'SUBSCRIBER_DB_UNUSABLE'`, with the driver code in `context.sqlite_code`)? */ export declare function isBusConnectionFatal(err: unknown): boolean; /** The slice of a bus event the reporters name (`event_id`); null/undefined on poll errors. */ export interface BusEventRef { event_id?: unknown; } export interface BusSubscriberErrorReporterOptions { /** The seam's own one-line description of an error — its existing warn line, unchanged. */ describe: (err: Error, event?: BusEventRef | null) => string; /** The seam's warn-level logger (every error, every tick). */ log: (msg: string) => void; /** The error-level logger the diagnostics ring folds; falls back to `log` when absent. */ logError?: ((msg: string) => void) | undefined; /** * The seam's poll cadence. Consecutive fatal errors arrive one per poll; a fatal error more than * {@link NEW_OUTAGE_AFTER_POLLS} intervals after the previous one is a NEW outage and escalates at * its 1st again (a good poll never calls `onError`, so the count cannot reset on success itself). */ pollIntervalMs?: number | undefined; /** Clock, injectable for tests. */ now?: (() => number) | undefined; } /** * One `onError` for a wicked-bus `subscribe()`: warn on ordinary errors (the seam's own line), * escalate connection-fatal ones to `logError` on the 1st and every {@link ESCALATE_EVERY}th * consecutive occurrence, with the running count and what it means for the seam. A poll-side fatal * (`event == null`) means the SUBSCRIBER CONNECTION is unusable — the seam receives nothing; a fatal * thrown inside the seam's handler (`event != null`) is named as such, since it may be the seam's own * store rather than the bus. The count restarts after a quiet stretch (see `pollIntervalMs`). */ export declare function busSubscriberErrorReporter(opts: BusSubscriberErrorReporterOptions): (err: Error, event?: BusEventRef | null) => void; //# sourceMappingURL=bus-subscriber-errors.d.ts.map