Azure / Azure/data-api-builder

[Enhancement]: GraphQL with Parallel Mutations

Open
#1,797 0 comments 0 reactions 3 assignees Claimed by @severussundar View on GitHub
2.x enhancement triage
Dominant language
C#
Stars
1.5k
Forks
370
Avg merge
3d 17h
Merged PRs (30d)
8

Description

### What happened?

Data API builder supports this:

```GQL
mutation {
addBook(input: { title: "C# in depth" }) {
book {
id
title
}
}
publishBook(input: { id: 1 }) {
book {
publishDate
}
}
}
```

However, this operation is currently serial. When we look at [Hot Chocolate](https://chillicream.com/docs/hotchocolate/v13/defining-a-schema/mutations), we see their mutations are executed similarly, but in the Data API builder, there's no clear technical reason for this. In fact, there are many reasons why they should run in parallel.

1. Parallel operations complete sooner.
2. Databases handle parallel operations well.
3. With multiple data sources, operations can spread across them.
4. I believe developers assume these operations run in parallel.

This issue becomes evident when considering many or lengthy operations. If I pass in 10 mutations, I don't want the delay of 10 times the operation time. Instead, I aim to minimize it. If I have only 2, it's reasonable to expect to wait only for the duration of the longest operation when in parallel.

## Make it optional with `graphql.execution` = `serial | parallel`
The default value should be `parallel`. Setting it to serial means the mutations line up & wait for the previous one to finish. Otherwise, they all try to execute simultaneously.

## Answers in `atomicity`
In another issue #1780, atomicity is discussed. When running parallel, each operation accesses the same token to halt execution should any parallel operation fail. In serial mode, that same token can prevent further execution. If atomicity is off, there's no reason to halt execution, even with a failure.

1. Should serial operations stop if one fails? `atomicity` provides the answer.
2. Should parallel operations halt if one fails? Again, `atomicity` is the answer.

## Make it scalable with `graphql.degreeofparallelism` = `5`
The default value should be undefined or maybe `-1`. In .NET, for the Task Parallel Library (TPL), the default Degree of Parallelism (DOP) isn't set to a specific number. It's often based on the number of available processors or cores.

Aside: this isn't relevant to bulk operations. #1783

Allowing customers to set the DOP lets them scale down complex mutations & prevent a single query from monopolizing the system. For instance, setting it to 2 means a query with 10 mutations runs 2 at a time. It's beneficial & great that it's optional.

By the way, customers setting DOP to 1 will have serial operations because there's nothing else to do. However, it makes more sense to have two config settings instead of one. `execution=parallel` isn't just easier to understand, but most users will ignore DOP - as they should.

### Version

Future

### What database are you using?

Azure SQL

### What hosting model are you using?

Local (including CLI)

### Which API approach are you accessing DAB through?

GraphQL

### Relevant log output

_No response_

### Code of Conduct

- [X] I agree to follow this project's Code of Conduct

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.