// timed(label, promise) — await a promise and log how long it took, plus a
// "still waiting" line every warnMs while it is pending.
//
// For awaits that have been seen to HANG rather than throw: a hang produces no
// error, so without this nothing says which await it is stuck on. stortron's AI
// Testing Town StateBase open never returned (2026-09-30) and the only evidence
// was every state.* RPC timing out.
//
// Messages are pre-formatted strings, not console %s format args: the hyper-tps
// TUI replaces console.error with a join() that does not interpolate, so %s
// arrives in its server buffer literally.
export async function timed (label, promise, warnMs = 5000) {
const t0 = Date.now()
const timer = setInterval(() => {
console.error('[timed] ' + label + ' still waiting after ' + (Date.now() - t0) + 'ms')
}, warnMs)
try {
const value = await promise
console.error('[timed] ' + label + ' ok in ' + (Date.now() - t0) + 'ms')
return value
} catch (err) {
console.error('[timed] ' + label + ' threw after ' + (Date.now() - t0) + 'ms: ' + (err && err.message))
throw err
} finally {
clearInterval(timer)
}
}