Files
MOPC-Portal/src/server/services/round-scheduler.ts
Matt 73759eaddd
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m8s
Trigger rebuild
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 11:52:28 +01:00

68 lines
1.9 KiB
TypeScript

import { prisma } from '@/lib/prisma'
import { activateRound, closeRound } from './round-engine'
/**
* Checks 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 }
}