perf: optimize monitor runner, fix SSE leak, deduplicate shared utils
This commit is contained in:
@@ -1,27 +1,10 @@
|
||||
import { Elysia, t } from "elysia";
|
||||
import { createHmac, randomBytes } from "crypto";
|
||||
import sql from "../db";
|
||||
import { createRateLimiter } from "../utils/rate-limit";
|
||||
|
||||
// ── Per-IP rate limiting for auth endpoints ───────────────────────────
|
||||
const authRateMap = new Map<string, { count: number; resetAt: number }>();
|
||||
|
||||
function checkAuthRateLimit(ip: string, maxPerMinute: number): boolean {
|
||||
const now = Date.now();
|
||||
const entry = authRateMap.get(ip);
|
||||
if (!entry || now > entry.resetAt) {
|
||||
authRateMap.set(ip, { count: 1, resetAt: now + 60_000 });
|
||||
return true;
|
||||
}
|
||||
entry.count++;
|
||||
return entry.count <= maxPerMinute;
|
||||
}
|
||||
|
||||
setInterval(() => {
|
||||
const now = Date.now();
|
||||
for (const [key, entry] of authRateMap) {
|
||||
if (now > entry.resetAt) authRateMap.delete(key);
|
||||
}
|
||||
}, 5 * 60_000);
|
||||
const checkAuthRateLimit = createRateLimiter();
|
||||
|
||||
const EMAIL_HMAC_KEY = process.env.EMAIL_HMAC_KEY || "pingql-default-hmac-key";
|
||||
|
||||
|
||||
@@ -2,16 +2,8 @@
|
||||
/// Protected by MONITOR_TOKEN — not exposed to users.
|
||||
|
||||
import { Elysia } from "elysia";
|
||||
import { timingSafeEqual } from "crypto";
|
||||
import sql from "../db";
|
||||
|
||||
function safeTokenCompare(a: string | undefined, b: string | undefined): boolean {
|
||||
if (!a || !b) return false;
|
||||
const bufA = Buffer.from(a);
|
||||
const bufB = Buffer.from(b);
|
||||
if (bufA.length !== bufB.length) return false;
|
||||
return timingSafeEqual(bufA, bufB);
|
||||
}
|
||||
import { safeTokenCompare } from "../utils/token";
|
||||
|
||||
export async function pruneOldPings(retentionDays = 90) {
|
||||
const result = await sql`DELETE FROM pings WHERE checked_at < now() - ${retentionDays + ' days'}::interval`;
|
||||
|
||||
@@ -113,7 +113,7 @@ export const monitors = new Elysia({ prefix: "/monitors" })
|
||||
SELECT id FROM monitors WHERE id = ${params.id} AND account_id = ${accountId}
|
||||
`;
|
||||
if (!monitor) return error(404, { error: "Not found" });
|
||||
const limit = Math.min(Number(query.limit ?? 100), 1000);
|
||||
const limit = Math.min(Number(query.limit) || 100, 1000);
|
||||
return sql`
|
||||
SELECT * FROM pings
|
||||
WHERE monitor_id = ${params.id}
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
import { Elysia, t } from "elysia";
|
||||
import { timingSafeEqual } from "crypto";
|
||||
import sql from "../db";
|
||||
import { resolveKey } from "./auth";
|
||||
|
||||
function safeTokenCompare(a: string | undefined, b: string | undefined): boolean {
|
||||
if (!a || !b) return false;
|
||||
const bufA = Buffer.from(a);
|
||||
const bufB = Buffer.from(b);
|
||||
if (bufA.length !== bufB.length) return false;
|
||||
return timingSafeEqual(bufA, bufB);
|
||||
}
|
||||
import { safeTokenCompare } from "../utils/token";
|
||||
|
||||
// ── SSE bus ───────────────────────────────────────────────────────────────────
|
||||
type SSEController = ReadableStreamDefaultController<Uint8Array>;
|
||||
@@ -35,7 +27,11 @@ function makeSSEStream(accountId: string): Response {
|
||||
bus.get(accountId)!.add(ctrl);
|
||||
ctrl.enqueue(enc.encode(": connected\n\n"));
|
||||
heartbeat = setInterval(() => {
|
||||
try { ctrl.enqueue(enc.encode(": heartbeat\n\n")); } catch { clearInterval(heartbeat); }
|
||||
try { ctrl.enqueue(enc.encode(": heartbeat\n\n")); } catch {
|
||||
clearInterval(heartbeat);
|
||||
bus.get(accountId)?.delete(ctrl);
|
||||
if (bus.get(accountId)?.size === 0) bus.delete(accountId);
|
||||
}
|
||||
}, 10_000);
|
||||
},
|
||||
cancel() {
|
||||
|
||||
Reference in New Issue
Block a user