refactor(api): implement caching for tunnel and version status endpoints

This commit is contained in:
decolua
2026-07-09 15:08:30 +07:00
parent 20b442b708
commit a4c5fa4e14
3 changed files with 70 additions and 30 deletions

View File

@@ -32,6 +32,10 @@ import { syncToJson as syncMitmAliasCache } from "@/lib/mitmAliasCache";
process.setMaxListeners(20);
// Defer heavy startup work so the first HTTP request (login → dashboard) isn't
// starved by DB cleanup, cloudflared download, lsof/DNS probes and OAuth pings.
const STARTUP_DEFER_MS = 3000;
// Survive Next.js hot reload
const g = global.__appSingleton ??= {
signalHandlersRegistered: false,
@@ -47,23 +51,8 @@ const g = global.__appSingleton ??= {
export async function initializeApp() {
try {
await cleanupProviderConnections();
const settings = await getSettings();
// Auto-resume tunnel (once per process)
if (settings.tunnelEnabled && !g.tunnelAutoResumed) {
g.tunnelAutoResumed = true;
console.log("[InitApp] Tunnel was enabled, auto-resuming...");
safeRestartTunnel("startup").catch((e) => console.log("[InitApp] Tunnel resume failed:", e.message));
}
// Auto-resume tailscale (once per process)
if (settings.tailscaleEnabled && !g.tailscaleAutoResumed) {
g.tailscaleAutoResumed = true;
console.log("[InitApp] Tailscale was enabled, auto-resuming...");
safeRestartTailscale("startup").catch((e) => console.log("[InitApp] Tailscale resume failed:", e.message));
}
// Register cleanup + exit-respawn callback immediately so signals and
// unexpected cloudflared exits are handled even during the deferred window.
if (!g.signalHandlersRegistered) {
const cleanup = () => {
try { removeAllDNSEntriesSync(); } catch { /* best effort */ }
@@ -76,25 +65,48 @@ export async function initializeApp() {
g.signalHandlersRegistered = true;
}
ensureCloudflared().catch(() => {});
// Sync mitmAlias DB → JSON cache so standalone MITM server can read it
syncMitmAliasCache().catch(() => {});
// Auto-respawn tunnel when cloudflared exits unexpectedly (e.g. network change drop)
setTunnelUnexpectedExitCallback(() => {
safeRestartTunnel("unexpected-exit").catch(() => {});
});
startWatchdog();
startNetworkMonitor();
autoStartMitm();
startQuotaAutoPing();
// Defer the heavy work — nothing here blocks incoming requests.
setTimeout(() => {
runHeavyStartup().catch((e) => console.error("[InitApp] deferred startup failed:", e.message));
}, STARTUP_DEFER_MS);
} catch (error) {
console.error("[InitApp] Error:", error);
}
}
async function runHeavyStartup() {
await cleanupProviderConnections();
const settings = await getSettings();
// Auto-resume tunnel (once per process)
if (settings.tunnelEnabled && !g.tunnelAutoResumed) {
g.tunnelAutoResumed = true;
console.log("[InitApp] Tunnel was enabled, auto-resuming...");
safeRestartTunnel("startup").catch((e) => console.log("[InitApp] Tunnel resume failed:", e.message));
}
// Auto-resume tailscale (once per process)
if (settings.tailscaleEnabled && !g.tailscaleAutoResumed) {
g.tailscaleAutoResumed = true;
console.log("[InitApp] Tailscale was enabled, auto-resuming...");
safeRestartTailscale("startup").catch((e) => console.log("[InitApp] Tailscale resume failed:", e.message));
}
ensureCloudflared().catch(() => {});
// Sync mitmAlias DB → JSON cache so standalone MITM server can read it
syncMitmAliasCache().catch(() => {});
startWatchdog();
startNetworkMonitor();
autoStartMitm();
startQuotaAutoPing();
}
async function autoStartMitm() {
if (g.mitmStartInProgress) return;
g.mitmStartInProgress = true;