mirror of
https://github.com/strapi/strapi.git
synced 2025-12-25 14:14:10 +00:00
Improve transaction API:
- make it possible to have nested transactions - wrap the knex transaction api and apply changes everywhere it was used
This commit is contained in:
parent
e90885ab91
commit
12dd68f4a7
@ -218,7 +218,7 @@ const createEntityManager = (db) => {
|
||||
|
||||
const trx = await strapi.db.transaction();
|
||||
try {
|
||||
await this.attachRelations(uid, id, data, { transaction: trx });
|
||||
await this.attachRelations(uid, id, data, { transaction: trx.get() });
|
||||
|
||||
await trx.commit();
|
||||
} catch (e) {
|
||||
@ -302,7 +302,7 @@ const createEntityManager = (db) => {
|
||||
|
||||
const trx = await strapi.db.transaction();
|
||||
try {
|
||||
await this.updateRelations(uid, id, data, { transaction: trx });
|
||||
await this.updateRelations(uid, id, data, { transaction: trx.get() });
|
||||
await trx.commit();
|
||||
} catch (e) {
|
||||
await trx.rollback();
|
||||
@ -373,7 +373,7 @@ const createEntityManager = (db) => {
|
||||
|
||||
const trx = await strapi.db.transaction();
|
||||
try {
|
||||
await this.deleteRelations(uid, id, { transaction: trx });
|
||||
await this.deleteRelations(uid, id, { transaction: trx.get() });
|
||||
|
||||
await trx.commit();
|
||||
} catch (e) {
|
||||
|
||||
11
packages/core/database/lib/index.d.ts
vendored
11
packages/core/database/lib/index.d.ts
vendored
@ -1,3 +1,4 @@
|
||||
import { Knex } from 'knex';
|
||||
import { LifecycleProvider } from './lifecycles';
|
||||
import { MigrationProvider } from './migrations';
|
||||
import { SchemaProvider } from './schema';
|
||||
@ -31,8 +32,7 @@ type AttributeOperators<T, K extends keyof T> = {
|
||||
|
||||
export type WhereParams<T> = {
|
||||
[K in keyof T]?: T[K] | T[K][] | AttributeOperators<T, K>;
|
||||
} &
|
||||
LogicalOperators<T>;
|
||||
} & LogicalOperators<T>;
|
||||
|
||||
type Sortables<T> = {
|
||||
// check sortable
|
||||
@ -160,7 +160,12 @@ export interface Database {
|
||||
entityManager: EntityManager;
|
||||
|
||||
query<T extends keyof AllTypes>(uid: T): QueryFromContentType<T>;
|
||||
transaction(cb: (em: EntityManager) => Promise<any>): Promise<void>;
|
||||
transaction(
|
||||
cb?: (trx: Knex.Transaction) => Promise<any>,
|
||||
options?: any
|
||||
):
|
||||
| Promise<void>
|
||||
| { get: () => Knex.Transaction; rollback: () => Promise<void>; commit: () => Promise<void> };
|
||||
}
|
||||
export class Database implements Database {
|
||||
static transformContentTypes(contentTypes: any[]): ModelConfig[];
|
||||
|
||||
@ -48,19 +48,40 @@ class Database {
|
||||
return this.entityManager.getRepository(uid);
|
||||
}
|
||||
|
||||
async transaction(cb) {
|
||||
async transaction(cb, { onError, onSuccess } = {}) {
|
||||
const notNestedTransaction = !transactionCtx.get();
|
||||
const trx = notNestedTransaction ? await this.connection.transaction() : transactionCtx.get();
|
||||
if (!cb) {
|
||||
return this.connection.transaction();
|
||||
return {
|
||||
async commit() {
|
||||
if (notNestedTransaction) {
|
||||
await trx.commit();
|
||||
}
|
||||
},
|
||||
async rollback() {
|
||||
if (notNestedTransaction) {
|
||||
await trx.rollback();
|
||||
}
|
||||
},
|
||||
get() {
|
||||
return trx;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const trx = await this.connection.transaction();
|
||||
return transactionCtx.run(trx, async () => {
|
||||
try {
|
||||
const res = await cb();
|
||||
await trx.commit();
|
||||
const res = await cb(trx);
|
||||
if (notNestedTransaction) {
|
||||
await trx.commit();
|
||||
}
|
||||
await onSuccess?.();
|
||||
return res;
|
||||
} catch (error) {
|
||||
await trx.rollback();
|
||||
if (notNestedTransaction) {
|
||||
await trx.rollback();
|
||||
}
|
||||
await onError?.();
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
@ -84,7 +84,7 @@ module.exports = {
|
||||
.queryBuilder(FOLDER_MODEL_UID)
|
||||
.select(['id', 'pathId', 'path'])
|
||||
.where({ id: { $in: folderIds } })
|
||||
.transacting(trx)
|
||||
.transacting(trx.get())
|
||||
.forUpdate()
|
||||
.execute();
|
||||
|
||||
@ -93,7 +93,7 @@ module.exports = {
|
||||
.queryBuilder(FILE_MODEL_UID)
|
||||
.select(['id'])
|
||||
.where({ id: { $in: fileIds } })
|
||||
.transacting(trx)
|
||||
.transacting(trx.get())
|
||||
.forUpdate()
|
||||
.execute();
|
||||
|
||||
@ -104,7 +104,7 @@ module.exports = {
|
||||
.queryBuilder(FOLDER_MODEL_UID)
|
||||
.select('path')
|
||||
.where({ id: destinationFolderId })
|
||||
.transacting(trx)
|
||||
.transacting(trx.get())
|
||||
.first()
|
||||
.execute();
|
||||
destinationFolderPath = destinationFolder.path;
|
||||
@ -121,7 +121,7 @@ module.exports = {
|
||||
const { joinTable } = strapi.db.metadata.get(FOLDER_MODEL_UID).attributes.parent;
|
||||
await strapi.db
|
||||
.queryBuilder(joinTable.name)
|
||||
.transacting(trx)
|
||||
.transacting(trx.get())
|
||||
.delete()
|
||||
.where({ [joinTable.joinColumn.name]: { $in: folderIds } })
|
||||
.execute();
|
||||
@ -129,7 +129,7 @@ module.exports = {
|
||||
if (destinationFolderId !== null) {
|
||||
await strapi.db
|
||||
.queryBuilder(joinTable.name)
|
||||
.transacting(trx)
|
||||
.transacting(trx.get())
|
||||
.insert(
|
||||
existingFolders.map((folder) => ({
|
||||
[joinTable.inverseJoinColumn.name]: destinationFolderId,
|
||||
@ -155,7 +155,7 @@ module.exports = {
|
||||
// update path for folders themselves & folders below
|
||||
totalFolderNumber = await strapi.db
|
||||
.getConnection(folderTable)
|
||||
.transacting(trx)
|
||||
.transacting(trx.get())
|
||||
.where(pathColName, existingFolder.path)
|
||||
.orWhere(pathColName, 'like', `${existingFolder.path}/%`)
|
||||
.update(
|
||||
@ -170,7 +170,7 @@ module.exports = {
|
||||
// update path of files below
|
||||
totalFileNumber = await strapi.db
|
||||
.getConnection(fileTable)
|
||||
.transacting(trx)
|
||||
.transacting(trx.get())
|
||||
.where(folderPathColName, existingFolder.path)
|
||||
.orWhere(folderPathColName, 'like', `${existingFolder.path}/%`)
|
||||
.update(
|
||||
@ -189,7 +189,7 @@ module.exports = {
|
||||
const fileJoinTable = strapi.db.metadata.get(FILE_MODEL_UID).attributes.folder.joinTable;
|
||||
await strapi.db
|
||||
.queryBuilder(fileJoinTable.name)
|
||||
.transacting(trx)
|
||||
.transacting(trx.get())
|
||||
.delete()
|
||||
.where({ [fileJoinTable.joinColumn.name]: { $in: fileIds } })
|
||||
.execute();
|
||||
@ -197,7 +197,7 @@ module.exports = {
|
||||
if (destinationFolderId !== null) {
|
||||
await strapi.db
|
||||
.queryBuilder(fileJoinTable.name)
|
||||
.transacting(trx)
|
||||
.transacting(trx.get())
|
||||
.insert(
|
||||
existingFiles.map((file) => ({
|
||||
[fileJoinTable.inverseJoinColumn.name]: destinationFolderId,
|
||||
@ -210,7 +210,7 @@ module.exports = {
|
||||
// update files main fields (path + updatedBy)
|
||||
await strapi.db
|
||||
.getConnection(fileTable)
|
||||
.transacting(trx)
|
||||
.transacting(trx.get())
|
||||
.whereIn('id', fileIds)
|
||||
.update(folderPathColName, destinationFolderPath);
|
||||
}
|
||||
|
||||
@ -103,7 +103,7 @@ const update = async (id, { name, parent }, { user }) => {
|
||||
.queryBuilder(FOLDER_MODEL_UID)
|
||||
.select(['pathId', 'path'])
|
||||
.where({ id })
|
||||
.transacting(trx)
|
||||
.transacting(trx.get())
|
||||
.forUpdate()
|
||||
.first()
|
||||
.execute();
|
||||
@ -112,7 +112,7 @@ const update = async (id, { name, parent }, { user }) => {
|
||||
const { joinTable } = strapi.db.metadata.get(FOLDER_MODEL_UID).attributes.parent;
|
||||
await strapi.db
|
||||
.queryBuilder(joinTable.name)
|
||||
.transacting(trx)
|
||||
.transacting(trx.get())
|
||||
.delete()
|
||||
.where({ [joinTable.joinColumn.name]: id })
|
||||
.execute();
|
||||
@ -120,7 +120,7 @@ const update = async (id, { name, parent }, { user }) => {
|
||||
if (parent !== null) {
|
||||
await strapi.db
|
||||
.queryBuilder(joinTable.name)
|
||||
.transacting(trx)
|
||||
.transacting(trx.get())
|
||||
.insert({ [joinTable.inverseJoinColumn.name]: parent, [joinTable.joinColumn.name]: id })
|
||||
.where({ [joinTable.joinColumn.name]: id })
|
||||
.execute();
|
||||
@ -133,7 +133,7 @@ const update = async (id, { name, parent }, { user }) => {
|
||||
.queryBuilder(FOLDER_MODEL_UID)
|
||||
.select('path')
|
||||
.where({ id: parent })
|
||||
.transacting(trx)
|
||||
.transacting(trx.get())
|
||||
.first()
|
||||
.execute();
|
||||
destinationFolderPath = destinationFolder.path;
|
||||
@ -148,7 +148,7 @@ const update = async (id, { name, parent }, { user }) => {
|
||||
// update folders below
|
||||
await strapi.db
|
||||
.getConnection(folderTable)
|
||||
.transacting(trx)
|
||||
.transacting(trx.get())
|
||||
.where(pathColumnName, existingFolder.path)
|
||||
.orWhere(pathColumnName, 'like', `${existingFolder.path}/%`)
|
||||
.update(
|
||||
@ -163,7 +163,7 @@ const update = async (id, { name, parent }, { user }) => {
|
||||
// update files below
|
||||
await strapi.db
|
||||
.getConnection(fileTable)
|
||||
.transacting(trx)
|
||||
.transacting(trx.get())
|
||||
.where(folderPathColumnName, existingFolder.path)
|
||||
.orWhere(folderPathColumnName, 'like', `${existingFolder.path}/%`)
|
||||
.update(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user