fix(db-mongodb): add req to migration templates for transactions (#8407)

- Add `req` to MigrateUpArgs and MigrateDownArgs for mongodb
- Improve docs for transactions and migrations
This commit is contained in:
Dan Ribbens
2024-09-25 12:58:48 -04:00
committed by GitHub
parent 87360f23ac
commit b10f61cb25
4 changed files with 55 additions and 8 deletions

View File

@@ -33,10 +33,6 @@ A migration file has two exports - an `up` function, which is called when a migr
that will be called if for some reason the migration fails to complete successfully. The `up` function should contain
all changes that you attempt to make within the migration, and the `down` should ideally revert any changes you make.
For an added level of safety, migrations should leverage Payload [transactions](/docs/database/transactions). Migration
functions should make use of the `req` by adding it to the arguments of your Payload Local API calls such
as `payload.create` and Database Adapter methods like `payload.db.create`.
Here is an example migration file:
```ts
@@ -53,6 +49,14 @@ export async function down({ payload, req }: MigrateDownArgs): Promise<void> {
}
```
## Using Transactions
When migrations are run, each migration is performed in a new [transactions](/docs/database/transactions) for you. All
you need to do is pass the `req` object to any [local API](/docs/local-api/overview) or direct database calls, such as
`payload.db.updateMany()`, to make database changes inside the transaction. Assuming no errors were thrown, the transaction is committed
after your `up` or `down` function runs. If the migration errors at any point or fails to commit, it is caught and the
transaction gets aborted. This way no change is made to the database if the migration fails.
## Migrations Directory
Each DB adapter has an optional property `migrationDir` where you can override where you want your migrations to be

View File

@@ -69,6 +69,48 @@ The following functions can be used for managing transactions:
`payload.db.commitTransaction` - Takes the identifier for the transaction, finalizes any changes.
`payload.db.rollbackTransaction` - Takes the identifier for the transaction, discards any changes.
Payload uses the `req` object to pass the transaction ID through to the database adapter. If you are not using the `req` object, you can make a new object to pass the transaction ID directly to database adapter methods and local API calls.
Example:
```ts
import payload from 'payload'
import config from './payload.config'
const standalonePayloadScript = async () => {
// initialize Payload
await payload.init({ config })
const transactionID = await payload.db.beginTransaction()
try {
// Make an update using the local API
await payload.update({
collection: 'posts',
data: {
some: 'data',
},
where: {
slug: { equals: 'my-slug' }
},
req: { transactionID },
})
/*
You can make additional db changes or run other functions
that need to be committed on an all or nothing basis
*/
// Commit the transaction
await payload.db.commitTransaction(transactionID)
} catch (error) {
// Rollback the transaction
await payload.db.rollbackTransaction(transactionID)
}
}
standalonePayloadScript()
```
## Disabling Transactions
If you wish to disable transactions entirely, you can do so by passing `false` as the `transactionOptions` in your database adapter configuration. All the official Payload database adapters support this option.

View File

@@ -11,11 +11,11 @@ const migrationTemplate = ({ downSQL, imports, upSQL }: MigrationTemplateArgs):
} from '@payloadcms/db-mongodb'
${imports}
export async function up({ payload }: MigrateUpArgs): Promise<void> {
export async function up({ payload, req }: MigrateUpArgs): Promise<void> {
${upSQL ?? ` // Migration code`}
}
export async function down({ payload }: MigrateDownArgs): Promise<void> {
export async function down({ payload, req }: MigrateDownArgs): Promise<void> {
${downSQL ?? ` // Migration code`}
}
`

View File

@@ -20,6 +20,7 @@ import type {
JSONField,
NumberField,
Payload,
PayloadRequest,
PointField,
RadioField,
RelationshipField,
@@ -109,5 +110,5 @@ export type FieldToSchemaMap<TSchema> = {
upload: FieldGeneratorFunction<TSchema, UploadField>
}
export type MigrateUpArgs = { payload: Payload }
export type MigrateDownArgs = { payload: Payload }
export type MigrateUpArgs = { payload: Payload; req: PayloadRequest }
export type MigrateDownArgs = { payload: Payload; req: PayloadRequest }