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

WriteConflict under MongoDB #97

Open
SunburntRock89 opened this issue Jun 27, 2022 · 11 comments
Open

WriteConflict under MongoDB #97

SunburntRock89 opened this issue Jun 27, 2022 · 11 comments

Comments

@SunburntRock89
Copy link
Contributor

Simply navigating to any page gives me

set(): Error: 
Invalid `this.prisma[this.sessionModelName].update()` invocation in
D:\Documents\Projects\Lunus\Rewrite\node_modules\@quixo3\prisma-session-store\dist\lib\prisma-session-store.js:492:81

  489 case 3:
  490     _a.trys.push([3, 8, , 9]);
  491     if (!(existingSession !== null)) return [3 /*break*/, 5];
 492     return [4 /*yield*/, this.prisma[this.sessionModelName].update(
  Error occurred during query execution:
ConnectorError(ConnectorError { user_facing_error: None, kind: RawDatabaseError { code: "unknown", message: "Command failed (WriteConflict): WriteConflict error: this operation conflicted with another operation. Please retry your operation or multi-document transaction.)" } })
Error: 
Invalid `this.prisma[this.sessionModelName].update()` invocation in
D:\Documents\Projects\Lunus\Rewrite\node_modules\@quixo3\prisma-session-store\dist\lib\prisma-session-store.js:492:81

  489 case 3:
  490     _a.trys.push([3, 8, , 9]);
  491     if (!(existingSession !== null)) return [3 /*break*/, 5];
 492     return [4 /*yield*/, this.prisma[this.sessionModelName].update(
  Error occurred during query execution:
ConnectorError(ConnectorError { user_facing_error: None, kind: RawDatabaseError { code: "unknown", message: "Command failed (WriteConflict): WriteConflict error: this operation conflicted with another operation. Please retry your operation or multi-document transaction.)" } })
    at RequestHandler.request (D:\Documents\Projects\Lunus\Rewrite\node_modules\@prisma\client\runtime\index.js:49026:15)
    at async PrismaClient._request (D:\Documents\Projects\Lunus\Rewrite\node_modules\@prisma\client\runtime\index.js:49919:18

Presumably there's multiple update commands being ran at the same time?

@kleydon
Copy link
Owner

kleydon commented Jun 27, 2022

Perhaps this is the result of using multiple prisma clients? E.g, one passed to the PrismaSessionStore constructor, other(s) for other backend functionality?

The one passed to the PrismaSessionStore constructor has a "background process" checking to see if sessions have expired; perhaps the conflict is related to this check?

(Just a paranoid theory; I haven't looked at the code.)

Also - not using a separate prisma client for the PrismaSessionStore constructor (i.e. passing in a pre-existing prisma client, used elsewhere in the backend) has historically proven problematic for some users; though its not clear to me why that might be the case, or if it is still the case. Might be worth a try.

@SunburntRock89
Copy link
Contributor Author

Double checked and I'm sure that only 1 prisma client is present.

...passing in a pre-existing prisma client, used elsewhere in the backend) has historically proven problematic for some users

That's frowned upon by Prisma themselves so probably not a great thing to have to put up with.
I don't think that this would be symptomatic of that anyway, it's presumable that 2 different queries within the lib are trying to update the same thing at the same time. I see a few .updateMany queries in log mode, maybe it's one of them? (what do they actually do?)

@SunburntRock89
Copy link
Contributor Author

SunburntRock89 commented Jun 28, 2022

Just had a brainwave, could this be caused by the fact that this library manually calls prisma.$connect?

Edit: seemingly not

@kleydon
Copy link
Owner

kleydon commented Jun 29, 2022

Guessing not... But maybe?
Possibly relevant, from the docs:

It is not necessary to call $connect() thanks to the lazy connect behavior: The PrismaClient instance connects lazily when the first request is made to the API ($connect() is called for you under the hood).

If you need the first request to respond instantly and cannot wait for a lazy connection to be established, you can explicitly call prisma.$connect() to establish a connection to the data source

To avoid too many connections in a long-running application, we recommend that you use a single instance of PrismaClient across your application.

@SunburntRock89 - Earlier, you wrote:

Double checked and I'm sure that only 1 prisma client is present.
...passing in a pre-existing prisma client, used elsewhere in the backend) has historically proven problematic for some users
That's frowned upon by Prisma themselves so probably not a great thing to have to put up with.

Curious: If Prisma is recommending using a single instance of PrismaClient, why is it frowned upon to pass an existing prisma client from back-end code to the prisma-session-store library code?

@SunburntRock89
Copy link
Contributor Author

Curious: If Prisma is recommending using a single instance of PrismaClient, why is it frowned upon to pass an existing prisma client from back-end code to the prisma-session-store library code?

Sorry, can see why that statement might be confusing. I meant that creating multiple clients was frowned upon because you implied doing that.
You're only meant to use one client.

@kleydon
Copy link
Owner

kleydon commented Jun 29, 2022

Ah - got it.

I suppose one wrinkle is that some people (not all) report issues (I believe Typescript typing issues) when they try to pass a pre-existing prisma client to the PrismaSessionStore constructor; in this case, people are likely using at least two clients (one for prisma-session-store, another for back-end code). But Prisma does support multiple clients, so I'm not yet convinced that two clients should be a problem.

@SunburntRock89
Copy link
Contributor Author

Yeah, multiple clients shouldn't be an issue regardless, it's just a connection pooling thing iirc. Making multiple pools means far more connections, some of which won't be touched at all. It's probably more a thing of trying to prevent people from making a new connection pool for every single part of their app.

@kleydon
Copy link
Owner

kleydon commented Jun 29, 2022

Thanks @SunburntRock89; good to get your sense of this...

@SunburntRock89
Copy link
Contributor Author

@kleydon Whilst we (were) here, do you happen to know why, when there's no updateMany queries in the session store code, logging queries in prisma returns several updateMany queries to the Session table?

Another thing:
It may be beneficial to edit the library so that, where possible, JSON types are used instead of a JSON string.

@kleydon
Copy link
Owner

kleydon commented Jun 30, 2022

Whilst we (were) here, do you happen to know why, when there's no updateMany queries in the session store code, logging queries in prisma returns several updateMany queries to the Session table?

Good question. Guessing prisma is doing something "under the hood", but I'm not 100% certain.

@kleydon
Copy link
Owner

kleydon commented Jun 30, 2022

It may be beneficial to edit the library so that, where possible, JSON types are used instead of a JSON string.

I'll add an issue for considering this.

It's unclear to me whether there are circumstances where this might "lock things down" too much, or not.

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

No branches or pull requests

2 participants