Prisma1: The MongoDB connector should support transactions for nested mutations

Created on 19 Dec 2018  路  7Comments  路  Source: prisma/prisma1

Currently, nested mutations with the MongoDB connector are not executed transactionally and therefore might bring your project into an inconsistent state and break the API. See this issue as an example.

kinfeature rf0-needs-spec areconnectomongo

Most helpful comment

so Prisma is not safe and I should implement my own API with mongoose

All 7 comments

MongoDB itself started supporting multi-document transactions starting with 4.0.

The Prisma Mongo connector is not officially tested against 4.0 yet but we would expect it to just work. Making use of the transactional capabilities that 4.0 offers is something we would need to explicitly add though.

We currently do not think that the implementation is the main hurdle, the biggest task is to get an understanding of the performance implications and potential deadlock issues this brings with it.

The SQL connectors also always run with transactionality enabled by default. It is not yet clear to us whether this should be the case for Mongo as well or whether users would like to configure this (to avoid performance penalties for example.)

If any one has a strong opinion on this or has specific use cases where they want / do not want it we would like to hear from you!

Thanks a lot for the explanation!

I think this is a very important product decision because not supporting transactions would mean that we're accepting projects to be inconsistent which will lead to errors further down the road when using the same project.

Consider the example from this issue where the following datamodel was used:

type User {
  id: ID! @id
  name: String
  companies: [Company!]! @relation(link: INLINE)
}

type Company {
  id: ID! @id
  name: String
  user: User!
}

Note that the user field is required on the Company model.

But because the transaction failed, there was a Company node created that had no User associated with it! This will lead to a GraphQL error when that Company node with the user relation is being retrieved.

I just tested with my own API using MongoDB 4.0 and it actually worked.
I linked my User with Logs into my type User and Log and then created a new user with the object:

{ firstName: "Allan", lastName: "Lima", email: "[email protected]", emailVerified: false, logs: { create: [{ resource: "prisma", operation: "delete" }] } }

It was created, but it was a small scale test. Everything worked fine. I don't think we should rush things, but it looks pretty solid with MongoDB 4.0. I'll be watching this thread to know your conclusions

* edit *

I don't know yet how to format code like the comment from nikolasburk

Hey @allanplima, here's how to format multi-line code on Github. Might I also suggest using json or js as the language like so.

```js
<code goes here>
```

Also if your new to markdown in general I recommend reading Github's markdown guide or the Mastering Markdown guide they are both pretty similar so only reading one is fine.

Doesn't work for me with MongoDB 4.0.6.

Im trying this (from the docs)

const newUserWithLinks = await prisma
  .createUser({
    name: "Alice",
    email: "[email protected]",
    password: "IlikeTurtles",
    links: {
      create: [{
        description: "My first link",
        url: "https://www.prisma.io"
      }, {
        description: "My second link",
        url: "https://www.howtographql.com"
      }]
    }, 
  })

the model is:

type Link {
  id: ID! @id
  createdAt: DateTime!
  description: String!
  url: String!
  postedBy: User
  votes: [Vote!]! @relation(link: INLINE)
}

type User {
  id: ID! @id
  name: String!
  email: String! @unique
  password: String!
  links: [Link!]! @relation(link: INLINE)
  votes: [Vote!]! @relation(link: INLINE)
}

type Vote {
  id: ID! @id
  link: Link!
  user: User!
}

and I get the following error:

{
  "result": {
    "data": null,
    "errors": [
      {
        "message": "Variable '$data' expected value of type 'UserCreateInput!' but got: {\"name\":\"Alice\",\"email\":\"[email protected]\",\"password\":\"IlikeTurtles\",\"links\":{\"create\":[{\"description\":\"My first link\",\"url\":\"https://www.prisma.io\"},{\"description\":\"My second link\",\"url\":\"https://www.howtographql.com\"}]}}. Reason: 'links.create[0].createdAt' Expected non-null value, found null. (line 1, column 11):\nmutation ($data: UserCreateInput!) {\n          ^",
        "locations": [
          {
            "line": 1,
            "column": 11
          }
        ]
      },
      {
        "message": "Variable '$data' expected value of type 'UserCreateInput!' but got: {\"name\":\"Alice\",\"email\":\"[email protected]\",\"password\":\"IlikeTurtles\",\"links\":{\"create\":[{\"description\":\"My first link\",\"url\":\"https://www.prisma.io\"},{\"description\":\"My second link\",\"url\":\"https://www.howtographql.com\"}]}}. Reason: 'links.create[0].createdAt' Expected non-null value, found null. (line 1, column 11):\nmutation ($data: UserCreateInput!) {\n          ^",
        "locations": [
          {
            "line": 1,
            "column": 11
          }
        ]
      }
    ],
    "status": 200
  }
}

EDIT:

Didn't pay attention to the reason. I just had to remove the createdAt field from Link and now it works!

so Prisma is not safe and I should implement my own API with mongoose

is there any plan for it ...?

Was this page helpful?
0 / 5 - 0 ratings