okta-mcp-server
Version:
Model Context Protocol (MCP) server for Okta API operations with support for bulk operations and caching
92 lines • 2.9 kB
JavaScript
/**
* Rolling window implementation for tracking circuit breaker metrics
*/
export class RollingWindowImpl {
buckets = [];
windowSize;
bucketSize;
numberOfBuckets;
constructor(windowSizeMs = 60000, numberOfBuckets = 10) {
this.windowSize = windowSizeMs;
this.numberOfBuckets = numberOfBuckets;
this.bucketSize = Math.floor(windowSizeMs / numberOfBuckets);
}
recordSuccess(timestamp = Date.now()) {
this.record('success', timestamp);
}
recordFailure(timestamp = Date.now()) {
this.record('failure', timestamp);
}
recordTimeout(timestamp = Date.now()) {
this.record('timeout', timestamp);
}
recordRejection(timestamp = Date.now()) {
this.record('rejected', timestamp);
}
getCounts() {
this.removeOldBuckets();
const counts = this.buckets.reduce((acc, bucket) => {
acc.success += bucket.success;
acc.failure += bucket.failure;
acc.timeout += bucket.timeout;
acc.rejected += bucket.rejected;
return acc;
}, { success: 0, failure: 0, timeout: 0, rejected: 0 });
const total = counts.success + counts.failure + counts.timeout;
const errorCount = counts.failure + counts.timeout;
const errorPercentage = total > 0 ? (errorCount / total) * 100 : 0;
return {
...counts,
total,
errorPercentage: Math.round(errorPercentage * 100) / 100,
};
}
reset() {
this.buckets = [];
}
record(type, timestamp) {
this.removeOldBuckets();
const bucketIndex = this.getBucketIndex(timestamp);
let bucket = this.buckets.find((b) => this.getBucketIndex(b.timestamp) === bucketIndex);
if (!bucket) {
bucket = {
success: 0,
failure: 0,
timeout: 0,
rejected: 0,
timestamp,
};
this.buckets.push(bucket);
this.buckets.sort((a, b) => a.timestamp - b.timestamp);
}
if (type !== 'timestamp') {
bucket[type]++;
}
}
getBucketIndex(timestamp) {
return Math.floor(timestamp / this.bucketSize);
}
removeOldBuckets() {
const now = Date.now();
const cutoff = now - this.windowSize;
this.buckets = this.buckets.filter((bucket) => bucket.timestamp > cutoff);
}
/**
* Get detailed bucket information for debugging
*/
getBuckets() {
this.removeOldBuckets();
return [...this.buckets];
}
/**
* Get window configuration
*/
getConfig() {
return {
windowSize: this.windowSize,
bucketSize: this.bucketSize,
numberOfBuckets: this.numberOfBuckets,
};
}
}
//# sourceMappingURL=rolling-window.js.map