Move round scheduler in-app via instrumentation.ts, remove cron endpoint
All checks were successful
Build and Push Docker Image / build (push) Successful in 18s
All checks were successful
Build and Push Docker Image / build (push) Successful in 18s
Round open/close scheduling now runs as a 60s setInterval inside the app process (via instrumentation.ts register hook) instead of needing an external crontab. Removed the /api/cron/round-scheduler endpoint. - DRAFT rounds auto-activate when windowOpenAt arrives - ACTIVE rounds auto-close when windowCloseAt passes - Uses existing activateRound/closeRound from round-engine Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
67
src/server/services/round-scheduler.ts
Normal file
67
src/server/services/round-scheduler.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { prisma } from '@/lib/prisma'
|
||||
import { activateRound, closeRound } from './round-engine'
|
||||
|
||||
/**
|
||||
* Check for rounds that need to be automatically opened or closed
|
||||
* based on their windowOpenAt / windowCloseAt timestamps.
|
||||
* Called on a 60-second interval from instrumentation.ts.
|
||||
*/
|
||||
export async function processScheduledRounds(): Promise<{
|
||||
activated: number
|
||||
closed: number
|
||||
}> {
|
||||
const now = new Date()
|
||||
let activated = 0
|
||||
let closed = 0
|
||||
|
||||
// Find a SUPER_ADMIN to use as the actor for audit logging
|
||||
const systemActor = await prisma.user.findFirst({
|
||||
where: { role: 'SUPER_ADMIN' },
|
||||
select: { id: true },
|
||||
})
|
||||
|
||||
if (!systemActor) {
|
||||
return { activated, closed }
|
||||
}
|
||||
|
||||
// 1. Activate DRAFT rounds whose windowOpenAt has arrived
|
||||
const roundsToOpen = await prisma.round.findMany({
|
||||
where: {
|
||||
status: 'ROUND_DRAFT',
|
||||
windowOpenAt: { lte: now },
|
||||
competition: { status: { not: 'ARCHIVED' } },
|
||||
},
|
||||
select: { id: true, name: true },
|
||||
})
|
||||
|
||||
for (const round of roundsToOpen) {
|
||||
const result = await activateRound(round.id, systemActor.id, prisma)
|
||||
if (result.success) {
|
||||
activated++
|
||||
console.log(`[RoundScheduler] Activated round: ${round.name}`)
|
||||
} else {
|
||||
console.warn(`[RoundScheduler] Failed to activate "${round.name}":`, result.errors)
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Close ACTIVE rounds whose windowCloseAt has passed
|
||||
const roundsToClose = await prisma.round.findMany({
|
||||
where: {
|
||||
status: 'ROUND_ACTIVE',
|
||||
windowCloseAt: { lte: now },
|
||||
},
|
||||
select: { id: true, name: true },
|
||||
})
|
||||
|
||||
for (const round of roundsToClose) {
|
||||
const result = await closeRound(round.id, systemActor.id, prisma)
|
||||
if (result.success) {
|
||||
closed++
|
||||
console.log(`[RoundScheduler] Closed round: ${round.name}`)
|
||||
} else {
|
||||
console.warn(`[RoundScheduler] Failed to close "${round.name}":`, result.errors)
|
||||
}
|
||||
}
|
||||
|
||||
return { activated, closed }
|
||||
}
|
||||
Reference in New Issue
Block a user