feat: 房间 24 小时自动过期,添加 TTL 清理机制

This commit is contained in:
2026-02-24 19:46:14 +08:00
parent b5fe3f6cc8
commit f6949a062f
3 changed files with 52 additions and 2 deletions
@@ -0,0 +1,20 @@
/*
Warnings:
- Added the required column `expiresAt` to the `Room` table without a default value. This is not possible if the table is not empty.
*/
-- RedefineTables
PRAGMA defer_foreign_keys=ON;
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_Room" (
"id" TEXT NOT NULL PRIMARY KEY,
"data" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"expiresAt" DATETIME NOT NULL
);
INSERT INTO "new_Room" ("createdAt", "data", "id", "expiresAt") SELECT "createdAt", "data", "id", "createdAt" FROM "Room";
DROP TABLE "Room";
ALTER TABLE "new_Room" RENAME TO "Room";
PRAGMA foreign_keys=ON;
PRAGMA defer_foreign_keys=OFF;
+1
View File
@@ -11,4 +11,5 @@ model Room {
id String @id
data String
createdAt DateTime @default(now())
expiresAt DateTime
}
+31 -2
View File
@@ -1,6 +1,8 @@
import { prisma } from "./prisma";
import { Restaurant } from "@/types";
const ROOM_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours
export interface RoomData {
users: string[];
restaurants: Restaurant[];
@@ -23,7 +25,29 @@ function normalize(raw: Partial<RoomData>): RoomData {
};
}
let lastCleanup = 0;
const CLEANUP_INTERVAL_MS = 60 * 60 * 1000; // at most once per hour
async function cleanupExpiredRooms() {
const now = Date.now();
if (now - lastCleanup < CLEANUP_INTERVAL_MS) return;
lastCleanup = now;
try {
const { count } = await prisma.room.deleteMany({
where: { expiresAt: { lt: new Date() } },
});
if (count > 0) {
console.log(`Cleaned up ${count} expired room(s)`);
}
} catch (e) {
console.error("Room cleanup failed:", e);
}
}
export async function createRoom(restaurants: Restaurant[]): Promise<string> {
await cleanupExpiredRooms();
const data: RoomData = {
users: [],
restaurants,
@@ -32,6 +56,7 @@ export async function createRoom(restaurants: Restaurant[]): Promise<string> {
match: null,
};
const expiresAt = new Date(Date.now() + ROOM_TTL_MS);
let roomId: string;
let attempts = 0;
@@ -40,7 +65,7 @@ export async function createRoom(restaurants: Restaurant[]): Promise<string> {
const existing = await prisma.room.findUnique({ where: { id: roomId } });
if (!existing) {
await prisma.room.create({
data: { id: roomId, data: JSON.stringify(data) },
data: { id: roomId, data: JSON.stringify(data), expiresAt },
});
return roomId;
}
@@ -49,7 +74,7 @@ export async function createRoom(restaurants: Restaurant[]): Promise<string> {
roomId = generateRoomId() + String(Date.now()).slice(-2);
await prisma.room.create({
data: { id: roomId, data: JSON.stringify(data) },
data: { id: roomId, data: JSON.stringify(data), expiresAt },
});
return roomId;
}
@@ -59,6 +84,10 @@ export async function getRoomData(
): Promise<RoomData | null> {
const room = await prisma.room.findUnique({ where: { id: roomId } });
if (!room) return null;
if (room.expiresAt < new Date()) {
prisma.room.delete({ where: { id: roomId } }).catch(() => {});
return null;
}
return normalize(JSON.parse(room.data));
}