fancy caching works now

This commit is contained in:
2025-06-25 19:57:28 +02:00
parent 784dcbf91c
commit e4c6a7e0a8
5 changed files with 226 additions and 36 deletions

View File

@@ -1,5 +1,18 @@
'use client';
import React, { useEffect, useState } from 'react';
import { Bar } from 'react-chartjs-2';
import {
Chart as ChartJS,
CategoryScale,
LinearScale,
BarElement,
Title,
Tooltip,
Legend,
ChartOptions,
} from 'chart.js';
ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend);
interface PostStats {
slug: string;
@@ -13,6 +26,8 @@ export default function RustStatusPage() {
const [stats, setStats] = useState<PostStats[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [autoRefresh, setAutoRefresh] = useState(false);
const autoRefreshRef = React.useRef<NodeJS.Timeout | null>(null);
const fetchStats = async () => {
setLoading(true);
@@ -31,45 +46,156 @@ export default function RustStatusPage() {
React.useEffect(() => {
fetchStats();
const interval = setInterval(fetchStats, 5000);
return () => clearInterval(interval);
// Listen for post changes via BroadcastChannel
let bc: BroadcastChannel | null = null;
if (typeof window !== 'undefined' && 'BroadcastChannel' in window) {
bc = new BroadcastChannel('posts-changed');
bc.onmessage = (event) => {
if (event.data === 'changed') {
fetchStats();
}
};
}
return () => {
if (bc) bc.close();
if (autoRefreshRef.current) clearInterval(autoRefreshRef.current);
};
}, []);
// Handle auto-refresh toggle
React.useEffect(() => {
if (autoRefresh) {
autoRefreshRef.current = setInterval(fetchStats, 2000);
} else if (autoRefreshRef.current) {
clearInterval(autoRefreshRef.current);
autoRefreshRef.current = null;
}
return () => {
if (autoRefreshRef.current) clearInterval(autoRefreshRef.current);
};
}, [autoRefresh]);
// Dashboard summary calculations
const totalHits = stats.reduce((sum, s) => sum + s.cache_hits, 0);
const totalMisses = stats.reduce((sum, s) => sum + s.cache_misses, 0);
const avgInterpret = stats.length ? (stats.reduce((sum, s) => sum + s.last_interpret_time_ms, 0) / stats.length).toFixed(1) : 0;
const avgCompile = stats.length ? (stats.reduce((sum, s) => sum + s.last_compile_time_ms, 0) / stats.length).toFixed(1) : 0;
// Chart data
const chartData = {
labels: stats.map(s => s.slug),
datasets: [
{
label: 'Cache Hits',
data: stats.map(s => s.cache_hits),
backgroundColor: 'rgba(34,197,94,0.7)',
},
{
label: 'Cache Misses',
data: stats.map(s => s.cache_misses),
backgroundColor: 'rgba(239,68,68,0.7)',
},
],
};
const chartOptions: ChartOptions<'bar'> = {
responsive: true,
plugins: {
legend: { position: 'top' },
title: { display: true, text: 'Cache Hits & Misses per Post' },
},
scales: {
x: { stacked: true },
y: { stacked: true, beginAtZero: true },
},
};
return (
<div className="p-8 max-w-4xl mx-auto">
<h1 className="text-2xl font-bold mb-6">Rust Parser Status</h1>
{loading && <div>Loading...</div>}
{error && <div className="text-red-500">{error}</div>}
{!loading && !error && (
<div className="overflow-x-auto">
<table className="min-w-full border border-gray-300 bg-white shadow-md rounded">
<thead>
<tr className="bg-gray-100">
<th className="px-4 py-2 text-left">Slug</th>
<th className="px-4 py-2 text-right">Cache Hits</th>
<th className="px-4 py-2 text-right">Cache Misses</th>
<th className="px-4 py-2 text-right">Last Interpret Time (ms)</th>
<th className="px-4 py-2 text-right">Last Compile Time (ms)</th>
</tr>
</thead>
<tbody>
{stats.length === 0 ? (
<tr><td colSpan={5} className="text-center py-4">No stats available.</td></tr>
) : (
stats.map(stat => (
<tr key={stat.slug} className="border-t">
<td className="px-4 py-2 font-mono">{stat.slug}</td>
<td className="px-4 py-2 text-right">{stat.cache_hits}</td>
<td className="px-4 py-2 text-right">{stat.cache_misses}</td>
<td className="px-4 py-2 text-right">{stat.last_interpret_time_ms}</td>
<td className="px-4 py-2 text-right">{stat.last_compile_time_ms}</td>
</tr>
))
)}
</tbody>
</table>
<div className="p-8 max-w-6xl mx-auto">
<h1 className="text-3xl font-bold mb-8 text-center">Rust Parser Dashboard</h1>
<div className="flex justify-end gap-4 mb-4">
<button
onClick={fetchStats}
className="px-4 py-2 bg-blue-600 text-white rounded shadow hover:bg-blue-700"
>
Refresh
</button>
<label className="flex items-center gap-2 cursor-pointer">
<input
type="checkbox"
checked={autoRefresh}
onChange={e => setAutoRefresh(e.target.checked)}
className="form-checkbox"
/>
<span className="text-sm">Auto-refresh every 2s</span>
</label>
</div>
{loading && (
<div className="flex flex-col items-center justify-center h-64">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-gray-900 mb-4"></div>
<div className="text-lg">Loading stats...</div>
</div>
)}
{error && (
<div className="text-red-500 text-center text-lg">{error}</div>
)}
{!loading && !error && (
<>
{/* Summary Cards */}
<div className="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
<div className="bg-green-100 rounded-lg p-6 flex flex-col items-center shadow">
<span className="text-2xl font-bold text-green-700">{totalHits}</span>
<span className="text-gray-700 mt-2">Total Cache Hits</span>
</div>
<div className="bg-red-100 rounded-lg p-6 flex flex-col items-center shadow">
<span className="text-2xl font-bold text-red-700">{totalMisses}</span>
<span className="text-gray-700 mt-2">Total Cache Misses</span>
</div>
<div className="bg-blue-100 rounded-lg p-6 flex flex-col items-center shadow">
<span className="text-2xl font-bold text-blue-700">{avgInterpret} ms</span>
<span className="text-gray-700 mt-2">Avg Interpret Time</span>
</div>
<div className="bg-purple-100 rounded-lg p-6 flex flex-col items-center shadow">
<span className="text-2xl font-bold text-purple-700">{avgCompile} ms</span>
<span className="text-gray-700 mt-2">Avg Compile Time</span>
</div>
</div>
{/* Bar Chart */}
<div className="bg-white rounded-lg shadow p-6 mb-10">
<Bar data={chartData} options={chartOptions} height={120} />
</div>
{/* Raw Data Table */}
<div className="overflow-x-auto">
<table className="min-w-full border border-gray-300 bg-white shadow-md rounded">
<thead>
<tr className="bg-gray-100">
<th className="px-4 py-2 text-left">Slug</th>
<th className="px-4 py-2 text-right">Cache Hits</th>
<th className="px-4 py-2 text-right">Cache Misses</th>
<th className="px-4 py-2 text-right">Last Interpret Time (ms)</th>
<th className="px-4 py-2 text-right">Last Compile Time (ms)</th>
</tr>
</thead>
<tbody>
{stats.length === 0 ? (
<tr><td colSpan={5} className="text-center py-4">No stats available.</td></tr>
) : (
stats.map(stat => (
<tr key={stat.slug} className="border-t">
<td className="px-4 py-2 font-mono">{stat.slug}</td>
<td className="px-4 py-2 text-right">{stat.cache_hits}</td>
<td className="px-4 py-2 text-right">{stat.cache_misses}</td>
<td className="px-4 py-2 text-right">{stat.last_interpret_time_ms}</td>
<td className="px-4 py-2 text-right">{stat.last_compile_time_ms}</td>
</tr>
))
)}
</tbody>
</table>
</div>
</>
)}
</div>
);
}