Prisma1: Transactional Guarantees for Nested Mutations

Created on 26 Sep 2017  路  2Comments  路  Source: prisma/prisma1

Nested mutations provide a transactional boundary. This document outline how nested mutations, permission queries and operationBefore/operationAfter functions fit together.

Nested Mutations

A nested mutation contains multiple CRUD operations in a single GraphQL mutation:

mutation {
  createUser(
    name: "S酶ren Bramer",
    articles: [
      {title: "My first article"}
      {title: "My second article"}
    ])
}

This nested mutation performs 5 crud operations:

  • create User node
  • create Article node
  • create Article node
  • connect Article and User
  • connect Article and User

These operations should either all succeed or not succeed at all.
Additionally, any other query running at the same time should either see the result of all operations or none.

Permission Queries

Permission queries are a convenient way to write permission rules that depend on data relations.

The following permission query gives access when an Article is related to the User called 'S酶ren Bramer':

{
  someArticleExists(filter: {id: $node_id, author: {name: "S酶ren Bramer"}})
}

If this permission governs UPDATE access, the permission query can be executed before the database transaction.

If the permission governs CREATE access the situation is a bit more tricky. In the nested mutation above we can not perform the permission query before the database transaction, as the user S酶ren Bramer does not exist until after the transaction has been performed.

The solution is to open a transaction, perform all the writes, keep the transaction open while performing the permission query, and then either commit or roll back the transaction depending on the result of the permission query.

Permission queries will default to run before the transaction, but the developer can configure a specific permission query to always run at the end of the transaction.

operationBefore/operationAfter functions

operationBefore and operationAfter functions are specified for a specific model. If multiple operations exist for the models involved in a nested mutation, all operations are performed together before and after the database transaction respectively.

Overview

  1. All operationBefore
  2. All permission queries that should run before
  3. Transaction start + write
  4. All permission queries that should run after
  5. transaction commit or rollback
  6. if transaction commit: All operationAfter

Most helpful comment

What about subscriptions (both client and server)? I think they should also be delayed until after the transaction commits.

Also, it's important to note somewhere in the docs that before operations should be 'pure', e.g. without side effects, for this to work properly.

All 2 comments

What about subscriptions (both client and server)? I think they should also be delayed until after the transaction commits.

Also, it's important to note somewhere in the docs that before operations should be 'pure', e.g. without side effects, for this to work properly.

Superceded by #1280.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

akoenig picture akoenig  路  3Comments

schickling picture schickling  路  3Comments

sedubois picture sedubois  路  3Comments

schickling picture schickling  路  3Comments

sorenbs picture sorenbs  路  3Comments