Skip to content

perry-ext-fastify::event_loop doesn't pump stdlib — perry-ext-{ws,net,http} events stranded after app.listen() #747

@proggeramlug

Description

@proggeramlug

Summary

`perry-ext-fastify::event_loop` (`crates/perry-ext-fastify/src/server.rs:332-348`) drains microtasks + Fastify HTTP requests, but never calls `js_run_stdlib_pump` (or `js_stdlib_process_pending` / `js_ws_process_pending` / `js_http_process_pending` / etc.). After `app.listen()` enters this loop, perry-ext-ws / perry-ext-net / perry-ext-http / perry-ext-fetch accept-loop tokio tasks push events to their pending queues forever; nothing drains them on the JS main thread.

Evidence

`crates/perry-ext-fastify/src/server.rs:332-348`:

```rust
fn event_loop(app_handle: Handle, request_rx: &mut mpsc::Receiver) {
loop {
// Drain microtasks queued by previous handler runs.
unsafe {
js_promise_run_microtasks();
}

    // Try to receive a request with a 10ms timeout. Keeps the
    // event loop responsive without busy-spinning.
    let result = match try_recv_with_timeout(request_rx) {
        Some(p) => p,
        None => continue,
    };

    process_request(app_handle, result);
}

}
```

The pre-v0.5.572 version still lives in `crates/perry-stdlib/src/fastify/server.rs:270-289` and does the right thing:

```rust
fn event_loop(...) {
...
loop {
// Process any pending stdlib operations (promises, etc.)
unsafe { crate::common::js_stdlib_process_pending() };

    // Process any pending microtasks
    perry_runtime::js_promise_run_microtasks();
    ...
}

}
```

The perry-stdlib version pumps `js_stdlib_process_pending` (which fans out to `js_ws_process_pending`, `js_http_process_pending`, `js_net_process_pending`, …). The perry-ext-fastify rewrite (introduced in `97e80d3b feat(perry-ext-{streams,fastify}): refs #466 — port streams + fastify in parallel (v0.5.572)`) dropped that call.

Effect

Any program that imports both `fastify` and `ws` (or `fastify` + raw `net`, or `fastify` + node `http` client to a different host, or `fastify` + outbound `fetch`, …) and benefits from the well-known flip routing `fastify` to perry-ext-fastify will have its perry-ext-* accept-loop events silently dropped while `app.listen()` is running.

Currently masked in our hub by the more upstream codegen-level WS regression (filed separately at #746), which prevents any v0.5.491+ build from delivering WS events at all. The moment that's fixed, this latent pump-bridge bug becomes the next failure.

Suggested fix

Add a pump call at the top of the perry-ext-fastify event loop body — either:

```rust
fn event_loop(app_handle: Handle, request_rx: &mut mpsc::Receiver) {
loop {
// NEW: pump stdlib so perry-ext-ws / perry-ext-net / perry-ext-http
// events that accumulated on tokio workers get dispatched.
unsafe { perry_runtime::stdlib_pump::js_run_stdlib_pump() };

    unsafe { js_promise_run_microtasks(); }

    let result = match try_recv_with_timeout(request_rx) {
        Some(p) => p,
        None => continue,
    };

    process_request(app_handle, result);
}

}
```

…matching what perry-stdlib::fastify already does. `js_run_stdlib_pump` is the right call here since it routes through the pump-FN-pointer mechanism perry-stdlib registers at startup (`js_register_stdlib_pump`), so this stays decoupled from perry-stdlib's internal feature set.

Environment

Discovered while diagnosing #746 against perry v0.5.891 / v0.5.892 on Linux x86_64.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions