// async_utils.mbt — cooperative sleep primitive.
//
// Bridges through mizchi/llm/ffi's Promise so the whole mnemo async
// stack stays on one scheduler. Replacing this with `@async.sleep`
// breaks tests because the ffi.Promise::wait handlers (used in lock.mbt
// and elsewhere) live on a different event-loop abstraction than the
// moonbitlang/async coroutine scheduler. Wall-clock time comes from
// `@env.now()` which is cross-target, so tests don't need a JS Date.
///|
/// Returns a Promise that resolves after `ms` milliseconds.
extern "js" fn _set_timeout_promise(ms : Int) -> @ffi.Promise[Unit] =
#| (ms) => new Promise(resolve => setTimeout(resolve, ms))
///|
/// Cooperative sleep: yields to the event loop for approximately `ms` ms.
pub async fn sleep_ms(ms : Int) -> Unit {
_set_timeout_promise(ms).wait()
}
// ── inline tests ──
///|
async test "sleep_ms: takes roughly the expected time" {
let t0 = @env.now().reinterpret_as_int64()
sleep_ms(30)
let elapsed = @env.now().reinterpret_as_int64() - t0
// Should be >= 25ms (not a busy-wait spin) and < 500ms (not stuck)
assert_eq(elapsed >= 25L, true)
assert_eq(elapsed < 500L, true)
}