fix: 盲盒抽取使用事务 + 乐观锁防止并发抽到同一想法
- 将 findMany + update 包裹在 prisma.$transaction 中
- 使用 updateMany({ where: { id, status: "in_pool" } }) 保证原子性
- count=0 时返回 409 提示用户重试
This commit is contained in:
@@ -11,7 +11,10 @@ export const POST = apiHandler(async (req) => {
|
|||||||
|
|
||||||
await requireMembership(roomId, userId);
|
await requireMembership(roomId, userId);
|
||||||
|
|
||||||
const pool = await prisma.blindBoxIdea.findMany({
|
const userSelect = { id: true, username: true, avatar: true } as const;
|
||||||
|
|
||||||
|
const idea = await prisma.$transaction(async (tx) => {
|
||||||
|
const pool = await tx.blindBoxIdea.findMany({
|
||||||
where: { roomId, status: "in_pool" },
|
where: { roomId, status: "in_pool" },
|
||||||
select: { id: true },
|
select: { id: true },
|
||||||
});
|
});
|
||||||
@@ -22,14 +25,25 @@ export const POST = apiHandler(async (req) => {
|
|||||||
|
|
||||||
const picked = pool[Math.floor(Math.random() * pool.length)];
|
const picked = pool[Math.floor(Math.random() * pool.length)];
|
||||||
|
|
||||||
const idea = await prisma.blindBoxIdea.update({
|
const { count } = await tx.blindBoxIdea.updateMany({
|
||||||
where: { id: picked.id },
|
where: { id: picked.id, status: "in_pool" },
|
||||||
data: { status: "drawn", drawnById: userId },
|
data: { status: "drawn", drawnById: userId },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (count === 0) {
|
||||||
|
throw new ApiError("手慢了,再试一次", 409);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tx.blindBoxIdea.findUnique({
|
||||||
|
where: { id: picked.id },
|
||||||
include: {
|
include: {
|
||||||
user: { select: { id: true, username: true, avatar: true } },
|
user: { select: userSelect },
|
||||||
drawnBy: { select: { id: true, username: true, avatar: true } },
|
drawnBy: { select: userSelect },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!idea) throw new ApiError("抽取失败", 500);
|
||||||
|
|
||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
id: idea.id,
|
id: idea.id,
|
||||||
|
|||||||
Reference in New Issue
Block a user