Merged in feature/warmup (pull request #1887)

* unified warmup function

Approved-by: Linus Flood
This commit is contained in:
Joakim Jäderberg
2025-04-29 06:18:14 +00:00
parent bbbd665a32
commit c1505ce50e
33 changed files with 886 additions and 185 deletions

View File

@@ -0,0 +1,139 @@
import { type NextRequest, NextResponse } from "next/server"
import { env } from "@/env/server"
import { warmup } from "@/services/warmup"
import { isWarmupKey } from "@/services/warmup/warmupKeys"
import { createLogger } from "@/utils/logger"
export const dynamic = "force-dynamic"
const logger = createLogger("Warmup")
export async function GET(req: NextRequest) {
const url = new URL(req.url)
const key = url.searchParams.get("key")
if (!isAuthroized(req)) {
return unauthorizedResponse()
}
const executionStart = performance.now()
if (!isWarmupKey(key)) {
return invalidKeyResponse(key)
}
logger.debug("Warming up:", key)
const warmupResult = await warmup(key)
const executionTime = performance.now() - executionStart
switch (warmupResult.status) {
case "completed":
return warmupCompletedResponse(warmupResult, key, executionTime)
case "error":
return warmupErrorResponse(warmupResult, key, executionTime)
case "skipped":
return warmupSkippedResponse(warmupResult, key, executionTime)
default:
const status = (warmupResult as unknown as { status: string }).status
throw new Error(`Unknown warmup status '${status}'`)
}
}
function isAuthroized(req: NextRequest) {
const authHeader = req.headers.get("Authorization")
if (!authHeader || !env.WARMUP_TOKEN) {
return false
}
const token = authHeader.split(" ")[1]
if (!token) {
return false
}
return token === env.WARMUP_TOKEN
}
function warmupCompletedResponse(
warmupResult: Awaited<ReturnType<typeof warmup>>,
key: string,
executionTime: number
) {
logger.debug(`Warmup completed: ${key} in ${executionTime.toFixed(2)}ms`)
return NextResponse.json(
{
...warmupResult,
key,
executionTime: `${executionTime.toFixed(2)}ms`,
},
{ status: 200 }
)
}
function warmupSkippedResponse(
warmupResult: Awaited<ReturnType<typeof warmup>>,
key: string,
executionTime: number
) {
logger.debug("Warmup skipped:", key)
return NextResponse.json(
{
key,
status: warmupResult.status,
executionTime: `${executionTime.toFixed(2)}ms`,
},
{ status: 200 }
)
}
function warmupErrorResponse(
warmupResult: Awaited<ReturnType<typeof warmup>>,
key: string,
executionTime: number
) {
if (warmupResult.status !== "error") {
throw new Error("Warmup result is not an error")
}
logger.error("Warmup error", {
key,
error: warmupResult.error.message,
})
return NextResponse.json(
{
key,
status: warmupResult.status,
error: warmupResult.error.message,
executionTime: `${executionTime.toFixed(2)}ms`,
},
{ status: 500 }
)
}
function unauthorizedResponse() {
return NextResponse.json(
{
error: "Unauthorized access",
},
{ status: 401 }
)
}
function invalidKeyResponse(key: string | null) {
if (isWarmupKey(key)) {
throw new Error("Invalid invocation with valid cache key")
}
logger.error(`Invalid key ${key}`)
return NextResponse.json(
{
key,
error: `Invalid warmup key: '${key}'`,
},
{ status: 400 }
)
}