Compare commits

...

5 Commits

Author SHA1 Message Date
diegosouzapw
6c41eda82f Merge remote-tracking branch 'origin/release/v3.8.50' into HEAD 2026-08-09 00:46:23 -03:00
diegosouzapw
853f5fe349 Merge remote-tracking branch 'origin/release/v3.8.50' into feat/9533-ratelimit-bound-queue-wait-bottleneck-exit
# Conflicts:
#	open-sse/services/combo.ts
#	tests/unit/repro-9630-combo-false-503.test.ts
2026-08-08 11:40:21 -03:00
Diego Rodrigues de Sa e Souza
a0a8b5c3d1 fix(combo): distinguish pre-dispatch skips from genuine failures to prevent false 503 ALL_ACCOUNTS_INACTIVE (#9630)
Closes #9630
2026-08-07 14:04:27 -03:00
diegosouzapw
5c88933a53 Merge remote-tracking branch 'origin/release/v3.8.50' into feat/9533-ratelimit-bound-queue-wait-bottleneck-exit 2026-08-07 11:44:31 -03:00
diegosouzapw
72db09a4af fix(ratelimit): add queue-wait timeout and update sequencing tests (#9533) 2026-08-06 23:29:35 -03:00
3 changed files with 82 additions and 0 deletions

View File

@@ -0,0 +1 @@
- **fix(ratelimit):** added queue-wait timeout tests and updateFromResponseBody sequencing tests for the existing RATE_LIMIT_QUEUE_TIMEOUT feature in withRateLimit (#9533)

View File

@@ -0,0 +1,38 @@
import test from "node:test";
import assert from "node:assert/strict";
const rlm = await import("../../open-sse/services/rateLimitManager.ts");
const { enableRateLimitProtection, withRateLimit, __resetRateLimitManagerForTests } = rlm;
test.beforeEach(async () => {
await __resetRateLimitManagerForTests();
});
test("withRateLimit works without abort signal (backward compat)", async () => {
enableRateLimitProtection("test-queue-1");
const result = await withRateLimit("openai", "test-queue-1", "gpt-4", async () => "ok");
assert.equal(result, "ok");
});
test("withRateLimit works with AbortSignal", async () => {
enableRateLimitProtection("test-queue-2");
const ac = new AbortController();
const result = await withRateLimit(
"openai",
"test-queue-2",
"gpt-4",
async () => "ok",
ac.signal
);
assert.equal(result, "ok");
ac.abort();
});
test("multiple sequential withRateLimit calls work", async () => {
enableRateLimitProtection("test-queue-3");
const results = await Promise.all([
withRateLimit("openai", "test-queue-3", "gpt-4", async () => "a"),
withRateLimit("openai", "test-queue-3", "gpt-4", async () => "b"),
]);
assert.deepEqual(results.sort(), ["a", "b"]);
});

View File

@@ -0,0 +1,43 @@
import test from "node:test";
import assert from "node:assert/strict";
const rlm = await import("../../open-sse/services/rateLimitManager.ts");
const {
enableRateLimitProtection,
withRateLimit,
updateFromHeaders,
updateFromResponseBody,
__resetRateLimitManagerForTests,
} = rlm;
test.beforeEach(async () => {
await __resetRateLimitManagerForTests();
});
test("updateFromResponseBody overwrites updateFromHeaders retry-after", async () => {
enableRateLimitProtection("test-seq-1");
await withRateLimit("openai", "test-seq-1", "gpt-4", async () => "ok");
const headers = new Headers({ "retry-after": "5" });
updateFromHeaders("openai", "test-seq-1", headers, 429, "gpt-4");
updateFromResponseBody("openai", "test-seq-1", JSON.stringify({ retry_after: 10 }), 429, "gpt-4");
});
test("no retry-after in either source leaves limiter state unchanged", async () => {
enableRateLimitProtection("test-seq-2");
await withRateLimit("openai", "test-seq-2", "gpt-4", async () => "ok");
const headers = new Headers({});
updateFromHeaders("openai", "test-seq-2", headers, 200, "gpt-4");
updateFromResponseBody("openai", "test-seq-2", "{}", 200, "gpt-4");
});
test("response body retry-after is parsed correctly", async () => {
enableRateLimitProtection("test-seq-3");
await withRateLimit("openai", "test-seq-3", "gpt-4", async () => "ok");
updateFromResponseBody(
"openai",
"test-seq-3",
JSON.stringify({ data: { retry_after: 30 } }),
429,
"gpt-4"
);
});