manifest
Version:
Self-hosted Manifest LLM router with embedded server, SQLite database, and dashboard
81 lines • 3.29 kB
JavaScript
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProxyRateLimiter = void 0;
const common_1 = require("@nestjs/common");
const RATE_WINDOW_MS = 60_000;
const RATE_MAX_REQUESTS = 200;
const MAX_RATE_ENTRIES = 50_000;
const CONCURRENCY_MAX = 10;
const CLEANUP_INTERVAL_MS = 60_000;
let ProxyRateLimiter = class ProxyRateLimiter {
rates = new Map();
concurrency = new Map();
cleanupTimer;
constructor() {
this.cleanupTimer = setInterval(() => this.evictExpired(), CLEANUP_INTERVAL_MS);
if (typeof this.cleanupTimer === 'object' && 'unref' in this.cleanupTimer) {
this.cleanupTimer.unref();
}
}
onModuleDestroy() {
clearInterval(this.cleanupTimer);
}
checkLimit(userId) {
const now = Date.now();
let entry = this.rates.get(userId);
if (!entry || now - entry.windowStart >= RATE_WINDOW_MS) {
entry = { count: 0, windowStart: now };
}
if (entry.count >= RATE_MAX_REQUESTS) {
throw new common_1.HttpException('Too many requests — wait a few seconds and retry.', common_1.HttpStatus.TOO_MANY_REQUESTS);
}
entry.count++;
this.rates.set(userId, entry);
this.evictLruIfNeeded();
}
acquireSlot(userId) {
const current = this.concurrency.get(userId) ?? 0;
if (current >= CONCURRENCY_MAX) {
throw new common_1.HttpException('Too many concurrent requests. Give it a moment.', common_1.HttpStatus.TOO_MANY_REQUESTS);
}
this.concurrency.set(userId, current + 1);
}
releaseSlot(userId) {
const current = this.concurrency.get(userId) ?? 0;
if (current <= 1) {
this.concurrency.delete(userId);
}
else {
this.concurrency.set(userId, current - 1);
}
}
evictExpired() {
const now = Date.now();
for (const [key, entry] of this.rates) {
if (now - entry.windowStart >= RATE_WINDOW_MS) {
this.rates.delete(key);
}
}
}
evictLruIfNeeded() {
while (this.rates.size > MAX_RATE_ENTRIES) {
const oldest = this.rates.keys().next().value;
this.rates.delete(oldest);
}
}
};
exports.ProxyRateLimiter = ProxyRateLimiter;
exports.ProxyRateLimiter = ProxyRateLimiter = __decorate([
(0, common_1.Injectable)(),
__metadata("design:paramtypes", [])
], ProxyRateLimiter);
//# sourceMappingURL=proxy-rate-limiter.js.map