fix: Prevent getOrCreateChat race conditions with a transaction and extract common chat include fields.
This commit is contained in:
@@ -10,50 +10,40 @@ import { SupportChatStatus } from '@prisma/client';
|
||||
export class SupportChatService {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
||||
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 },
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Get or create an OPEN support chat for a user
|
||||
* 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
|
||||
let chat = await this.prisma.supportChat.findFirst({
|
||||
const existing = await tx.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 },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
include: this.chatInclude,
|
||||
});
|
||||
|
||||
if (!chat) {
|
||||
chat = await this.prisma.supportChat.create({
|
||||
if (existing) return existing;
|
||||
|
||||
return tx.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 },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
include: this.chatInclude,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return chat;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user