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

Client extensions in interactive transactions are bound to the base client #17948

Closed
Tracked by #19416
robere2 opened this issue Feb 16, 2023 · 15 comments
Closed
Tracked by #19416
Assignees
Labels
Milestone

Comments

@robere2
Copy link

robere2 commented Feb 16, 2023

Bug description

Extensions to the Prisma client have this bound to the base client as opposed to the transaction. I was not experiencing this problem in 4.9.0.

How to reproduce

  1. Create a Prisma client extension which uses this in some way.
  2. Create an interactive transaction from that extended client.
  3. Use the extension method within your transaction.
  4. this will be the base Prisma client instead of the transaction client.

Expected behavior

When client extensions are used within a transaction, this should be bound to the transaction client instead of the original Prisma client.

Prisma information

Schema does not appear to be relevant.

const xprisma = prisma.$extends({
    client: {
        isTransaction(): boolean {
            return typeof this.$use !== "function";
        },
    }
});

console.log(xprisma.isTransaction()) // false
await xprisma.$transaction(async (tx) => {
    console.log(tx.isTransaction()); // false. Should be true
})

Environment & setup

  • OS: Windows 11 22H2
  • Database: PostgreSQL
  • Node.js version: 18.14.0

Prisma Version

4.10.1
@robere2 robere2 added the kind/bug A reported bug. label Feb 16, 2023
@robere2
Copy link
Author

robere2 commented Feb 16, 2023

Hmm... I've downgraded to 4.9.0 and am still experiencing this issue. Perhaps it was working before for some other reason in one of my recent changes, or I've not correctly downgraded.

Regardless, I do think this is an issue, but maybe it should be re-tagged as a feature request?

@janpio janpio added bug/1-unconfirmed Bug should have enough information for reproduction, but confirmation has not happened yet. team/client Issue for team Client. topic: clientExtensions labels Feb 16, 2023
@janpio
Copy link
Member

janpio commented Feb 16, 2023

Still a bug potentially, just not a regression. We'll take a look.

@millsp millsp added topic: interactiveTransactions bug/2-confirmed Bug has been reproduced and confirmed. and removed bug/1-unconfirmed Bug should have enough information for reproduction, but confirmation has not happened yet. labels Feb 16, 2023
@millsp
Copy link
Member

millsp commented Feb 16, 2023

Thanks, I can confirm this. I think the right thing to do is to make this work as you expected, as it would be totally unexpected that an extension could emit queries outside an interactive transaction while being explicitly used there.

That said, I see anothe potential issue if we enable/fix this: it is possible that an extension would want to also emit a batch transaction (call $transaction), but such calls aren't allowed to happen if you're already in an interactive tx. So we will need to look into how to handle that properly as well.

For reference, "$use" | "$on" | "$connect" | "$disconnect" | "$transaction" are all disallowed in an itx.

@ke-interel
Copy link

Is there a timeline for when a fix is planned?

@janpio
Copy link
Member

janpio commented Mar 30, 2023

No, we never commit to timelines publicly because plans change. clientExtensions is a preview feature that has a few bugs right now, and we will want to resolve these before the feature can be made generally available. I expect that we push in that direction soon.

@joeka36
Copy link

joeka36 commented Apr 11, 2023

Are there any other workaround to mitigate this for the time-being? Also running into the same issue.

@marcus13371337
Copy link

I'm experiencing the same issue!

@marcus13371337
Copy link

Especially frustrating in our integration tests, where we have connection_limit=1, which means that if we are doing something like this:

await prisma.$transaction(tx => {
    tx.myModel.create({
          data: {}
     })
     
     return tx.myModel.myExtension()
})

The call to myExtension will wait for a new connection, but since that is not available, as the transaction already used up all available connections, the code gets stuck until our test timeout runs out...

@MichalLytek
Copy link

MichalLytek commented May 18, 2023

I'm also suffering from this issue:
#5022 (comment)

#16500 (comment)

It's blocking me from migrating to use client extensions instead of generating code for custom db repositories.

@SevInf
Copy link
Contributor

SevInf commented Jun 5, 2023

This is fixed in #19565 and will be available in the next prisma release.
For those of you who'd like to test a fix sooner - you can use 4.16.0-dev.17 snapshot version. Be aware that dev version is not considered stable and is not recommended for production usage, but it should be enough to verify that fix is working for you.

@SevInf SevInf closed this as completed Jun 5, 2023
@marcus13371337
Copy link

Nice! Will try it out tomorrow! 🎉

@marcus13371337
Copy link

marcus13371337 commented Jun 7, 2023

Tried it and it seems to have fixed the tests I written for my client extensions regarding transactions (which was failing previously) 🎉

However a little heads up, it seems as if it broke some other tests, and the error I'm getting:

error TypeError: 'get' on proxy: property '_extensions' is a read-only and non-configurable data property on the proxy target but the proxy did not return its actual value (expected '#<et>' but got '#<et>')
    at ru (/node_modules/.pnpm/@prisma+client@4.16.0-dev.17_prisma@4.16.0-dev.17/node_modules/@prisma/client/runtime/library.js:162:11145)
    at a (/node_modules/.pnpm/@prisma+client@4.16.0-dev.17_prisma@4.16.0-dev.17/node_modules/@prisma/client/runtime/library.js:177:10309)
    at /node_modules/.pnpm/@prisma+client@4.16.0-dev.17_prisma@4.16.0-dev.17/node_modules/@prisma/client/runtime/library.js:177:10445
    at AsyncResource.runInAsyncScope (node:async_hooks:203:9)
    at /node_modules/.pnpm/@prisma+client@4.16.0-dev.17_prisma@4.16.0-dev.17/node_modules/@prisma/client/runtime/library.js:177:10425
    at Proxy.runInChildSpan (/node_modules/.pnpm/@prisma+client@4.16.0-dev.17_prisma@4.16.0-dev.17/node_modules/@prisma/client/runtime/library.js:174:1343)
    at Proxy.<anonymous> (/node_modules/.pnpm/@prisma+client@4.16.0-dev.17_prisma@4.16.0-dev.17/node_modules/@prisma/client/runtime/library.js:178:848)
    at Proxy._request (/node_modules/.pnpm/@prisma+client@4.16.0-dev.17_prisma@4.16.0-dev.17/node_modules/@prisma/client/runtime/library.js:177:10348)
    at Proxy.<anonymous> (/node_modules/.pnpm/@prisma+client@4.16.0-dev.17_prisma@4.16.0-dev.17/node_modules/@prisma/client/runtime/library.js:178:848)
    at Proxy.$queryRawInternal (/node_modules/.pnpm/@prisma+client@4.16.0-dev.17_prisma@4.16.0-dev.17/node_modules/@prisma/client/runtime/library.js:177:7988)

Will see if I can come up with a minimal reproduction for the issue

@marcus13371337
Copy link

marcus13371337 commented Jun 7, 2023

$queryRaw* on transactions seems to be broken in this version, here is a minimal reproduction (note, I've added some extensions to my Prisma client). Should I report this in a separate issue? @SevInf

  describe("success", () => {
    test("breaks if using $queryRawUnsafe", async () => {
      const result = await prisma.$queryRawUnsafe(
        `SELECT * FROM machine_user;`
      );

      expect(result).toEqual([]);
    });

    test("breaks if using $queryRaw", async () => {
      const result =
        await prisma.$queryRaw<unknown>`SELECT * FROM machine_user;`;

      expect(result).toEqual([]);
    });
  });

  describe("error", () => {
    test("breaks if using $queryRawUnsafe", async () => {
      const result = await prisma.$transaction(async (tx) => {
        return tx.$queryRawUnsafe(`SELECT * FROM machine_user;`);
      });

      expect(result).toEqual([]);
    });

    test("breaks if using $queryRaw", async () => {
      const result = await prisma.$transaction(async (tx) => {
        return tx.$queryRaw<unknown>`SELECT * FROM machine_user;`;
      });

      expect(result).toEqual([]);
    });
  });

Both the "error"-tests fails with the following error:

TypeError: 'get' on proxy: property '_extensions' is a read-only and non-configurable data property on the proxy target but the proxy did not return its actual value (expected '#<et>' but got '#<et>')
 ❯ ru node_modules/.pnpm/@prisma+client@4.16.0-dev.17_prisma@4.16.0-dev.17/node_modules/@prisma/client/runtime/library.js:162:11145
 ❯ a node_modules/.pnpm/@prisma+client@4.16.0-dev.17_prisma@4.16.0-dev.17/node_modules/@prisma/client/runtime/library.js:177:10309
 ❯ node_modules/.pnpm/@prisma+client@4.16.0-dev.17_prisma@4.16.0-dev.17/node_modules/@prisma/client/runtime/library.js:177:10445
 ❯ AsyncResource.runInAsyncScope node:async_hooks:203:9
 ❯ node_modules/.pnpm/@prisma+client@4.16.0-dev.17_prisma@4.16.0-dev.17/node_modules/@prisma/client/runtime/library.js:177:10425
 ❯ Proxy.runInChildSpan node_modules/.pnpm/@prisma+client@4.16.0-dev.17_prisma@4.16.0-dev.17/node_modules/@prisma/client/runtime/library.js:174:1343
 ❯ Proxy.<anonymous> node_modules/.pnpm/@prisma+client@4.16.0-dev.17_prisma@4.16.0-dev.17/node_modules/@prisma/client/runtime/library.js:178:848
 ❯ Proxy._request node_modules/.pnpm/@prisma+client@4.16.0-dev.17_prisma@4.16.0-dev.17/node_modules/@prisma/client/runtime/library.js:177:10348
 ❯ Proxy.<anonymous> node_modules/.pnpm/@prisma+client@4.16.0-dev.17_prisma@4.16.0-dev.17/node_modules/@prisma/client/runtime/library.js:178:848
 ❯ Proxy.$queryRawInternal node_modules/.pnpm/@prisma+client@4.16.0-dev.17_prisma@4.16.0-dev.17/node_modules/@prisma/client/runtime/library.js:177:7988

FYI @Jolg42

@Jolg42
Copy link
Member

Jolg42 commented Jun 7, 2023

Thanks @marcus13371337! If you can create a new issue, that would be great 🙌🏼

@marcus13371337
Copy link

Issue created here

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

No branches or pull requests

9 participants