Files
apophis-fastify/src/extension/timeout.ts
T
John Dvorak d0523fcc2d fix: harden engine, enrich failure diagnostics, close adoption gaps
- P0: CLI verify now honors  test budget with seeded multi-sample
- P0: Observe sampling enforced via Math.random() gate in hook-validator
- P1: Remove misleading undici-mock-agent isolation option
- P1: Qualify reuses shared discoverRouteDetails() with warnings
- P1: Chaos/scenario config exposed via preset schema
- P1: README/docs limitations updated to current state
- P2: Nested response annotations prefer 2xx deterministically
- P2: --changed documented as heuristic in verify.md

- Add observe sink tests (sampling 0/1, sink failure non-interference)
- Add verify runs regression tests (scale, determinism, variants)
- Add configured-scenario qualify test (independent of OAuth fixture)
- Add coverageBreakdown to qualify artifacts (per-gate route coverage)
- Add production-style observe example with real sink in docs/observe.md
- Add nightly/staging vs PR gating guidance to docs/qualify.md

- Enrich VerifyFailure with formula-aware diagnostics:
  status:201 => 'HTTP 200', body field checks => actual values
- Remove stale observe CLI activation message
- Document outbound mocks as process-global in getting-started.md
- Refresh APOPHIS_ADOPTION_AUDIT.md with current state

903 tests pass, build clean, typecheck clean.
2026-05-21 20:39:36 -07:00

40 lines
975 B
TypeScript

/**
* Hook Timeout Utility
*
* Wraps async operations with a timeout to prevent indefinite hangs.
*/
class HookTimeoutError extends Error {
constructor(extensionName: string, hookName: string, timeoutMs: number) {
super(
`Extension '${extensionName}' ${hookName} timed out after ${timeoutMs}ms. ` +
`Consider increasing hookTimeoutMs or investigating the extension for blocking operations.`
)
this.name = 'HookTimeoutError'
}
}
/**
* Wrap a promise with a timeout.
* @returns Promise that rejects with HookTimeoutError if deadline exceeded
*/
export function withTimeout<T>(
promise: Promise<T>,
timeoutMs: number,
extensionName: string,
hookName: string
): Promise<T> {
if (timeoutMs <= 0) {
return promise
}
return Promise.race([
promise,
new Promise<never>((_, reject) => {
setTimeout(() => {
reject(new HookTimeoutError(extensionName, hookName, timeoutMs))
}, timeoutMs)
}),
])
}