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 {
|
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,
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user