okta-mcp-server
Version:
Model Context Protocol (MCP) server for Okta API operations with support for bulk operations and caching
82 lines • 3.03 kB
JavaScript
export class RateLimitSimulator {
counters = new Map();
config;
constructor(config = {
limit: 600,
window: 60,
warningThreshold: 0.8,
simulateExhaustion: true,
exhaustionProbability: 0.01,
}) {
this.config = config;
}
check(key = 'default') {
const now = Date.now();
const counter = this.counters.get(key) || {
count: 0,
resetTime: now + this.config.window * 1000,
};
// Reset counter if window has passed
if (now > counter.resetTime) {
counter.count = 0;
counter.resetTime = now + this.config.window * 1000;
}
// Simulate random exhaustion for testing
if (this.config.simulateExhaustion && Math.random() < this.config.exhaustionProbability) {
counter.count = this.config.limit;
}
counter.count++;
this.counters.set(key, counter);
const remaining = Math.max(0, this.config.limit - counter.count);
const allowed = counter.count <= this.config.limit;
const resetTimestamp = Math.floor(counter.resetTime / 1000);
const headers = {
'X-Rate-Limit-Limit': String(this.config.limit),
'X-Rate-Limit-Remaining': String(remaining),
'X-Rate-Limit-Reset': String(resetTimestamp),
};
// Add warning headers when approaching limit
if (this.config.warningThreshold &&
counter.count / this.config.limit >= this.config.warningThreshold) {
headers['X-Rate-Limit-Warning'] = `Approaching rate limit: ${remaining} requests remaining`;
}
// Add retry-after header when rate limited
if (!allowed) {
const retryAfter = Math.ceil((counter.resetTime - now) / 1000);
headers['Retry-After'] = String(retryAfter);
}
return {
allowed,
remaining,
limit: this.config.limit,
reset: resetTimestamp,
headers,
};
}
reset(key = 'default') {
this.counters.delete(key);
}
resetAll() {
this.counters.clear();
}
// Simulate different rate limit scenarios
simulateScenario(scenario, key = 'default') {
const now = Date.now();
const resetTime = now + this.config.window * 1000;
switch (scenario) {
case 'normal':
this.counters.set(key, { count: Math.floor(this.config.limit * 0.3), resetTime });
break;
case 'warning':
this.counters.set(key, { count: Math.floor(this.config.limit * 0.85), resetTime });
break;
case 'exhausted':
this.counters.set(key, { count: this.config.limit + 1, resetTime });
break;
case 'recovering':
this.counters.set(key, { count: this.config.limit - 10, resetTime });
break;
}
}
}
//# sourceMappingURL=rate-limiter.js.map