neondatabase / serverless

Connect to Neon PostgreSQL from serverless/worker/edge functions
https://www.npmjs.com/package/@neondatabase/serverless
MIT License
343 stars 13 forks source link

Websocket error on Vercel Serverless Function #15

Closed domluna closed 1 year ago

domluna commented 1 year ago

I'm getting the following error when using this on vercel

Unhandled Promise Rejection     {"errorType":"Runtime.UnhandledPromiseRejection","errorMessage":"Error: All attempts to open a WebSocket to connect to the database failed. If using Node, please install the `ws` package (or simply use the `pg` package instead).","reason":{"errorType":"Error","errorMessage":"All attempts to open a WebSocket to connect to the database failed. If using Node, please install the `ws` package (or simply use the `pg` package instead).","stack":["Error: All attempts to open a WebSocket to connect to the database failed. If using Node, please install the `ws` package (or simply use the `pg` package instead).","    at ws (/var/task/node_modules/@neondatabase/serverless/index.js:43:3301)","    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)"]},"promise":{},"stack":["Runtime.UnhandledPromiseRejection: Error: All attempts to open a WebSocket to connect to the database failed. If using Node, please install the `ws` package (or simply use the `pg` package instead).","    at process.<anonymous> (file:///var/runtime/index.mjs:1188:17)","    at process.emit (node:events:525:35)","    at emit (node:internal/process/promises:149:20)","    at processPromiseRejections (node:internal/process/promises:283:27)","    at process.processTicksAndRejections (node:internal/process/task_queues:96:32)"]}
Unknown application error occurred
Runtime.Unknown

I also got this locally and then install ws and then it went away. wsshould be available on Vercel so I'm not sure what the issue this. This is my package.json

  "devDependencies": {
    "@sveltejs/adapter-auto": "^2.0.0",
    "@sveltejs/kit": "^1.11.0",
    "autoprefixer": "^10.4.13",
    "dotenv-cli": "^7.2.1",
    "esbuild": "^0.17.16",
    "flowbite-svelte": "^0.29.12",
    "postcss": "^8.4.21",
    "prettier": "^2.8.3",
    "prettier-plugin-svelte": "^2.9.0",
    "svelte": "^3.57.0",
    "svelte-check": "^3.0.1",
    "tailwindcss": "^3.2.4",
    "tslib": "^2.4.1",
    "typescript": "^4.9.3",
    "vite": "^4.0.0",
    "vite-plugin-top-level-await": "^1.3.0",
    "vite-plugin-wasm": "^3.2.2"
  },
  "type": "module",
  "dependencies": {
    "@auth/core": "^0.5.1",
    "@auth/sveltekit": "^0.3.0",
    "@neondatabase/serverless": "^0.2.9",
    "@sveltejs/adapter-vercel": "^2.4.1",
    "ag-grid-community": "^29.2.0",
    "ag-grid-react": "^29.2.0",
    "apache-arrow": "^11.0.0",
    "install": "^0.13.0",
    "lucide-svelte": "^0.130.1",
    "marked": "^4.3.0",
    "parquet-wasm": "^0.4.0-beta.5",
    "ws": "^8.13.0"
  }
ivoilic commented 1 year ago

See issue #12: Next/Vercel CLI don't support WebSockets in local dev currently. They do apparently work when deployed which makes it even more frustrating IMO.

domluna commented 1 year ago

I'm running into this issue when deployed though. Locally this works fine for me with sveltekit

jawj commented 1 year ago

Are you deploying this as a Vercel Edge Function (via export const config = { runtime: 'edge' };) or a traditional Serverless Function? A simple repro could be helpful.

domluna commented 1 year ago

using serverless. would this not work with that? only on edge?

joshiain commented 1 year ago

I'm also having the same issue. Got the error locally, adding ws to my project fixed it, but when deployed to Vercel (Serverless not edge) the error is there. Works fine on Cloudflare pages. I'm using SvelteKit as well.

domluna commented 1 year ago

fyi using edge functions works. I was having other issues before getting edge to work, which is why I was trying to do it with just serverless

jawj commented 1 year ago

A colleague has reproduced this issue on Vercel's non-Edge serverless functions. We're looking at what we can do it about it.

In the meantime, it should be possible to use ordinary node-postgres (npm install pg @types/pg) there.

maccman commented 1 year ago
Error occurred prerendering page "/api/export/packages". Read more: https://nextjs.org/docs/messages/prerender-error
18:03:19.403 | Error: All attempts to open a WebSocket to connect to the database failed. If using Node, please install the `ws` package (or simply use the `pg` package instead).
18:03:19.403 | at ws (/vercel/path0/.next/server/chunks/7280.js:3961:44)
18:03:19.404 | info  - Generating static pages (11/11)
18:03:19.405

I'm getting an error message about not being able to reach the websock. DATABASE_URL is set.

Unfortunately pg seems broken on vercel too...

mikevalstar commented 1 year ago

I am also having this issue with edge functions, adding the ws library does not appear to fix the problem when running locally with vercel dev

jawj commented 1 year ago

Hi all. I know Vercel have made recent updates to the vercel CLI tool, and npx vercel dev now works for me for both Edge Functions and Serverless Functions.

Edge Functions example

import { Pool } from '@neondatabase/serverless';

export const config = {
  runtime: 'edge',
  regions: ['fra1'],  // fra1 = Frankfurt: pick the Vercel region nearest your Neon DB
};

export default async (req: Request, ctx: any) => {
  const pool = new Pool({ connectionString: process.env.DATABASE_URL });

  const longitude = parseFloat(req.headers.get('x-vercel-ip-longitude') ?? '-122.47');
  const latitude = parseFloat(req.headers.get('x-vercel-ip-latitude') ?? '37.81');

  const { rows: sites } = await pool.query(`
    SELECT 
      id_no, name_en, category,
      'https://whc.unesco.org/en/list/' || id_no || '/' AS link,
      location <-> st_makepoint($1, $2) AS distance
    FROM whc_sites_2021
    ORDER BY distance
    LIMIT 10`, 
    [longitude, latitude]
  );

  ctx.waitUntil(pool.end());

  return new Response(JSON.stringify({ longitude, latitude, sites }, null, 2));
}

Serverless Functions example

import { Client, neonConfig } from '@neondatabase/serverless';
import { WebSocket } from 'undici';
import type { VercelRequest, VercelResponse } from '@vercel/node';

neonConfig.webSocketConstructor = WebSocket;

export default async (req: VercelRequest, res: VercelResponse) => {
  const client = new Client(process.env.DATABASE_URL);
  await client.connect();

  const longitude = parseFloat(req.headers['x-vercel-ip-longitude'] as string ?? '-122.47');
  const latitude = parseFloat(req.headers['x-vercel-ip-latitude'] as string ?? '37.81');

  const { rows: sites } = await client.query(`
    SELECT 
      id_no, name_en, category,
      'https://whc.unesco.org/en/list/' || id_no || '/' AS link,
      location <-> st_makepoint($1, $2) AS distance
    FROM whc_sites_2021
    ORDER BY distance
    LIMIT 10`, 
    [longitude, latitude]
  );

  res.status(200).json({ longitude, latitude, sites });
  await client.end();
}

Please shout if you're still having trouble, otherwise I'll close the issue.

domluna commented 1 year ago

so the error I had before is gone which is cool. I think now the trouble is with combining edge and serverless functions. Which I suppose is a vercel problem. Is it worthwhile to set the websocket constructor in an edge function as well?

jawj commented 1 year ago

Glad the previous error is resolved.

No, there's no need to set webSocketConstructor in an Edge Function, and trying to do so is likely to raise an error.