Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Patch: Connection stuck after a while #738

Merged
merged 2 commits into from
Nov 26, 2023
Merged

Conversation

wackfx
Copy link
Contributor

@wackfx wackfx commented Nov 24, 2023

Hey @porsager

I noticed that, after a while, I had random "WRITE_TIMEOUT" // "CONNECT_TIMEOUT" happening and my system became unresposive.

It appears that the socket, once closed, doesn't correctly reconnect. By recreating the socket, it looks like it solved the issue. Today, this behavior is done only on "secured" but I believe we could have it for all connections.

I believe it's ok to do so as 1) it shouldn't happen often 2) socket is closed and will eventually be garbage collected 3) it's already done for secured connections

Reproducing & checks

Context: I'm using Bun
I started with Postgres down - and started postgres after the first attempt to try to reproduce #641

⚠️ It looks like this behavior doesn't happen on Node - when using node with or without my patch, the socket correctly reconnects. I believe it may be solved by some Node shenanigan and impacting Bun (or even Worker?) only.

import postgres from 'postgres'

const sql = postgres(`${process.env['DATABASE_URL']}`, {
    max: 1, # trigger the issue sooner
    max_lifetime: 1, # trigger the issue sooner by closing the connection really quickly
})

setInterval(async () => {
    console.log((await sql`SELECT * FROM pg_am`)[0])
}, 3000)

Before

After the first query - connection is closed (because of max_lifetime: 1) and doesn't reconnect
image

After

It reconnects well.
image

@dimonnwc3
Copy link

dimonnwc3 commented Nov 26, 2023

@wackfx thanks for contribution. I've experienced the same, connection in bun times out and then postgres is not available anymore, with the following error: write CONNECT_TIMEOUT postgres:5432

before it gets merged, a workaround is to use a "secured" connection?

@wackfx
Copy link
Contributor Author

wackfx commented Nov 26, 2023 via email

@porsager
Copy link
Owner

porsager commented Nov 26, 2023

Very nice debugging, and thanks for the proposed fix @wackfx, but I actually think this should be fixed on Buns end. Making workarounds for Bun bugs in all libraries is just a useless work multiplier. If we were using native Bun apis, it would be a completely different matter, but this is Bun wanting to mimick Node.js APIs, so I'm certain they'd also want to have a bug like this fixed. - Did you make an issue with Bun, and a minimal reproducible case using only net (tcp)?

@porsager
Copy link
Owner

Even so, you are also right, there shouldn't be any actual performance concerns or issues recreating the socket for non ssl connections too, so let's take your simplification 😉

@porsager porsager merged commit 6f20a48 into porsager:master Nov 26, 2023
30 checks passed
@wackfx
Copy link
Contributor Author

wackfx commented Nov 26, 2023

hey @porsager - you're very right about the fact that Bun might wanna take a look into this for a better Node compat, tbh I opened this before trying to reproduce with Node.JS.

@dimonnwc3
Copy link

@porsager any plans on releasing this to npm?

@Th1nkK1D
Copy link

Amazing findings! I ran into the same issue. While waiting for a release, I use the following command to temporarily patch connection.js from this PR.

curl https://raw.githubusercontent.com/porsager/postgres/6f20a4820c683b33e7670b606d8daf5670f4b973/src/connection.js > node_modules/postgres/src/connection.js

PS. I added it in my docker file after bun install, but you and also run it manually.

@mattbishop
Copy link

Probably can remove the two individual socket.removeListener() calls a few lines before this change too.

@WildEgo
Copy link

WildEgo commented Jan 21, 2024

Can we publish this..? It's an high impact bug fix

@hex2f
Copy link

hex2f commented Jan 29, 2024

any update on when this will make it into a release? its causing me a lot of headaches right now 😅

@emilienbidet
Copy link

It cause me a lot of troubles too. Latest release is from November, may we can make a new one?

@porsager
Copy link
Owner

A reminder at the right time ;) Just released v3.4.4

@edwardchew97
Copy link

A reminder at the right time ;) Just released v3.4.4

Deployed the latest version yesterday, 12 hours passed and so far it seems to resolve the issue in our case! 🙌
image

@porsager
Copy link
Owner

Fantastic! Mind sharing what you're running on? Bun?

@porsager
Copy link
Owner

porsager commented Apr 1, 2024

@edwardchew97 are you using bun?

@kam-st
Copy link

kam-st commented Jun 9, 2024

Hello, so pulling directly from github to resolve cloudflare issue. But the issue of queries getting stuck persists. The way I reproduce stuck queries is through repetitive refresh of page. The queries though authjs gets stuck and whole server gets jammed.

Stack is NextJS | Drizzle | AuthJS (Drizzle running through postgresjs driver)

The reason I know this issue is with postgresjs is because if I use neon drivers. Then the issue does not persists and everything works flawlessly.

PS: I am using nodeJS

@gregory-krieger
Copy link

gregory-krieger commented Jun 29, 2024

This is the solution I implemented, just replace this :

import "dotenv/config";

import { drizzle } from "drizzle-orm/postgres-js";
import postgres from "postgres";
import * as schema from "./schema";

const connectionString = process.env.DATABASE_URL;

// Disable prefetch as it is not supported for "Transaction" pool mode
export const client = postgres(connectionString!, {
  prepare: false,
  ssl: false,
});
export const db = drizzle(client, { schema });

with this :

import "dotenv/config";
import { PostgresJsDatabase, drizzle } from "drizzle-orm/postgres-js";
import postgres from "postgres";
import * as schema from "./schema";

declare global {
  var database: PostgresJsDatabase<typeof schema> | undefined;
}

const connectionString = process.env.DATABASE_URL;

if (process.env.NODE_ENV === "production") {
  database = drizzle(
    postgres(connectionString!, {
      prepare: false,
    }),
    { schema },
  );
} else {
  if (!global.database)
    global.database = drizzle(
      postgres(connectionString!, {
        prepare: false,
      }),
      { schema },
    );
  database = global.database;
}
export const db = database;

I'm using Drizzle + Supabase + Next.js

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.