-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Use monotonic clock for rate limiting #8456
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1098,9 +1098,9 @@ describe("Cline", () => { | |
| await parentIterator.next() | ||
|
|
||
| // Simulate time passing (more than rate limit) | ||
| const originalDateNow = Date.now | ||
| const mockTime = Date.now() + (mockApiConfig.rateLimitSeconds + 1) * 1000 | ||
| Date.now = vi.fn(() => mockTime) | ||
| const originalPerformanceNow = performance.now | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When overriding performance.now here, consider wrapping the override in a try…finally block so that the original function is always restored even if the test fails. |
||
| const mockTime = performance.now() + (mockApiConfig.rateLimitSeconds + 1) * 1000 | ||
| performance.now = vi.fn(() => mockTime) | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3: Instead of reassigning performance.now directly, prefer vi.spyOn(performance, 'now').mockReturnValue(...) and restore with mockRestore(). This avoids mutating globals and plays nicer with parallel tests. |
||
| // Create a subtask after time has passed | ||
| const child = new Task({ | ||
|
|
@@ -1121,8 +1121,8 @@ describe("Cline", () => { | |
| // Verify no rate limiting was applied | ||
| expect(mockDelay).not.toHaveBeenCalled() | ||
|
|
||
| // Restore Date.now | ||
| Date.now = originalDateNow | ||
| // Restore performance.now | ||
| performance.now = originalPerformanceNow | ||
| }) | ||
|
|
||
| it("should share rate limiting across multiple subtasks", async () => { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2: Now that this uses a monotonic clock, consider extracting this remaining-delay calculation into a small helper (with unit tests) to make the ms→s conversion and clamping intent explicit. For example: min(rateLimitSeconds, ceil(max(0, remainingMs)/1000)). This helps avoid future regressions and clarifies that lastGlobalApiRequestTime and now are performance.now() values (ms, monotonic).