feat: complete v0.5 operations foundation
This commit is contained in:
+17
-6
@@ -1,8 +1,19 @@
|
||||
const visits = new Map<string, { count: number; resetAt: number }>();
|
||||
import { db } from "@/lib/db";
|
||||
|
||||
export function withinRateLimit(key: string, limit = 30, windowMs = 60_000) {
|
||||
const now = Date.now(); const record = visits.get(key);
|
||||
if (!record || record.resetAt <= now) { visits.set(key, { count: 1, resetAt: now + windowMs }); return true; }
|
||||
if (record.count >= limit) return false;
|
||||
record.count += 1; return true;
|
||||
/** SQLite-backed fixed-window limiter shared by every Web container using this database. */
|
||||
export function withinRateLimit(bucket: string, limit = 30, windowMs = 60_000) {
|
||||
const now = Date.now();
|
||||
const transaction = db.transaction(() => {
|
||||
const found = db.prepare("SELECT count,reset_at FROM rate_limits WHERE bucket=?").get(bucket) as { count: number; reset_at: number } | undefined;
|
||||
if (!found || found.reset_at <= now) {
|
||||
db.prepare("INSERT INTO rate_limits(bucket,count,reset_at) VALUES(?,?,?) ON CONFLICT(bucket) DO UPDATE SET count=excluded.count,reset_at=excluded.reset_at").run(bucket, 1, now + windowMs);
|
||||
return true;
|
||||
}
|
||||
if (found.count >= limit) return false;
|
||||
db.prepare("UPDATE rate_limits SET count=count+1 WHERE bucket=?").run(bucket);
|
||||
return true;
|
||||
});
|
||||
const allowed = transaction();
|
||||
if (Math.random() < 0.01) db.prepare("DELETE FROM rate_limits WHERE reset_at<?").run(now);
|
||||
return allowed;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user