Skip to content
This repository was archived by the owner on Sep 2, 2022. It is now read-only.
This repository was archived by the owner on Sep 2, 2022. It is now read-only.

Transactional Guarantees for Nested Mutations #597

@sorenbs

Description

@sorenbs

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions