question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Transaction with bad input should rollback (when using middleware)

See original GitHub issue

Bug description

If one query in the transaction fails the input validation, the transaction doesn’t rollback and the other queries proceed normally.

Error:

Error: Argument city for data.address.create.city is missing.

    at Document.validate (/app/node_modules/.prisma/client/runtime/index.js:32462:19)
    at NewPrismaClient._executeRequest (/app/node_modules/.prisma/client/runtime/index.js:34399:17)
    at NewPrismaClient._requestWithMiddlewares (/app/node_modules/.prisma/client/runtime/index.js:34350:19)
    at /app/node_modules/.prisma/client/runtime/index.js:34343:53
    at /app/src/common/prisma/retry.js:35:38
    at NewPrismaClient._requestWithMiddlewares (/app/node_modules/.prisma/client/runtime/index.js:34343:16)
    at /app/node_modules/.prisma/client/runtime/index.js:34332:54
    at AsyncResource.runInAsyncScope (async_hooks.js:197:9)
    at NewPrismaClient._request (/app/node_modules/.prisma/client/runtime/index.js:34332:27)
    at Object.requestTransaction (/app/node_modules/.prisma/client/runtime/index.js:34469:39)

How to reproduce

Consider the following schema:

model User {
  id   Int    @id @default(autoincrement())
  name String
}

Run the following code:

const prisma = new PrismaClient();

prisma.$transaction([
  prisma.user.create({ data: { name: 'emile' } })
  prisma.user.create({ data: {} })
])

There should be a user in the database as the transaction is not rollback.

Expected behavior

The transaction should be rollback.

Environment & setup

  • OS: Linux
  • Database: PostgreSQL
  • Node.js version: 14
  • Prisma version: 2.21.2

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:2
  • Comments:8 (8 by maintainers)

github_iconTop GitHub Comments

1reaction
millspcommented, Jul 1, 2021

If we “fix” things so that it can fail/stop on Document.validate, we’ll end up with a mediocre solution that just stops on the first error. Rollback won’t happen and you’ll have a partial “transaction” applied. Transactions are sequential, before you move to the next one you wait that the middleware has finished (and that’s the query exec). So no rollback like asked in the OP. (this is again because async makes the failure non-immediate).

1reaction
millspcommented, Jun 30, 2021

So in link with what I mentioned above, the current transaction implementation relies on failure immediateness to rollback. For this reason, since middlewares are asynchronous by design and under the hood, we cannot rollback. Doing await next(params) triggers the query to be executed. This is a problem because we expect a result, but at the same time we want previous queries to rollback if needed. Because of this, we cannot rely on immediate failure to rollback, we are awaiting results - one at a time.

The obvious solution now is that we implement https://github.com/prisma/prisma/issues/1844

Read more comments on GitHub >

github_iconTop Results From Across the Web

Practical Transaction Handling in Microservice Architecture
In the case of failure in a service in the workflow, we need to rollback the overall transaction.
Read more >
hotchocolate - Is there a way to implement a transaction-per ...
At the beginning of the request, we begin a transaction and then delegate to the next middleware. If any unhandled exceptions occur, we...
Read more >
ASP.NET Core: One transaction per server roundtrip - Medium
One (simple) solution is to wrap it all up into one database transaction, which can be rolled back in case of failure (or...
Read more >
A clean way to implement database transaction in Golang
The idea is simple: it takes a context and a callback function as input, then it will start a new db transaction, create...
Read more >
Middleware Architecture - Transactions
Concurrent execution allows taking advantage of multiprocessing facilities, both for process execution and for input-output. Concurrent ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found