strapi/packages/core/database/src/transaction-context.ts

94 lines
2.0 KiB
TypeScript
Raw Normal View History

2023-07-19 16:35:50 +02:00
import { AsyncLocalStorage } from 'node:async_hooks';
import { Knex } from 'knex';
2022-09-12 15:24:53 +02:00
2023-09-21 16:49:53 +02:00
export type Callback = (...args: any[]) => Promise<any> | any;
2022-09-12 15:24:53 +02:00
2023-09-21 16:49:53 +02:00
export interface TransactionObject {
commit: () => Promise<void>;
rollback: () => Promise<void>;
get: () => Knex.Transaction;
}
2023-07-19 16:35:50 +02:00
export interface Store {
trx: Knex.Transaction | null;
commitCallbacks: Callback[];
rollbackCallbacks: Callback[];
}
const storage = new AsyncLocalStorage<Store>();
2022-09-12 15:24:53 +02:00
const transactionCtx = {
async run<TCallback extends Callback>(trx: Knex.Transaction, cb: TCallback) {
const store = storage.getStore();
2023-09-21 16:49:53 +02:00
return storage.run<ReturnType<TCallback>, void[]>(
{
trx,
// Fill with existing callbacks if nesting transactions
commitCallbacks: store?.commitCallbacks || [],
rollbackCallbacks: store?.rollbackCallbacks || [],
},
2023-09-21 16:49:53 +02:00
cb
);
2022-09-12 15:24:53 +02:00
},
get() {
const store = storage.getStore();
return store?.trx;
},
2023-07-19 16:35:50 +02:00
async commit(trx: Knex.Transaction) {
const store = storage.getStore();
// Clear transaction from store
if (store?.trx) {
store.trx = null;
}
// Commit transaction
await trx.commit();
2023-07-19 16:35:50 +02:00
if (!store?.commitCallbacks.length) {
return;
}
// Run callbacks
store.commitCallbacks.forEach((cb) => cb());
store.commitCallbacks = [];
},
2023-07-19 16:35:50 +02:00
async rollback(trx: Knex.Transaction) {
const store = storage.getStore();
// Clear transaction from store
if (store?.trx) {
store.trx = null;
}
// Rollback transaction
await trx.rollback();
2023-07-19 16:35:50 +02:00
if (!store?.rollbackCallbacks.length) {
return;
}
// Run callbacks
store.rollbackCallbacks.forEach((cb) => cb());
store.rollbackCallbacks = [];
},
2023-07-19 16:35:50 +02:00
onCommit(cb: Callback) {
const store = storage.getStore();
2023-05-22 15:19:53 +02:00
if (store?.commitCallbacks) {
store.commitCallbacks.push(cb);
}
},
2023-07-19 16:35:50 +02:00
onRollback(cb: Callback) {
const store = storage.getStore();
2023-05-22 15:19:53 +02:00
if (store?.rollbackCallbacks) {
store.rollbackCallbacks.push(cb);
}
2022-09-12 15:24:53 +02:00
},
};
2023-07-19 16:35:50 +02:00
export { transactionCtx };