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

Add $destroy to the client, so they client cannot be reused #12153

Open
TheVoid-0 opened this issue Mar 4, 2022 · 10 comments
Open

Add $destroy to the client, so they client cannot be reused #12153

TheVoid-0 opened this issue Mar 4, 2022 · 10 comments
Labels
kind/feature A request for a new feature. team/client Issue for team Client. topic: client api topic: performance/memory

Comments

@TheVoid-0
Copy link

TheVoid-0 commented Mar 4, 2022

Problem

It's currently hard to maintain prisma on a multi-tenant scenario that requires a lot of clients instantiated for several reasons, one of them that caused me a hard time recently, was the fact that the client does not destroy itself when $disconnect is called, not only this, but it can automatically spin up his internal pool when a new request (intentional or not) comes to him ( #12134 )

Suggested solution

Expose a $destroy function on the client for the developer have the option to complety inutilize and clean prisma from the memory, making any other attempt to call the same client result on a error.

const prismaClient = new PrismaClient();

await prismaClient.$destroy() // <- not sure if promise is needed, but probably a good option

await prismaClient.$executeRaw`SELECT 1`
// Error: 'Client destroyed/closed'

Alternatives

This also could be a client option on initialization, perhaps a flag enabling destruction when $disconnect is called?

Additional context

The whole point in this feature is to let the user-developer decide what happens if a disconnected client receives a query request, silently restarting the prisma internal pool is dangerous for the application and the developer should have the tools to control it, destroying the client is one solution for that, this way the developer assures the client will not accept any incoming queries.

In the context of a Tenant application, a leaked client is obviously a reason for an error in the developer code logic, however the current behavior of prisma does not let the developer take control of that, this could even lead to severe consequences on the database, since a small leak in code logic could leave thousands of clients reopen automatically without the developer even notice

@janpio janpio added kind/feature A request for a new feature. team/client Issue for team Client. topic: client api labels Mar 4, 2022
@itsravenous
Copy link

itsravenous commented Mar 11, 2022

I would love to see this too. My use case might be a bit niche, but I'm currently spinning up a new PrismaClient between jest tests because I destroy and re-migrate the DB between tests to prevent state leaking, and I get the "more than 10 prisma clients are already running" warning. I don't think it's actually a problem as it's only while the tests run, but in case Prisma is more aggressive about this in future I'd like my tests not to break.

I can't re-use the same PrismaClient across all tests because it fails to connect once the DB has been re-created.

Ideally I'd be able to destroy each PrismaClient after each test.

This is my test setup file (provided to jest's setupFilesAfterEnv). If there's an easier/more idiomatic way of achieving what I'm trying to do, I'm all ears 🐘 . I'm aware my approach is different to the official integration test recipe, in that it clears data between each test, rather than each test suite.

let prisma: PrismaClient
beforeEach(async () => {
  prisma = new PrismaClient();
  // Create the database tables as defined in schema.prisma
  execSync('npx prisma db push', {
    env: {
      ...process.env,
      DATABASE_URL: testDatabaseUrl,
    },
  });

  // Seed test users with various roles
  await prisma.user.createMany({
    data: testUsersDb,
  });
});

afterEach(() => {
  // 💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡
  // Ideally call prisma.$destroy() here. Have tried prisma.$disconnect() but doesn't seem to
  // squish the warning - i.e. the client is still running even though disconnected
  // 💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡

  // Destroy the DB to prevent leaking data between tests
  execSync('npx prisma migrate reset --force', {
    env: {
      ...process.env,
      DATABASE_URL: testDatabaseUrl,
    },
  });
});

@diovannaschell
Copy link

I also would appreciate this a lot! I need at least some way to remove the PrismaClient references from memory, in the current scenario when a client is $disconnected it remains somewhere in the Prisma code, after 10 instances are created, prisma emits a warning saying that there already are 10 instances running, the thing is that I DO NOT want them to be running anynmore, I really need a way to completly destroy the client so I can safely create new ones later.

@janpio
Copy link
Member

janpio commented Mar 12, 2022

I can't re-use the same PrismaClient across all tests because it fails to connect once the DB has been re-created.

Is this reproducible @itsravenous? If so, please make sure you open a bug report issue. That seems the underlying problem here. Thanks!

@itsravenous
Copy link

Is this reproducible @itsravenous? If so, please make sure you open a bug report issue. That seems the underlying problem here. Thanks!

Actually it must be something to do with my setup; I tried a simple repro and the client is able to connect after deleting and re-creating the DB.

Apologies for the issue hijack.

@ogroppo
Copy link

ogroppo commented May 26, 2022

This is still very much an issue, with 10 test files memory builds up to 1GB+

@janpio
Copy link
Member

janpio commented May 30, 2022

Please open a bug report issue with a reproduction of this, so we can look at it or benchmark other changes against this. Thanks.

@bernardopantaleao
Copy link

@diovannaschell @TheVoid-0
Gente, desculpa correr atrás de vocês aqui, precisava contactar vocês. Trabalhamos juntos no Obrinha :)

@slaesh
Copy link

slaesh commented May 11, 2023

any news on this topic?
we are running into this as well..
due to a workaround to these AWS RDS Signer issues #6587 #7869.

@janpio janpio changed the title Add $destroy to the client so it cannot be reused Add $destroy to the client, so they client cannot be reused May 17, 2023
@wmadden
Copy link

wmadden commented Sep 26, 2023

This is an issue for us too 👍🏻

@didiercapozzi
Copy link

In my case I resolved this issue by testing like this:

const db = new PrismaClient({
  datasources: {
    db: {
      url: process.env.DATABASE_TEST_URL,
    },
  },
})

beforeEach(async () => {
  // Resets and migrates database before running tests
  await db.$disconnect()
  execSync(`DATABASE_URL=${process.env.DATABASE_TEST_URL} yarn reset-test-db`)
  await db.$connect()
})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/feature A request for a new feature. team/client Issue for team Client. topic: client api topic: performance/memory
Projects
None yet
Development

No branches or pull requests

9 participants