A quick vibe-coded site to test response times of PLC.directory mirrors (over 3 attempts)
1import { Mirror } from "@/config/mirrors";
2import { BenchmarkAttempt, BenchmarkResult } from "@/types/benchmark";
3
4const ATTEMPTS_PER_MIRROR = 5;
5
6const singleAttempt = async (
7 url: string,
8 did: string,
9): Promise<BenchmarkAttempt> => {
10 const fullUrl = `${url}/${did}`;
11 const uniqueUrl = `${fullUrl}?i=${Date.now()}`;
12
13 return new Promise((resolve) => {
14 const observer = new PerformanceObserver((list) => {
15 const entries = list.getEntries();
16 const entry = entries.find(
17 (e) => e.entryType === "resource" && e.name === uniqueUrl,
18 ) as PerformanceResourceTiming | undefined;
19
20 if (entry) {
21 observer.disconnect();
22
23 // Use duration for total time, or calculate from start/response
24 const responseTime = entry.duration ||
25 (entry.responseEnd - entry.startTime);
26
27 resolve({
28 responseTime,
29 status: "success",
30 statusCode: 200, // PerformanceResourceTiming doesn't provide status code
31 });
32 }
33 });
34
35 observer.observe({ entryTypes: ["resource"] });
36
37 // Start the fetch
38 fetch(uniqueUrl, {
39 cache: "no-store",
40 })
41 .then(async (response) => {
42 if (!response.ok) {
43 observer.disconnect();
44 resolve({
45 responseTime: 0,
46 status: "error",
47 statusCode: response.status,
48 error: `HTTP ${response.status}`,
49 });
50 return;
51 }
52
53 await response.json(); // Consume the response
54
55 // Wait briefly for PerformanceObserver to capture the entry
56 setTimeout(() => {
57 const entries = performance.getEntriesByName(uniqueUrl, "resource");
58 if (entries.length > 0) {
59 const entry = entries[0] as PerformanceResourceTiming;
60 const responseTime = entry.duration ||
61 (entry.responseEnd - entry.startTime);
62 observer.disconnect();
63 resolve({
64 responseTime,
65 status: "success",
66 statusCode: response.status,
67 });
68 } else {
69 // Fallback if entry not found
70 observer.disconnect();
71 resolve({
72 responseTime: 0,
73 status: "error",
74 error: "Performance entry not found",
75 });
76 }
77 }, 100);
78 })
79 .catch((error) => {
80 observer.disconnect();
81 resolve({
82 responseTime: 0,
83 status: "error",
84 error: error instanceof Error ? error.message : "Unknown error",
85 });
86 });
87 });
88};
89
90export const benchmarkMirror = async (
91 mirror: Mirror,
92 did: string,
93): Promise<BenchmarkResult> => {
94 const attempts: BenchmarkAttempt[] = [];
95
96 for (let i = 0; i < ATTEMPTS_PER_MIRROR; i++) {
97 const attempt = await singleAttempt(mirror.url, did);
98 attempts.push(attempt);
99 }
100
101 const successfulAttempts = attempts.filter((a) => a.status === "success");
102 const avgResponseTime = successfulAttempts.length > 0
103 ? successfulAttempts.reduce((sum, a) => sum + a.responseTime, 0) /
104 successfulAttempts.length
105 : 0;
106
107 return {
108 mirrorUrl: mirror.url,
109 implementation: mirror.implementation,
110 attempts,
111 avgResponseTime,
112 status: successfulAttempts.length > 0 ? "success" : "error",
113 };
114};
115
116export const benchmarkAllMirrors = async (
117 mirrors: Mirror[],
118 did: string,
119): Promise<BenchmarkResult[]> => {
120 const promises = mirrors.map((mirror) => benchmarkMirror(mirror, did));
121 return Promise.all(promises);
122};