Refactor badge endpoint to use KV store

pull/163/head
2jang 2025-12-10 21:02:45 +09:00
parent ad98b21762
commit d24341c989
No known key found for this signature in database
GPG Key ID: EAF1B299C8E9B61E
1 changed files with 27 additions and 33 deletions

View File

@ -1,22 +1,9 @@
import { workerConfig } from '@/uptime.config'
import { MonitorState } from '@/types/config'
import { NextRequest } from 'next/server' import { NextRequest } from 'next/server'
export const runtime = 'edge' export const runtime = 'edge'
type DataResponse = {
up: number
down: number
updatedAt: number
monitors: Record<
string,
{
up: boolean
latency: number
location: string
message: string
}
>
}
type BadgePayload = { type BadgePayload = {
schemaVersion: 1 schemaVersion: 1
label: string label: string
@ -44,41 +31,48 @@ export default async function handler(req: NextRequest): Promise<Response> {
try { try {
const url = new URL(req.url) const url = new URL(req.url)
const monitorId = url.searchParams.get('id') const defaultMonitorId = workerConfig.monitors[0]?.id
if (!monitorId) { const monitorId = url.searchParams.get('id') ?? defaultMonitorId
return new Response(JSON.stringify(errorBadge('UptimeFlare', 'id required')), { const label = url.searchParams.get('label') ?? monitorId ?? 'UptimeFlare'
headers: jsonHeaders,
status: 400,
})
}
const label = url.searchParams.get('label') ?? 'UptimeFlare'
const upMsg = url.searchParams.get('up') ?? 'UP' const upMsg = url.searchParams.get('up') ?? 'UP'
const downMsg = url.searchParams.get('down') ?? 'DOWN' const downMsg = url.searchParams.get('down') ?? 'DOWN'
const colorUp = url.searchParams.get('colorUp') ?? 'brightgreen' const colorUp = url.searchParams.get('colorUp') ?? 'brightgreen'
const colorDown = url.searchParams.get('colorDown') ?? 'red' const colorDown = url.searchParams.get('colorDown') ?? 'red'
const dataUrl = new URL('/api/data', url.origin) if (!monitorId) {
const resp = await fetch(dataUrl, { cache: 'no-store' }) return new Response(JSON.stringify(errorBadge(label, 'no-monitor')), {
if (!resp.ok) {
return new Response(JSON.stringify(errorBadge(label, 'unavailable')), {
headers: jsonHeaders, headers: jsonHeaders,
status: resp.status, status: 400,
}) })
} }
const payload = (await resp.json()) as DataResponse const { UPTIMEFLARE_STATE } = process.env as unknown as {
const monitor = payload.monitors?.[monitorId] UPTIMEFLARE_STATE: KVNamespace
}
if (!monitor) { const stateStr = await UPTIMEFLARE_STATE?.get('state')
if (!stateStr) {
return new Response(JSON.stringify(errorBadge(label, 'unavailable')), {
headers: jsonHeaders,
status: 503,
})
}
const state = JSON.parse(stateStr) as MonitorState
const monitorIncidentHistory = state.incident?.[monitorId]
const hasLatencyData = Boolean(state.latency?.[monitorId]?.recent?.length)
if (!monitorIncidentHistory || monitorIncidentHistory.length === 0 || !hasLatencyData) {
return new Response(JSON.stringify(errorBadge(label, 'unknown')), { return new Response(JSON.stringify(errorBadge(label, 'unknown')), {
headers: jsonHeaders, headers: jsonHeaders,
status: 404, status: 404,
}) })
} }
const isUp = monitor.up const latestIncident = monitorIncidentHistory.slice(-1)[0]
const isUp = latestIncident.end !== undefined
const badge: BadgePayload = { const badge: BadgePayload = {
schemaVersion: 1, schemaVersion: 1,
label, label,