mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 08:20:36 +00:00
Fix: Limit stats retention to 7 days
This commit is contained in:
@@ -4,7 +4,7 @@ import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
|
||||
type WindowKey = "24h" | "7d" | "30d";
|
||||
type WindowKey = "24h" | "7d";
|
||||
|
||||
type PacketTypeEntry = {
|
||||
key: string;
|
||||
@@ -91,7 +91,6 @@ type DashboardResponse = {
|
||||
const WINDOW_OPTIONS: Array<{ key: WindowKey; label: string }> = [
|
||||
{ key: "24h", label: "24h" },
|
||||
{ key: "7d", label: "7 days" },
|
||||
{ key: "30d", label: "30 days" },
|
||||
];
|
||||
|
||||
const PACKET_TYPE_INFO: Record<string, { title: string; summary: string }> = {
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
extractCfGeo,
|
||||
jsonHeaders,
|
||||
loadDashboardSummary,
|
||||
purgeOldReports,
|
||||
validateIngestPayload,
|
||||
type Env,
|
||||
type IngestPayload,
|
||||
@@ -82,6 +83,9 @@ async function handleIngest(request: Request, env: Env): Promise<Response> {
|
||||
const result = await env.DB.prepare(REPORT_INSERT_SQL).bind(...values).run();
|
||||
const changes = Number((result.meta as { changes?: number }).changes ?? 0);
|
||||
|
||||
// Purge reports older than 7 days (best-effort, don't block response)
|
||||
void purgeOldReports(env).catch(() => {});
|
||||
|
||||
return Response.json(
|
||||
{
|
||||
ok: true,
|
||||
@@ -107,7 +111,7 @@ async function handleDashboard(request: Request, env: Env): Promise<Response> {
|
||||
const url = new URL(request.url);
|
||||
const windowParam = url.searchParams.get("window");
|
||||
const summary = await loadDashboardSummary(env, windowParam);
|
||||
const cacheTtl = windowParam === "7d" || windowParam === "30d" ? 86400 : 60;
|
||||
const cacheTtl = windowParam === "7d" ? 86400 : 60;
|
||||
return Response.json(
|
||||
{
|
||||
generatedAt: new Date().toISOString(),
|
||||
|
||||
@@ -85,13 +85,10 @@ const WINDOW_OPTIONS = {
|
||||
durationMs: 7 * 24 * 60 * 60 * 1000,
|
||||
bucket: "day",
|
||||
},
|
||||
"30d": {
|
||||
label: "Last 30 days",
|
||||
durationMs: 30 * 24 * 60 * 60 * 1000,
|
||||
bucket: "day",
|
||||
},
|
||||
} as const;
|
||||
|
||||
const RETENTION_MS = 7 * 24 * 60 * 60 * 1000;
|
||||
|
||||
export const jsonHeaders = {
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
} as const;
|
||||
@@ -269,8 +266,7 @@ export function buildWindowFilter(
|
||||
): WindowFilter {
|
||||
const windowKey =
|
||||
requestedWindow === "24h" ||
|
||||
requestedWindow === "7d" ||
|
||||
requestedWindow === "30d"
|
||||
requestedWindow === "7d"
|
||||
? requestedWindow
|
||||
: "24h";
|
||||
const option = WINDOW_OPTIONS[windowKey];
|
||||
@@ -282,6 +278,19 @@ export function buildWindowFilter(
|
||||
};
|
||||
}
|
||||
|
||||
export async function purgeOldReports(
|
||||
env: Env,
|
||||
now: Date = new Date(),
|
||||
): Promise<number> {
|
||||
const cutoff = new Date(now.getTime() - RETENTION_MS).toISOString();
|
||||
const result = await env.DB.prepare(
|
||||
"DELETE FROM reports WHERE window_end < ?",
|
||||
)
|
||||
.bind(cutoff)
|
||||
.run();
|
||||
return Number((result.meta as { changes?: number }).changes ?? 0);
|
||||
}
|
||||
|
||||
export async function loadDashboardSummary(
|
||||
env: Env,
|
||||
requestedWindow: string | null,
|
||||
|
||||
Reference in New Issue
Block a user