NestJs 中的 Prisma 交易中间件

问题描述 投票:0回答:0

我尝试将这种责任具体化到某个地方,而不是必须声明一个新的 prisma.$transaction 来获取能够自动回滚我需要的每个 api 请求的 prisma 实例。

目前我最好的尝试是一个事务中间件,它可以工作,我可以准确地声明我需要的位置,并通过请求或参数装饰器接收控制器上的 prisma 实例(因为我使用的是 Nest)。

import { Injectable, NestMiddleware } from '@nestjs/common'
import { Request, Response, NextFunction } from 'express'
import { PrismaService } from '../prisma.service'

@Injectable()
export class TransacitonMiddleware implements NestMiddleware {
  constructor(private readonly prisma: PrismaService) {}

  async use(req: Request, res: Response, next: NextFunction) {
    await this.prisma.$transaction(async (instance) => {
      req['prisma'] = instance

      next() // => GET /user
    })
  }
}
import {
  Controller,
  Get,
  Req
} from '@nestjs/common'

@Controller('users')
export class UsersController {
  @Get()
  async findAll(@Req() request: any) {
    const { prisma } = request

    const users = await prisma.user.findMany()

    return users
  }
}

但是,prisma 请求需要在 prisma.$transaction 仍处于打开状态时发出,并且由于 Express Next 功能的同步行为,事务将始终在请求结束之前关闭。

Error: 
Invalid `prisma.user.findMany()` invocation in .../users.controller.ts:35:37

  32 async findAll(@Req() request: any) {
  33   const { prisma } = request
  34 
→ 35   const users = await prisma.user.findMany(
Transaction API error: Transaction already closed: A query cannot be executed on a committed transaction. at An.handleRequestError...

首先,我尝试以某种方式使 nextFunction 异步,在其上放置一个等待,将其放入异步函数中,但都不起作用。

然后我尝试以某种方式延长事务的生命周期,我在中间件内的下一个函数之后声明了另一个 prisma 请求并且它起作用了。

  async use(req: Request, res: Response, next: NextFunction) {
    await this.prisma.$transaction(async (instance) => {
      req['prisma'] = instance

      next() // => GET /user

      await instance.user.count()
    })
  }

但是,由于显而易见的原因,我认为这不是一个好的做法,而且我目前已经用尽了我的选择和时间来交付这个。因此,如果有人对如何实现此功能有任何想法,请做出贡献。

感谢大家的时间和考虑!

asynchronous transactions middleware prisma nest
© www.soinside.com 2019 - 2024. All rights reserved.