I was trying to implement a clean prisma transaction architecture with a DDD architecture.
My problem is that i want to be able to perform transactions cross different modules without need to pass the prisma transaction client to each repository
ie:
// repository layer
@injectable()
export class UserRepository{
constructor(@inject(PrismaClient) private prisma: PrismaClient)
save(user: IUser): Promise<User>{
return this.prisma.user.create({data: user});
}
}
@injectable()
export class OrderRepository{
constructor(@inject(PrismaClient) private prisma: PrismaClient)
save(order: IOrder): Promise<Order>{
return this.prisma.order.create({data: order});
}
}
// service layer
export class UserService{
constructor(@inject(UserRepository) private userRepo: UserRepository)
create(request: CreateUserRequest){
return this.userRepo.save(request);
}
}
export class OrderService{
constructor(@inject(OrderRepository) private orderRepo: OrderRepository)
create(request: CreateOrderRequest){
return this.orderRepo.save(request);
}
}
// controller layer
export UserController{
constructor(
@inject(UserService) private userService: UserService,
@inject(OrderService) private orderService: OrderService
){}
placeOrder(
userRequest: CreateUserRequest,
orderRequest: CreateOrderRequest
){
// perform transaction, if any fails go with rollback
// !THIS ACTUALLY DOESN'T WORK
prisma.$transaction([
await this.userService.create(userRequest),
await this.orderService.create(orderRequest)
])
}
}
I want to figure out a clean way to achieve this, has anyone faced a similar problem before?
Thank you all!
Your UserRepository.save and OrderRepository.save, should return PrismaPromises instead of a Promise(https://www.prisma.io/docs/concepts/components/prisma-client/transactions#the-transaction-api)
Also, when you await the promise returned by UserRepository.save you are passing a User not a PrismaPromise<User> which the $transaction expects.
To fix it, fix the typing from the repositories methods as commented above and then you should be able to do a transaction by inverting the order on which you await:
await prisma.$transaction([
this.userService.create(userRequest),
this.orderService.create(orderRequest)
])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With