-
Notifications
You must be signed in to change notification settings - Fork 19
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
Invalid invocation
error caused by an update
query
#88
Comments
Invalid invocation
caused by an update
queryInvalid invocation
error caused by an update
query
Oh, forgot to say but it looks like it's not causing anything db-wise. All my records are still there after this error pops up and nothing seems to really change. |
Hey @fowled - glad you're finding this useful! I've been seeing this error too sometimes; not entirely sure why. One going theory is that maybe this error is the result of a race condition: perhaps when there are multiple prisma clients talking to a database, they make requests that collide, yielding errors like this. I haven't had the bandwidth to consider this carefully, but - maybe? If you have (or develop) any insight over time related to this, would love to know about it. Cheers. |
Thanks for your answer! Do you know what's at the origin of that update query? It should help us in resolving the issue. |
This might be related - prisma/prisma#2955 Though I don't really see, in our case, how the db would get 'locked' |
I found something interesting, after having enabled
I think what's happening here is that the database gets locked after the first Maybe the @kleydon - can you think of any way to fix that? |
@fowled Thanks for digging into this.
I've experienced this error using Prisma with Postgres, so I'm pretty sure it isn't an sql-lite specific issue. Unfortunately, my understanding of databases under-the-hood is fairly tenuous (a big part of why I'm leaning on prisma in the first place :) What you're saying does seem plausible... Its not immediately clear to me, though, how to test out an alternative that would result in different SQL queries (or alternately-sequenced SQL queries)... My first guess is that this is mostly up to prisma. Perhaps something related to transactions? Perhaps resorting to "raw" sql queries, made via prisma (though it doesn't seem like that should ever really be necessary...)? |
I'm not sure either to be honest, I'm relying on Prisma to simplify CRUD operations as well 😅 I noticed one thing using Prisma Studio though, every time I refresh an API page (that uses express-session), the Is that a normal behavior? I thought that the Here's what I mean: 2022-05-22.15-22-06.mp4 |
Hi @fowled - sorry for the late reply here... I haven't checked the express session docs yet to be certain, but I'm pretty sure that there is a setting (possibly the default behavior?) governing whether or not My hunch is that refreshing the page is causing a request to occur, via express, that automatically updates Hope this helps... |
Thanks for the update @kleydon. I just changed several things in my configuration file: app.use([
session({
secret: process.env.SESSION_SECRET,
cookie: { secure: !process.env.SECURE_COOKIE, maxAge: 1000 * 60 * 60 * 24 * 7 },
resave: false,
saveUninitialized: false,
store: new PrismaSessionStore(database, { loggerLevel: "log" }),
}),
]); and a new error shows up, pointing to this function: {
/**
* Refresh the time-to-live for the session with the given `sid`.
*
* @param sid the id of the session to refresh
* @param session the data of the session to resave
* @param callback a callback notifying that the refresh was completed
* or that an error occurred
*/
public readonly touch = async (
sid: string,
session: PartialDeep<SessionData>,
callback?: (err?: unknown) => void
) => {
if (!(await this.validateConnection())) return callback?.();
const ttl = getTTL(this.options, session, sid);
const expiresAt = createExpiration(ttl, {
rounding: this.options.roundTTL,
});
try {
const existingSession = await this.prisma[
this.sessionModelName
].findUnique({
where: { sid },
});
if (existingSession !== null) {
const existingSessionData = {
...this.serializer.parse(existingSession.data ?? '{}'),
cookie: session.cookie,
};
await this.prisma[this.sessionModelName].update({
where: { sid: existingSession.sid },
data: {
expiresAt,
data: this.serializer.stringify(existingSessionData),
},
});
}
// *** If there is no found session, for some reason, should it be recreated from sess *** ?
if (callback) defer(callback);
} catch (e: unknown) {
this.logger.error(`touch(): ${String(e)}`);
if (callback) defer(callback, e);
}
};
} I ended up deleting it in the
After some research, I couldn't find anything in the docs in that regard. Of course, my hacky workaround isn't the best, and I'm probably missing a key feature of your module now. Do you know what is the purpose of that |
Hold up... I just noticed my issue was exactly what @lachezargrigorov reported here: #64 And I can confirm that the |
Hi @fowled,
I believe that the purpose of I'm not sure when exactly Unfortunately I don't have much time this week to drill into this... If I did though, I would probably first look through references to
Good to know; hopefully this will help in narrowing down what's happening / is expected to happen. |
using nestjs prisma postgres did exactly whats written in docs console when i log out (destroy session)
|
it seems to be working for me now, not sure what I did, perhaps lots of restarts to server .. hopefully it wont return logout(req: any) {
if (!req.session.user) {
return { err: "must be logged" }
}
req.session.destroy()
return { msg: "Logged out successfully." }
} |
yea unfortunately the error returns randomly when i try to log out. I can't use this package until it's fixed sadly |
Hi @TamirCode - Sorry to hear it. I'm a bit limited to work on this time-wise right now, but hopefully there are others who can investigate? |
I'm using v I found out that if I reloaded my app quickly (CMD+R in the browser), the error was more likely to happen. And tracing back (and by some other explanations on this thread) the culprit seems to be the So when my application loaded a view (html), parallel requests are triggered by the browser to download all the CSS/JS assets, and due to the middleware ordering I had a session was being set up even for static assets. This means in a very short amount of time, several concurrent request to my backend were made, all of them trying to So after I inverted the order of the middlewares in my express application (so that first assets are served from express, and later if no asset is served, a session is setup and then my handlers take over) the problem stopped happening. Given I was still concerned about multiple concurrent requests (by the same user) "touching" the same record in the database in a very limited period of time, I ended up writing my own "Prisma session store" for learning/understanding purposes (which you can find here) and I ended up doing the following workaround so no multiple "touches" happen to the same record concurrently. The specific part of the code that implements this protection is here for reference: async touch(sid, session, cb) {
if (this.isTouching[sid]) {
return cb();
}
this.isTouching[sid] = true;
try {
await this.db.session.update({
where: { sid },
data: { data: JSON.stringify(session) },
});
} finally {
delete this.isTouching[sid];
}
return cb();
} So, even if probably this is more like a "workaround" than a proper solution, I think for this specific library, one could create a child class of Hope this helps others with this problem 👍 |
@msurdi Appreciate your notes / insight. You mentioned that you fixed the problem by inverting the order of your middlewares, and then you added the set of If not: Is there any chance you might be willing to try a quick test? For science :)? I'm considering adding this "workaround" fix to the lib, but its hard for me to test/verify, because I've never seen this behavior... I'd dearly love to know whether the approach you offer above definitely fixed things (in the context of your side project), or whether this remains an unknown... Thanks again for posting, -K |
Hi @kleydon! I've just pushed this minimal example to reproduce the issue and the workarounds I've found so far. Instructions are in the readme and in the code comments. Hope it helps to find a better solution to this problem. |
Appreciate it, @msurdi! I'm pretty short on time these days - so I may end up temporarily adding just a work-around but - glad that there is a repro that will allow this to be explored properly at some point. |
PR #104 merged. |
Sorry for my late answer, I've been travelling all over the weekend. I've just looked at the changes and they look good to me. Thanks for addressing this. |
I don't seem to be getting the error after having updated. Thanks @kleydon! |
@msurdi - no worries; appreciate your being willing to take a look (and thanks for "cracking the case", earlier!) Its not 100% clear to me whether the issue you identified is the only one that people are experiencing / referencing here, but - glad that at least one part of the problem is clearer now, and has a work-around... |
@fowled - Glad to hear. Appreciate your taking a look! |
Going to go out on a limb here, and call this issue solved-for-the-moment (albeit with a work-around). |
Hello!
I've been using your module for a bit and I must say it fulfils its mission perfectly.
But sometimes, a random error shows up, and I have no idea why:
I'm using
@quixo3/prisma-session-store@3.1.5
with aSQLite
database.Do you have an idea of what's causing it?
Thanks a lot!
The text was updated successfully, but these errors were encountered: