| 551 | }; |
| 552 | |
| 553 | const run = async <T = unknown>( |
| 554 | payload: unknown, |
| 555 | timeoutMs?: number, |
| 556 | ): Promise<WorkerdRunResult<T>> => { |
| 557 | await start(); |
| 558 | const state = processState; |
| 559 | if (!state) throw new Error("workerd subprocess is not running"); |
| 560 | |
| 561 | const controller = new AbortController(); |
| 562 | const effectiveTimeoutMs = Math.max(100, timeoutMs ?? DEFAULT_TIMEOUT_MS); |
| 563 | const timer = setTimeout( |
| 564 | () => controller.abort(), |
| 565 | effectiveTimeoutMs + DEFAULT_HOST_TIMEOUT_GRACE_MS, |
| 566 | ); |
| 567 | const startedAt = performance.now(); |
| 568 | return await new Promise<WorkerdRunResult<T>>((resolve, reject) => { |
| 569 | const pendingRequest = { reject }; |
| 570 | pending.add(pendingRequest); |
| 571 | fetch(`http://127.0.0.1:${state.listenPort}/run`, { |
| 572 | method: "POST", |
| 573 | headers: { "content-type": "application/json" }, |
| 574 | body: JSON.stringify(payload), |
| 575 | signal: controller.signal, |
| 576 | }) |
| 577 | .then(async (response) => { |
| 578 | const text = await response.text(); |
| 579 | const body = text.length > 0 ? (JSON.parse(text) as T) : (null as T); |
| 580 | resolve({ status: response.status, body, elapsedMs: performance.now() - startedAt }); |
| 581 | }) |
| 582 | .catch((cause) => { |
| 583 | reject(normalizeError(cause)); |
| 584 | }) |
| 585 | .finally(() => { |
| 586 | clearTimeout(timer); |
| 587 | pending.delete(pendingRequest); |
| 588 | }); |
| 589 | }); |
| 590 | }; |
| 591 | |
| 592 | return { |
| 593 | pid: () => processState?.proc.pid, |