inngest / inngest-js

The developer platform for easily building reliable workflows with zero infrastructure for TypeScript & JavaScript
https://www.inngest.com/
GNU General Public License v3.0
434 stars 42 forks source link

[BUG] Next.js serve not folllowing specified servePath #470

Open gramliu opened 9 months ago

gramliu commented 9 months ago

Describe the bug I'm trying to serve two inngest clients, to support both edge and base nodejs runtimes on vercel. I'm using the edge runtime for longer running jobs, but I need the nodejs runtime for some api calls that aren't available on the edge runtime. To do this, I'm serving two clients on different API routes, and specifying servePath in the serve function call. However, looking at the logs, calls still end up getting sent to the base /api/inngest route.

To Reproduce Steps to reproduce the behavior:

  1. Create a nextjs app with inngest and host on vercel.
  2. Create two inngest clients and serve them on different routes: /api/inngest/base and /api/inngest/edge. Specify this in the servePath parameter in the serve call.
  3. Trigger an inngest function on one of the clients and look at the Vercel logs.

Expected behavior Triggering a call to my client on /api/inngest/edge should trigger a call to the endpoint

Code snippets / Logs / Screenshots /src/app/api/inngest/edge/route.ts

export const runtime = "edge";

export const { GET, POST, PUT } = serve({
  client: inngestEdgeClient,
  functions: [dummyHandler],
  streaming: "allow",
  servePath: "/api/inngest/edge",
});
image

System info (please complete the following information):

Additional context Add any other context about the problem here.

jpwilliams commented 9 months ago

Hi, @gramliu đŸ‘‹ Thanks for the detailed report!

We've seen this recently but thought we had a fix for it. Is this only happening for you in production or with the Inngest Dev Server too?

gramliu commented 9 months ago

@jpwilliams On the dev server, I can point it to one of the endpoints using the -u flag, but otherwise, it also doesn't seem to be following the servePath

gramliu commented 9 months ago

@jpwilliams I tried debugging locally and found some leads. I think the issue why these alternative servePaths aren't being recognized is because the functions are never being registered. It looks like they're only registered here after one of the edge handlers receives a PUT request. After sending a PUT requests to my two different inngest endpoints, they get registered and the dev server is able to forward events to them as needed.

I think this registration should probably be done when the serve handler is instantiated.

Update: I tried creating a custom wrapper around InngestCommHandler which called register during construction and pulled process.env.VERCEL_URL rather than read the host header of an incoming request, but discovered that the issue would still remain for a different reason. The serve call (or my wrapper in this case) wasn't being called until a request went to that endpoint, since Next dynamically loads the endpoints as requests come in. The problem is I'd typically be sending requests to the other endpoints which call the Inngest clients, which assume the endpoint was already registered.

I tried wrapping this in the Inngest client logic so that I first checked if the handler was instantiated but the dependency tree quickly got very messy. I decided to just go with my workaround described below. I think a good next step here could be to have the inngest client constructor optionally take in a servePath parameter and run the registration process. This way, once any code attempts to call an inngest client, the handler endpoint would have already been registered with the remote inngest server.

Workaround

My current workaround running in Vercel is setting up an integration with checkly, to run a "test" after a build is deployed. This test sends a PUT request to my separate inngest endpoints so that they get registered with the remote inngest server.

p.s. this was a lot. Feel free to ask follow-up questions if anything wasn't clear