rwadurian/backend/services/planting-service/src/infrastructure/persistence/prisma/prisma.service.ts

70 lines
1.8 KiB
TypeScript

import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common';
import { PrismaClient, Prisma } from '@prisma/client';
// 定义事务客户端类型
export type TransactionClient = Omit<
PrismaClient,
'$connect' | '$disconnect' | '$on' | '$transaction' | '$use' | '$extends'
>;
@Injectable()
export class PrismaService
extends PrismaClient
implements OnModuleInit, OnModuleDestroy
{
constructor() {
super({
log:
process.env.NODE_ENV === 'development'
? ['query', 'info', 'warn', 'error']
: ['error'],
});
}
async onModuleInit() {
await this.$connect();
}
async onModuleDestroy() {
await this.$disconnect();
}
/**
* 执行数据库事务
* @param fn 事务回调函数
* @param options 事务选项
*/
async executeTransaction<T>(
fn: (tx: TransactionClient) => Promise<T>,
options?: {
maxWait?: number;
timeout?: number;
isolationLevel?: Prisma.TransactionIsolationLevel;
},
): Promise<T> {
return this.$transaction(fn, {
maxWait: options?.maxWait ?? 5000,
timeout: options?.timeout ?? 10000,
isolationLevel: options?.isolationLevel ?? Prisma.TransactionIsolationLevel.ReadCommitted,
});
}
async cleanDatabase() {
if (process.env.NODE_ENV !== 'test') {
throw new Error('cleanDatabase can only be used in test environment');
}
const tablenames = await this.$queryRaw<
Array<{ tablename: string }>
>`SELECT tablename FROM pg_tables WHERE schemaname='public'`;
for (const { tablename } of tablenames) {
if (tablename !== '_prisma_migrations') {
await this.$executeRawUnsafe(
`TRUNCATE TABLE "public"."${tablename}" CASCADE;`,
);
}
}
}
}