Skip to content

Commit

Permalink
fix(prisma-client-transactions-guide): Make $transaction([]) explicit (
Browse files Browse the repository at this point in the history
…#5122)

Right now the document refers to the batch transaction API only as "`$transaction` API". But interactive transactions of course also use `$transaction()`, just with a different parameter (functions instead of array).

Calling it the "`$transaction([])` API" at least lets us differentiate.

This needs to be cleaned up on a higher level though as well.
  • Loading branch information
janpio authored Nov 15, 2023
1 parent 98b8b5f commit 5125610
Showing 1 changed file with 21 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Prisma Client supports six different ways of handling transactions for three dif
| Scenario | Available techniques |
| :------------------ | :-------------------------------------------------------------------------------------------------------------- |
| Dependent writes | <ul><li>Nested writes</li></ul> |
| Independent writes | <ul><li>`$transaction` API</li><li>Batch operations</li></ul> |
| Independent writes | <ul><li>`$transaction([])` API</li><li>Batch operations</li></ul> |
| Read, modify, write | <ul><li>Idempotent operations</li><li>Optimistic concurrency control</li><li>Interactive transactions</li></ul> |

The technique you choose depends on your particular use case.
Expand Down Expand Up @@ -79,7 +79,7 @@ Consider using nested writes if:

<Tip>

If you [pre-compute your IDs, you can choose between a nested write or using the `$transaction` API](#scenario-pre-computed-ids-and-the-transaction-api).
If you [pre-compute your IDs, you can choose between a nested write or using the `$transaction([])` API](#scenario-pre-computed-ids-and-the-transaction-api).

</Tip>

Expand Down Expand Up @@ -156,9 +156,9 @@ Furthermore, if an error occurs at any point, Prisma Client rolls back the entir

#### Nested writes FAQs

##### Why can't I use the `$transaction` API to solve the same problem?
##### Why can't I use the `$transaction([])` API to solve the same problem?

The `$transaction` API does not allow you to pass IDs between distinct operations. In the following example, `createUserOperation.id` is not available yet:
The `$transaction([])` API does not allow you to pass IDs between distinct operations. In the following example, `createUserOperation.id` is not available yet:

```ts highlight=12;delete
const createUserOperation = prisma.user.create({
Expand All @@ -181,9 +181,9 @@ const createTeamOperation = prisma.team.create({
await prisma.$transaction([createUserOperation, createTeamOperation])
```

##### Nested writes support nested updates, but updates are not dependent writes - should I use the `$transaction` API?
##### Nested writes support nested updates, but updates are not dependent writes - should I use the `$transaction([])` API?

It is correct to say that because you know the ID of the team, you can update the team and its team members independently within a `$transaction`. The following example performs both operations in a `$transaction`:
It is correct to say that because you know the ID of the team, you can update the team and its team members independently within a `$transaction([])`. The following example performs both operations in a `$transaction([])`:

```ts
const updateTeam = prisma.team.update({
Expand Down Expand Up @@ -247,7 +247,7 @@ const updateTeam = await prisma.team.update({
Yes, but this is a combination of scenarios and techniques:

- Creating a team and assigning users is a dependent write - use nested writes
- Creating all teams and users at the same time is an independent write because team/user combination #1 and team/user combination #2 are unrelated writes - use the `$transaction` API
- Creating all teams and users at the same time is an independent write because team/user combination #1 and team/user combination #2 are unrelated writes - use the `$transaction([])` API

```ts
// Nested write
Expand All @@ -274,7 +274,7 @@ const createTwo = prisma.team.create({
},
})

// $transaction API
// $transaction([]) API
await prisma.$transaction([createTwo, createOne])
```

Expand Down Expand Up @@ -359,13 +359,13 @@ await prisma.team.deleteMany({
})
```

#### Can I use bulk operations with the `$transaction` API?
#### Can I use bulk operations with the `$transaction([])` API?

Yes - for example, you can include multiple `deleteMany` operations inside a `$transaction`.
Yes - for example, you can include multiple `deleteMany` operations inside a `$transaction([])`.

### <inlinecode>$transaction</inlinecode> API
### <inlinecode>$transaction([])</inlinecode> API

The `$transaction` API is generic solution to independent writes that allows you to run multiple operations as a single, atomic operation - if any operation fails, Prisma rolls back the entire transaction.
The `$transaction([])` API is generic solution to independent writes that allows you to run multiple operations as a single, atomic operation - if any operation fails, Prisma rolls back the entire transaction.

Its also worth noting that operations are executed according to the order they are placed in the transaction.

Expand All @@ -375,11 +375,11 @@ await prisma.$transaction([iRunFirst, iRunSecond, iRunThird])

> **Note**: Using a query in a transaction does not influence the order of operations in the query itself.
As Prisma Client evolves, use cases for the `$transaction` API will increasingly be replaced by more specialized bulk operations (such as `createMany`) and nested writes.
As Prisma Client evolves, use cases for the `$transaction([])` API will increasingly be replaced by more specialized bulk operations (such as `createMany`) and nested writes.

#### When to use the `$transaction` API
#### When to use the `$transaction([])` API

Consider the `$transaction` API if:
Consider the `$transaction([])` API if:

- ✔ You want to update a batch that includes different types of records, such as emails and users. The records do not need to be related in any way.
- ✔ You want to batch raw SQL queries (`$executeRaw`) - for example, for features that Prisma Client does not yet support.
Expand Down Expand Up @@ -411,7 +411,7 @@ model PrivateMessage {
}
```

If a user invokes the right to be forgotten, we must delete three records: the user record, private messages, and posts. It is critical that _all_ delete operations succeed together or not at all, which makes this a use case for a transaction. However, using a single bulk operation like `deleteMany` is not possible in this scenario because we need to delete across three models. Instead, we can use the `$transaction` API to run three operations together - two `deleteMany` and one `delete`:
If a user invokes the right to be forgotten, we must delete three records: the user record, private messages, and posts. It is critical that _all_ delete operations succeed together or not at all, which makes this a use case for a transaction. However, using a single bulk operation like `deleteMany` is not possible in this scenario because we need to delete across three models. Instead, we can use the `$transaction([])` API to run three operations together - two `deleteMany` and one `delete`:

```ts
const id = 9 // User to be deleted
Expand All @@ -437,9 +437,9 @@ const deleteUser = prisma.user.delete({
await prisma.$transaction([deletePosts, deleteMessages, deleteUser]) // Operations succeed or fail together
```

#### Scenario: Pre-computed IDs and the `$transaction` API
#### Scenario: Pre-computed IDs and the `$transaction([])` API

Dependent writes are not supported by the `$transaction` API - if operation A relies on the ID generated by operation B, use [nested writes](#nested-writes). However, if you _pre-computed_ IDs (for example, by generating GUIDs), your writes become independent. Consider the sign-up flow from the nested writes example:
Dependent writes are not supported by the `$transaction([])` API - if operation A relies on the ID generated by operation B, use [nested writes](#nested-writes). However, if you _pre-computed_ IDs (for example, by generating GUIDs), your writes become independent. Consider the sign-up flow from the nested writes example:

```ts
await prisma.team.create({
Expand Down Expand Up @@ -472,7 +472,7 @@ model User {
}
```

Refactor the sign-up flow example to use the `$transaction` API instead of nested writes:
Refactor the sign-up flow example to use the `$transaction([])` API instead of nested writes:

```ts
import { v4 } from 'uuid'
Expand Down Expand Up @@ -524,7 +524,7 @@ await prisma.team.create({
})
```

There's no compelling reason to switch to manually generated IDs and the `$transaction` API if you are already using auto-generated IDs and nested writes.
There's no compelling reason to switch to manually generated IDs and the `$transaction([])` API if you are already using auto-generated IDs and nested writes.

## Read, modify, write

Expand Down Expand Up @@ -818,7 +818,7 @@ It is now impossible for two people to book the same seat:
If you have an existing application, it can be a significant undertaking to refactor your application to use optimistic concurrency control. Interactive Transactions offers a useful escape hatch for cases like this.
To create an interactive transaction, pass an async function into [$transaction](#transaction-api).
To create an interactive transaction, pass an async function into [$transaction](#transaction-api). <!-- TODO This is terrible wording, as that other section is meant to describe the batch $transaction([]) API, and not $transaction in general -->
The first argument passed into this async function is an instance of Prisma Client. Below, we will call this instance `tx`. Any Prisma call invoked on this `tx` instance is encapsulated into the transaction.
Expand Down

1 comment on commit 5125610

@vercel
Copy link

@vercel vercel bot commented on 5125610 Nov 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

docs – ./

docs-git-main-prisma.vercel.app
prisma2-docs.vercel.app
docs-prisma.vercel.app

Please sign in to comment.