Files
Claude-Code-Workflow/ccw/src/core/services/rate-limiter.ts
catlog22 4344e79e68 Add benchmark results for fast3 and fast4, implement KeepAliveLspBridge, and add tests for staged strategies
- Added new benchmark result files: compare_2026-02-09_score_fast3.json and compare_2026-02-09_score_fast4.json.
- Implemented KeepAliveLspBridge to maintain a persistent LSP connection across multiple queries, improving performance.
- Created unit tests for staged clustering strategies in test_staged_stage3_fast_strategies.py, ensuring correct behavior of score and dir_rr strategies.
2026-02-09 20:45:29 +08:00

50 lines
1.4 KiB
TypeScript

export interface RateLimitResult {
ok: boolean;
remaining: number;
resetAt: number;
}
interface BucketState {
tokens: number;
resetAt: number;
}
/**
* Simple fixed-window token bucket (in-memory).
* Good enough for local dashboard usage; not suitable for multi-process deployments.
*/
export class RateLimiter {
private buckets = new Map<string, BucketState>();
private limit: number;
private windowMs: number;
constructor(opts: { limit: number; windowMs: number }) {
this.limit = Math.max(0, opts.limit);
this.windowMs = Math.max(1, opts.windowMs);
}
consume(key: string, cost: number = 1): RateLimitResult {
const now = Date.now();
const safeCost = Math.max(0, Math.floor(cost));
const existing = this.buckets.get(key);
if (!existing || now >= existing.resetAt) {
const resetAt = now + this.windowMs;
const nextTokens = this.limit - safeCost;
const ok = nextTokens >= 0;
const tokens = ok ? nextTokens : this.limit;
this.buckets.set(key, { tokens, resetAt });
return { ok, remaining: Math.max(0, ok ? tokens : 0), resetAt };
}
const nextTokens = existing.tokens - safeCost;
if (nextTokens < 0) {
return { ok: false, remaining: Math.max(0, existing.tokens), resetAt: existing.resetAt };
}
existing.tokens = nextTokens;
return { ok: true, remaining: nextTokens, resetAt: existing.resetAt };
}
}