fix: Prevent getOrCreateChat race conditions with a transaction and extract common chat include fields.

This commit is contained in:
pradeepkumar
2026-03-05 06:38:33 +05:30
parent 399b8aa937
commit 0487d1caca

View File

@@ -10,50 +10,40 @@ import { SupportChatStatus } from '@prisma/client';
export class SupportChatService {
constructor(private readonly prisma: PrismaService) {}
/**
* Get or create an OPEN support chat for a user
*/
async getOrCreateChat(userId: string) {
// Find existing OPEN chat
let chat = await this.prisma.supportChat.findFirst({
where: { userId, status: SupportChatStatus.OPEN },
include: {
user: {
select: {
id: true,
email: true,
userProfile: {
select: { firstName: true, lastName: true, avatar: true },
},
agentProfile: {
select: { firstName: true, lastName: true, avatar: true },
},
},
private readonly chatInclude = {
user: {
select: {
id: true,
email: true,
userProfile: {
select: { firstName: true, lastName: true, avatar: true },
},
agentProfile: {
select: { firstName: true, lastName: true, avatar: true },
},
},
});
},
};
if (!chat) {
chat = await this.prisma.supportChat.create({
data: { userId },
include: {
user: {
select: {
id: true,
email: true,
userProfile: {
select: { firstName: true, lastName: true, avatar: true },
},
agentProfile: {
select: { firstName: true, lastName: true, avatar: true },
},
},
},
},
/**
* Get or create an OPEN support chat for a user.
* Uses a transaction to prevent race conditions creating duplicates.
*/
async getOrCreateChat(userId: string) {
return this.prisma.$transaction(async (tx) => {
// Find existing OPEN chat
const existing = await tx.supportChat.findFirst({
where: { userId, status: SupportChatStatus.OPEN },
include: this.chatInclude,
});
}
return chat;
if (existing) return existing;
return tx.supportChat.create({
data: { userId },
include: this.chatInclude,
});
});
}
/**