Captures consume + reset call arguments verbatim via consumeCalls and resetCalls accessors. Uses local IRateLimit type alias (no core-shared dep) following the recording-job-queue pattern. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
61 lines
1.4 KiB
TypeScript
61 lines
1.4 KiB
TypeScript
// Local type aliases matching the contracts in @repo/core-shared/rate-limit.
|
|
// Kept inline to avoid a build-graph cycle between core-testing and core-shared
|
|
// (mirrors the recording-job-queue pattern).
|
|
|
|
type RateLimitDecision = {
|
|
allowed: boolean;
|
|
remaining: number;
|
|
resetAt: Date;
|
|
};
|
|
|
|
interface IRateLimit {
|
|
consume(
|
|
budgetName: string,
|
|
key: string,
|
|
weight?: number,
|
|
): Promise<RateLimitDecision>;
|
|
reset(budgetName: string, key: string): Promise<void>;
|
|
}
|
|
|
|
export type RecordedConsumeCall = {
|
|
budgetName: string;
|
|
key: string;
|
|
weight: number | undefined;
|
|
};
|
|
|
|
export type RecordedResetCall = {
|
|
budgetName: string;
|
|
key: string;
|
|
};
|
|
|
|
const EPOCH = new Date(0);
|
|
|
|
export class RecordingRateLimit implements IRateLimit {
|
|
readonly consumeCalls: RecordedConsumeCall[] = [];
|
|
readonly resetCalls: RecordedResetCall[] = [];
|
|
|
|
private _decision: RateLimitDecision = {
|
|
allowed: true,
|
|
remaining: Infinity,
|
|
resetAt: EPOCH,
|
|
};
|
|
|
|
withDecision(decision: RateLimitDecision): this {
|
|
this._decision = decision;
|
|
return this;
|
|
}
|
|
|
|
async consume(
|
|
budgetName: string,
|
|
key: string,
|
|
weight?: number,
|
|
): Promise<RateLimitDecision> {
|
|
this.consumeCalls.push({ budgetName, key, weight });
|
|
return this._decision;
|
|
}
|
|
|
|
async reset(budgetName: string, key: string): Promise<void> {
|
|
this.resetCalls.push({ budgetName, key });
|
|
}
|
|
}
|