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