mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 16:30:28 +00:00
Fix: Limit stats retention to 7 days
This commit is contained in:
@@ -5,22 +5,22 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000729">
|
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000669">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="1: increment_build_number" time="1.008455">
|
<testcase classname="fastlane.lanes" name="1: increment_build_number" time="0.917785">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="2: build_app" time="224.694344">
|
<testcase classname="fastlane.lanes" name="2: build_app" time="130.084682">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="3: upload_to_app_store" time="170.718455">
|
<testcase classname="fastlane.lanes" name="3: upload_to_app_store" time="203.665249">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { Button } from "@/components/ui/button";
|
|||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||||
|
|
||||||
type WindowKey = "24h" | "7d" | "30d";
|
type WindowKey = "24h" | "7d";
|
||||||
|
|
||||||
type PacketTypeEntry = {
|
type PacketTypeEntry = {
|
||||||
key: string;
|
key: string;
|
||||||
@@ -91,7 +91,6 @@ type DashboardResponse = {
|
|||||||
const WINDOW_OPTIONS: Array<{ key: WindowKey; label: string }> = [
|
const WINDOW_OPTIONS: Array<{ key: WindowKey; label: string }> = [
|
||||||
{ key: "24h", label: "24h" },
|
{ key: "24h", label: "24h" },
|
||||||
{ key: "7d", label: "7 days" },
|
{ key: "7d", label: "7 days" },
|
||||||
{ key: "30d", label: "30 days" },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const PACKET_TYPE_INFO: Record<string, { title: string; summary: string }> = {
|
const PACKET_TYPE_INFO: Record<string, { title: string; summary: string }> = {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {
|
|||||||
extractCfGeo,
|
extractCfGeo,
|
||||||
jsonHeaders,
|
jsonHeaders,
|
||||||
loadDashboardSummary,
|
loadDashboardSummary,
|
||||||
|
purgeOldReports,
|
||||||
validateIngestPayload,
|
validateIngestPayload,
|
||||||
type Env,
|
type Env,
|
||||||
type IngestPayload,
|
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 result = await env.DB.prepare(REPORT_INSERT_SQL).bind(...values).run();
|
||||||
const changes = Number((result.meta as { changes?: number }).changes ?? 0);
|
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(
|
return Response.json(
|
||||||
{
|
{
|
||||||
ok: true,
|
ok: true,
|
||||||
@@ -107,7 +111,7 @@ async function handleDashboard(request: Request, env: Env): Promise<Response> {
|
|||||||
const url = new URL(request.url);
|
const url = new URL(request.url);
|
||||||
const windowParam = url.searchParams.get("window");
|
const windowParam = url.searchParams.get("window");
|
||||||
const summary = await loadDashboardSummary(env, windowParam);
|
const summary = await loadDashboardSummary(env, windowParam);
|
||||||
const cacheTtl = windowParam === "7d" || windowParam === "30d" ? 86400 : 60;
|
const cacheTtl = windowParam === "7d" ? 86400 : 60;
|
||||||
return Response.json(
|
return Response.json(
|
||||||
{
|
{
|
||||||
generatedAt: new Date().toISOString(),
|
generatedAt: new Date().toISOString(),
|
||||||
|
|||||||
@@ -85,13 +85,10 @@ const WINDOW_OPTIONS = {
|
|||||||
durationMs: 7 * 24 * 60 * 60 * 1000,
|
durationMs: 7 * 24 * 60 * 60 * 1000,
|
||||||
bucket: "day",
|
bucket: "day",
|
||||||
},
|
},
|
||||||
"30d": {
|
|
||||||
label: "Last 30 days",
|
|
||||||
durationMs: 30 * 24 * 60 * 60 * 1000,
|
|
||||||
bucket: "day",
|
|
||||||
},
|
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
const RETENTION_MS = 7 * 24 * 60 * 60 * 1000;
|
||||||
|
|
||||||
export const jsonHeaders = {
|
export const jsonHeaders = {
|
||||||
"content-type": "application/json; charset=utf-8",
|
"content-type": "application/json; charset=utf-8",
|
||||||
} as const;
|
} as const;
|
||||||
@@ -269,8 +266,7 @@ export function buildWindowFilter(
|
|||||||
): WindowFilter {
|
): WindowFilter {
|
||||||
const windowKey =
|
const windowKey =
|
||||||
requestedWindow === "24h" ||
|
requestedWindow === "24h" ||
|
||||||
requestedWindow === "7d" ||
|
requestedWindow === "7d"
|
||||||
requestedWindow === "30d"
|
|
||||||
? requestedWindow
|
? requestedWindow
|
||||||
: "24h";
|
: "24h";
|
||||||
const option = WINDOW_OPTIONS[windowKey];
|
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(
|
export async function loadDashboardSummary(
|
||||||
env: Env,
|
env: Env,
|
||||||
requestedWindow: string | null,
|
requestedWindow: string | null,
|
||||||
|
|||||||
Reference in New Issue
Block a user