PRIX / lib /src /services /token-scheduler.js
Rachit-Tw's picture
Upload 169 files
9284ad7 verified
Raw
History Blame Contribute Delete
2.78 kB
"use strict";
/**
* Token Scheduler Service
* Manages rate limiting for AI API calls
*
* NOTE: This is currently a per-process scheduler.
* For horizontal scaling, replace with Redis-backed distributed rate limiter.
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.heavyScheduler = exports.lightScheduler = exports.TokenScheduler = void 0;
const pino_1 = __importDefault(require("pino"));
const logger = (0, pino_1.default)({ level: process.env.LOG_LEVEL || 'info' });
class TokenScheduler {
usedTokens = 0;
limit = 10500; // Safety margin below 12k Groq TPM
windowStart = Date.now();
name;
constructor(name = 'default') {
this.name = name;
}
/**
* Update the token limit
*/
setLimit(newLimit) {
this.limit = newLimit;
logger.info(`[TokenScheduler:${this.name}] Limit updated to ${this.limit} tokens/min`);
}
/**
* Get current metrics
*/
getMetrics() {
return {
usedTokens: this.usedTokens,
limit: this.limit,
windowStart: this.windowStart
};
}
/**
* Wait for token budget to be available
* Implements sliding window rate limiting
*/
async wait(tokens) {
const now = Date.now();
// Reset window if 60 seconds have passed
if (now - this.windowStart > 60000) {
this.usedTokens = 0;
this.windowStart = now;
}
// Check if we need to wait
if (this.usedTokens + tokens > this.limit) {
const waitTime = Math.max(0, 60000 - (now - this.windowStart) + 2000);
logger.info(`[TokenScheduler:${this.name}] Budget exhausted (${this.usedTokens}/${this.limit}). Waiting ${Math.round(waitTime / 1000)}s...`);
await new Promise(r => setTimeout(r, waitTime));
this.usedTokens = 0; // Reset after waiting a full window
this.windowStart = Date.now();
return this.wait(tokens); // Recursive check
}
this.usedTokens += tokens;
}
/**
* Reset the scheduler (useful for testing)
*/
reset() {
this.usedTokens = 0;
this.windowStart = Date.now();
logger.debug(`[TokenScheduler:${this.name}] Reset`);
}
}
exports.TokenScheduler = TokenScheduler;
/**
* Global scheduler instances (maintained for backward compatibility)
*
* TODO: Replace with Redis-backed distributed scheduler for horizontal scaling
*/
exports.lightScheduler = new TokenScheduler('light');
exports.heavyScheduler = new TokenScheduler('heavy');
//# sourceMappingURL=token-scheduler.js.map