Skip to content

AbortSignal not working in subscriptions #191

@l-drews

Description

@l-drews

I played around with subscriptions by using SSE and noticed that my EventEmitter was hitting the max listener limit. It seems that the opts.signal is never signalling the abort of the request. After patching the createNuxtApiHandler and using a custom AbortController I managed to clean up the closed/aborted connections most of the time. The issue seems to be that toWebRequest is not managing the AbortSignal properly. Here is my "working" example:

// Example router
import { EventEmitter, on } from "node:events";
import { z } from "zod";
import { authedProcedure, router } from "../trpc";

const ee = new EventEmitter();

export const appRouter = router({
  chat: authedProcedure.input(z.void()).subscription(async function* (opts) {
    console.log("listeners: ", ee.listenerCount("add") + 1);
    for await (const [data] of on(ee, "add", {
      signal: opts.signal, // Sometimes this signal is not aborted
    })) {
      yield data;
    }
  }),
});
// Patched createNuxtApiHandler
    // ...
    if (event.method === "POST") {
      req.body = await readBody(event);
    }

    // We create our own AbortController and attach it to the Request
    const abortController = new AbortController();
    const reqFromEvent = new Request(toWebRequest(event), {
      signal: abortController.signal
    });

    req.on("close", () => {
      abortController.abort();
    })

    const httpResponse = await resolveResponse({
      ...opts,
      req: reqFromEvent,
      error: null,
      createContext,
      path,
      onError(o) {
        opts.onError?.({
          ...o,
          req
        });
      }
    });

This seems to somewhat fix the issue but there is still a leak when i spam reload the browser. Any ideas on how to fix this?

Environment

Node: v20.15.0
Browsers:
    Chrome: 131.0.6778.265
    Safari: 18.2
npmPackages
  @trpc/server@11.0.0-rc.700
  @trpc/client@11.0.0-rc.700
  trpc-nuxt@0.11.1-next.1

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions