Files
openclaw-market/app/api/v1/heatmap/route.ts

62 lines
1.6 KiB
TypeScript

import { NextResponse } from "next/server";
import { gte, and, isNotNull, sql } from "drizzle-orm";
import { db } from "@/lib/db";
import { claws } from "@/lib/db/schema";
import { getCacheHeatmap, setCacheHeatmap } from "@/lib/redis";
export async function GET() {
try {
const cached = await getCacheHeatmap();
if (cached) {
return NextResponse.json(JSON.parse(cached));
}
const fiveMinutesAgo = new Date(Date.now() - 5 * 60 * 1000);
const activeClaws = await db
.select({
city: claws.city,
country: claws.country,
latitude: claws.latitude,
longitude: claws.longitude,
count: sql<number>`count(*)`,
})
.from(claws)
.where(
and(
gte(claws.lastHeartbeat, fiveMinutesAgo),
isNotNull(claws.latitude),
isNotNull(claws.longitude)
)
)
.groupBy(
claws.city,
claws.country,
claws.latitude,
claws.longitude
);
const points = activeClaws.map((row) => ({
lat: Number(row.latitude),
lng: Number(row.longitude),
weight: row.count,
clawCount: row.count,
city: row.city,
country: row.country,
}));
const lastUpdated = new Date().toISOString();
const responseData = { points, lastUpdated };
await setCacheHeatmap(JSON.stringify(responseData));
return NextResponse.json(responseData);
} catch (error) {
console.error("Heatmap error:", error);
return NextResponse.json(
{ error: "Internal server error" },
{ status: 500 }
);
}
}