61 lines
1.8 KiB
JavaScript
61 lines
1.8 KiB
JavaScript
function sleep(milliseconds) {
|
|
return new Promise(resolve => setTimeout(resolve, milliseconds));
|
|
}
|
|
|
|
function buildThrottle(maxRequestsPerMinute) {
|
|
const limit = Math.max(1, Math.floor(maxRequestsPerMinute));
|
|
const interval = Math.ceil(60000 / limit);
|
|
let nextAvailable = 0;
|
|
|
|
return function throttle(fn) {
|
|
return async function throttledFunction(...args) {
|
|
const now = Date.now();
|
|
const waitMs = Math.max(0, nextAvailable - now);
|
|
nextAvailable = Math.max(nextAvailable, now) + interval;
|
|
|
|
if (waitMs > 0) {
|
|
await sleep(waitMs);
|
|
}
|
|
|
|
return fn(...args);
|
|
};
|
|
};
|
|
}
|
|
|
|
function applyRateLimitBuffer(rateLimitPerMinute) {
|
|
return Math.max(1, Math.floor(rateLimitPerMinute * 0.95));
|
|
}
|
|
|
|
function getTotalRateLimitPerMinute(config) {
|
|
const defaultRateLimit = config.rateLimitPerMinute || 50;
|
|
let totalRateLimit = 0;
|
|
|
|
if (Array.isArray(config.apiKeys) && config.apiKeys.length > 0) {
|
|
for (const entry of config.apiKeys) {
|
|
if (typeof entry === 'string') {
|
|
totalRateLimit += applyRateLimitBuffer(defaultRateLimit);
|
|
} else if (entry && typeof entry === 'object') {
|
|
totalRateLimit += applyRateLimitBuffer(entry.rateLimitPerMinute || defaultRateLimit);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Array.isArray(config.serviceAccounts) && config.serviceAccounts.length > 0) {
|
|
for (const entry of config.serviceAccounts) {
|
|
if (typeof entry === 'string') {
|
|
totalRateLimit += applyRateLimitBuffer(defaultRateLimit);
|
|
} else if (entry && typeof entry === 'object') {
|
|
totalRateLimit += applyRateLimitBuffer(entry.rateLimitPerMinute || defaultRateLimit);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (totalRateLimit === 0) {
|
|
totalRateLimit = applyRateLimitBuffer(defaultRateLimit);
|
|
}
|
|
|
|
return Math.max(1, totalRateLimit);
|
|
}
|
|
|
|
module.exports = {buildThrottle, applyRateLimitBuffer, getTotalRateLimitPerMinute};
|