feat: improve daily puzzle generation with a global Prisma client, detailed logging, and race condition handling.
This commit is contained in:
56
app/page.tsx
56
app/page.tsx
@@ -1,41 +1,59 @@
|
|||||||
import Game from '@/components/Game';
|
import Game from '@/components/Game';
|
||||||
|
|
||||||
|
import { PrismaClient } from '@prisma/client';
|
||||||
|
|
||||||
|
// PrismaClient is attached to the `global` object in development to prevent
|
||||||
|
// exhausting your database connection limit.
|
||||||
|
const globalForPrisma = global as unknown as { prisma: PrismaClient };
|
||||||
|
|
||||||
|
const prisma = globalForPrisma.prisma || new PrismaClient();
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma;
|
||||||
|
|
||||||
async function getDailyPuzzle() {
|
async function getDailyPuzzle() {
|
||||||
try {
|
try {
|
||||||
// In a real app, use absolute URL or internal API call
|
|
||||||
// Since we are server-side, we can call the DB directly or fetch the API
|
|
||||||
// Calling API requires full URL (http://localhost:3000...), which is tricky in some envs
|
|
||||||
// Better to call DB directly here or use a helper function shared with the API
|
|
||||||
// But for simplicity, let's fetch the API if we can, or just use Prisma directly.
|
|
||||||
// Using Prisma directly is better for Server Components.
|
|
||||||
|
|
||||||
const { PrismaClient } = await import('@prisma/client');
|
|
||||||
const prisma = new PrismaClient();
|
|
||||||
|
|
||||||
const today = new Date().toISOString().split('T')[0];
|
const today = new Date().toISOString().split('T')[0];
|
||||||
|
console.log(`[getDailyPuzzle] Checking puzzle for date: ${today}`);
|
||||||
|
|
||||||
let dailyPuzzle = await prisma.dailyPuzzle.findUnique({
|
let dailyPuzzle = await prisma.dailyPuzzle.findUnique({
|
||||||
where: { date: today },
|
where: { date: today },
|
||||||
include: { song: true },
|
include: { song: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!dailyPuzzle) {
|
if (!dailyPuzzle) {
|
||||||
// Trigger generation logic (same as API)
|
console.log('[getDailyPuzzle] No puzzle found, attempting to create...');
|
||||||
// Duplicating logic is bad, but for now it's quickest.
|
|
||||||
// Ideally extract "getOrCreateDailyPuzzle" to a lib.
|
|
||||||
const songsCount = await prisma.song.count();
|
const songsCount = await prisma.song.count();
|
||||||
|
console.log(`[getDailyPuzzle] Found ${songsCount} songs in DB`);
|
||||||
|
|
||||||
if (songsCount > 0) {
|
if (songsCount > 0) {
|
||||||
const skip = Math.floor(Math.random() * songsCount);
|
const skip = Math.floor(Math.random() * songsCount);
|
||||||
const randomSong = await prisma.song.findFirst({ skip });
|
const randomSong = await prisma.song.findFirst({ skip });
|
||||||
|
|
||||||
if (randomSong) {
|
if (randomSong) {
|
||||||
dailyPuzzle = await prisma.dailyPuzzle.create({
|
try {
|
||||||
data: { date: today, songId: randomSong.id },
|
dailyPuzzle = await prisma.dailyPuzzle.create({
|
||||||
include: { song: true },
|
data: { date: today, songId: randomSong.id },
|
||||||
});
|
include: { song: true },
|
||||||
|
});
|
||||||
|
console.log(`[getDailyPuzzle] Created puzzle for song: ${randomSong.title}`);
|
||||||
|
} catch (createError) {
|
||||||
|
// Handle race condition: if another request created it in the meantime
|
||||||
|
console.log('[getDailyPuzzle] Creation failed, trying to fetch again (likely race condition)');
|
||||||
|
dailyPuzzle = await prisma.dailyPuzzle.findUnique({
|
||||||
|
where: { date: today },
|
||||||
|
include: { song: true },
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
console.log('[getDailyPuzzle] No songs available to create puzzle');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dailyPuzzle) return null;
|
if (!dailyPuzzle) {
|
||||||
|
console.log('[getDailyPuzzle] Failed to get or create puzzle');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: dailyPuzzle.id,
|
id: dailyPuzzle.id,
|
||||||
@@ -46,7 +64,7 @@ async function getDailyPuzzle() {
|
|||||||
coverImage: dailyPuzzle.song.coverImage ? `/uploads/covers/${dailyPuzzle.song.coverImage}` : null,
|
coverImage: dailyPuzzle.song.coverImage ? `/uploads/covers/${dailyPuzzle.song.coverImage}` : null,
|
||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error('[getDailyPuzzle] Error:', e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user