Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **feat(providers):** allow overriding the rate-limit queue wait timeout (`maxWaitMs`) per connection, alongside the existing `rpm`/`tpm`/`tpd`/`minTime`/`maxConcurrent` overrides — a single slow provider no longer has to lower the global wait budget for every other provider (#11251)
28 changes: 20 additions & 8 deletions open-sse/services/rateLimitManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,28 +140,40 @@ function isAutoEnableActive(settings: RequestQueueSettings): boolean {
const EFFECTIVELY_INFINITE = Number.MAX_SAFE_INTEGER;
const EFFECTIVELY_INFINITE_CONCURRENCY = 1000;

// Shared override-resolution rule for every per-connection rate-limit field:
// a positive override wins, 0 or missing falls through to `fallback`.
function resolveOverride(override: number | undefined | null, fallback: number): number {
return typeof override === "number" && override > 0 ? override : fallback;
}

// Resolve an RPM override. 0 or missing means "infinite" (no rate cap).
function resolveRpm(override: number | undefined | null): number {
return typeof override === "number" && override > 0 ? override : EFFECTIVELY_INFINITE;
return resolveOverride(override, EFFECTIVELY_INFINITE);
}

// Resolve a minTime override. 0 or missing means "no minimum gap".
function resolveMinTime(override: number | undefined | null): number {
return typeof override === "number" && override > 0 ? override : 0;
return resolveOverride(override, 0);
}

// Resolve a maxConcurrent override. 0 or missing means "effectively infinite".
function resolveMaxConcurrent(override: number | undefined | null): number {
return typeof override === "number" && override > 0 ? override : EFFECTIVELY_INFINITE_CONCURRENCY;
return resolveOverride(override, EFFECTIVELY_INFINITE_CONCURRENCY);
}

export function resolveRequestQueueMaxWaitMs(
provider: string,
configuredMaxWaitMs: number = currentRequestQueueSettings.maxWaitMs
configuredMaxWaitMs: number = currentRequestQueueSettings.maxWaitMs,
connectionId?: string
): number {
return provider.trim().toLowerCase() === "zai-web"
? Math.max(configuredMaxWaitMs, ZAI_WEB_REQUEST_QUEUE_MAX_WAIT_MS)
: configuredMaxWaitMs;
const legacyDefault =
provider.trim().toLowerCase() === "zai-web"
? Math.max(configuredMaxWaitMs, ZAI_WEB_REQUEST_QUEUE_MAX_WAIT_MS)
: configuredMaxWaitMs;
const override = connectionId
? connectionRateLimitOverrides.get(connectionId)?.maxWaitMs
: undefined;
return resolveOverride(override, legacyDefault);
}

function buildLimiterDefaults() {
Expand Down Expand Up @@ -546,7 +558,7 @@ export async function withRateLimit(provider, connectionId, model, fn, signal =

// Proactive sliding-window fallback for header-less providers with a declared cap
// (Fase 8.2). No-op unless PROVIDER_DEFAULT_RATE_LIMITS has an entry for `provider`.
const maxWaitMs = resolveRequestQueueMaxWaitMs(provider);
const maxWaitMs = resolveRequestQueueMaxWaitMs(provider, undefined, connectionId);
await awaitProviderDefaultSlot(provider, connectionId, signal, maxWaitMs);

const limiter = getLimiter(provider, connectionId, model);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ export default function EditConnectionModal({
tpm: "",
tpd: "",
minTime: "",
maxWaitMs: "",
rateLimitMaxConcurrent: "",
apiKey: "",
healthCheckInterval: 60,
Expand Down Expand Up @@ -312,6 +313,10 @@ export default function EditConnectionModal({
connection.rateLimitOverrides?.minTime != null
? String(connection.rateLimitOverrides.minTime)
: "",
maxWaitMs:
connection.rateLimitOverrides?.maxWaitMs != null
? String(connection.rateLimitOverrides.maxWaitMs)
: "",
rateLimitMaxConcurrent:
connection.rateLimitOverrides?.maxConcurrent != null
? String(connection.rateLimitOverrides.maxConcurrent)
Expand Down Expand Up @@ -528,6 +533,7 @@ export default function EditConnectionModal({
if (formData.tpm.trim()) overrides.tpm = Number(formData.tpm);
if (formData.tpd.trim()) overrides.tpd = Number(formData.tpd);
if (formData.minTime.trim()) overrides.minTime = Number(formData.minTime);
if (formData.maxWaitMs.trim()) overrides.maxWaitMs = Number(formData.maxWaitMs);
if (formData.rateLimitMaxConcurrent.trim())
overrides.maxConcurrent = Number(formData.rateLimitMaxConcurrent);
updates.rateLimitOverrides = Object.keys(overrides).length > 0 ? overrides : null;
Expand Down Expand Up @@ -1224,6 +1230,15 @@ export default function EditConnectionModal({
placeholder={t("inherit")}
hint={t("rateLimitOverridesMinTimeHint")}
/>
<Input
label={t("rateLimitOverridesMaxWaitMsLabel")}
type="number"
min={0}
value={formData.maxWaitMs}
onChange={(e) => setFormData({ ...formData, maxWaitMs: e.target.value })}
placeholder={t("inherit")}
hint={t("rateLimitOverridesMaxWaitMsHint")}
/>
<Input
label={t("rateLimitOverridesMaxConcurrentLabel")}
type="number"
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/messages/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -5834,6 +5834,8 @@
"rateLimitOverridesSection": "تجاوزات حد المعدل",
"rateLimitOverridesMaxConcurrentHint": "تجاوز الحد الأقصى للطلبات المتزامنة لهذا الاتصال. يتجاوز الحد الأقصى على مستوى الحساب.",
"rateLimitOverridesMaxConcurrentLabel": "الحد الأقصى للتزامن (حد المعدل)",
"rateLimitOverridesMaxWaitMsHint": "__MISSING__:Maximum time (ms) a request may wait for a rate-limit slot before failing. Overrides the global Resilience setting for this connection only.",
"rateLimitOverridesMaxWaitMsLabel": "__MISSING__:Max Queue Wait (ms)",
"rateLimitOverridesMinTimeHint": "الحد الأدنى للوقت (مللي ثانية) بين الطلبات. يتجاوز تأخير محدد المعدل الافتراضي.",
"rateLimitOverridesMinTimeLabel": "الحد الأدنى للفاصل الزمني (مللي ثانية)",
"rateLimitOverridesRpmHint": "الحد الأقصى للطلبات في الدقيقة لهذا الاتصال. يتجاوز القيمة الافتراضية للمزود.",
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/messages/az.json
Original file line number Diff line number Diff line change
Expand Up @@ -5834,6 +5834,8 @@
"rateLimitOverridesSection": "Sorğu Limiti Üstələmələri",
"rateLimitOverridesMaxConcurrentHint": "Bu bağlantı üçün maksimum eyni vaxtda olan sorğuların üstələnməsi. Hesab səviyyəsindəki limiti üstələyir.",
"rateLimitOverridesMaxConcurrentLabel": "Maksimum Eyni Vaxtda (Sorğu Limiti)",
"rateLimitOverridesMaxWaitMsHint": "__MISSING__:Maximum time (ms) a request may wait for a rate-limit slot before failing. Overrides the global Resilience setting for this connection only.",
"rateLimitOverridesMaxWaitMsLabel": "__MISSING__:Max Queue Wait (ms)",
"rateLimitOverridesMinTimeHint": "Sorğular arasındakı minimum vaxt (ms). Standart sorğu limiti gecikməsini üstələyir.",
"rateLimitOverridesMinTimeLabel": "Min İnterval (ms)",
"rateLimitOverridesRpmHint": "Bu bağlantı üçün dəqiqədə maksimum sorğu sayı. Provayderin standart dəyərini üstələyir.",
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/messages/bg.json
Original file line number Diff line number Diff line change
Expand Up @@ -5834,6 +5834,8 @@
"rateLimitOverridesSection": "Предефиниране на ограниченията на скоростта",
"rateLimitOverridesMaxConcurrentHint": "Предефиниране на максималния брой едновременни заявки за тази връзка. Предефинира ограничението на ниво акаунт.",
"rateLimitOverridesMaxConcurrentLabel": "Макс. едновременни (Ограничение на скоростта)",
"rateLimitOverridesMaxWaitMsHint": "__MISSING__:Maximum time (ms) a request may wait for a rate-limit slot before failing. Overrides the global Resilience setting for this connection only.",
"rateLimitOverridesMaxWaitMsLabel": "__MISSING__:Max Queue Wait (ms)",
"rateLimitOverridesMinTimeHint": "Минимално време (ms) между заявките. Предефинира закъснението по подразбиране на ограничителя на скоростта.",
"rateLimitOverridesMinTimeLabel": "Мин. интервал (ms)",
"rateLimitOverridesRpmHint": "Максимален брой заявки в минута за тази връзка. Предефинира стойността по подразбиране на доставчика.",
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/messages/bn.json
Original file line number Diff line number Diff line change
Expand Up @@ -5834,6 +5834,8 @@
"rateLimitOverridesSection": "রেট লিমিট ওভাররাইড",
"rateLimitOverridesMaxConcurrentHint": "এই সংযোগের জন্য সর্বোচ্চ সমবর্তী অনুরোধের ওভাররাইড। অ্যাকাউন্ট-স্তরের সীমা ওভাররাইড করে।",
"rateLimitOverridesMaxConcurrentLabel": "সর্বোচ্চ সমবর্তী (রেট লিমিট)",
"rateLimitOverridesMaxWaitMsHint": "__MISSING__:Maximum time (ms) a request may wait for a rate-limit slot before failing. Overrides the global Resilience setting for this connection only.",
"rateLimitOverridesMaxWaitMsLabel": "__MISSING__:Max Queue Wait (ms)",
"rateLimitOverridesMinTimeHint": "অনুরোধগুলোর মধ্যে ন্যূনতম সময় (ms)। ডিফল্ট রেট লিমিটারের বিলম্ব ওভাররাইড করে।",
"rateLimitOverridesMinTimeLabel": "ন্যূনতম ব্যবধান (ms)",
"rateLimitOverridesRpmHint": "এই সংযোগের জন্য প্রতি মিনিটে সর্বোচ্চ অনুরোধ। প্রদানকারীর ডিফল্ট ওভাররাইড করে।",
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/messages/cs.json
Original file line number Diff line number Diff line change
Expand Up @@ -5834,6 +5834,8 @@
"rateLimitOverridesSection": "Přepsání limitů četnosti",
"rateLimitOverridesMaxConcurrentHint": "Přepsání maximálního počtu souběžných požadavků pro toto připojení. Přepisuje limit na úrovni účtu.",
"rateLimitOverridesMaxConcurrentLabel": "Max. souběžných (limit četnosti)",
"rateLimitOverridesMaxWaitMsHint": "__MISSING__:Maximum time (ms) a request may wait for a rate-limit slot before failing. Overrides the global Resilience setting for this connection only.",
"rateLimitOverridesMaxWaitMsLabel": "__MISSING__:Max Queue Wait (ms)",
"rateLimitOverridesMinTimeHint": "Minimální doba (ms) mezi požadavky. Přepisuje výchozí prodlevu omezovače četnosti.",
"rateLimitOverridesMinTimeLabel": "Min. interval (ms)",
"rateLimitOverridesRpmHint": "Maximální počet požadavků za minutu pro toto připojení. Přepisuje výchozí hodnotu poskytovatele.",
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/messages/da.json
Original file line number Diff line number Diff line change
Expand Up @@ -5834,6 +5834,8 @@
"rateLimitOverridesSection": "Tilsidesættelser af hastighedsbegrænsning",
"rateLimitOverridesMaxConcurrentHint": "Tilsidesættelse af maks. samtidige anmodninger for denne forbindelse. Tilsidesætter loftet på kontoniveau.",
"rateLimitOverridesMaxConcurrentLabel": "Maks. samtidige (hastighedsbegrænsning)",
"rateLimitOverridesMaxWaitMsHint": "__MISSING__:Maximum time (ms) a request may wait for a rate-limit slot before failing. Overrides the global Resilience setting for this connection only.",
"rateLimitOverridesMaxWaitMsLabel": "__MISSING__:Max Queue Wait (ms)",
"rateLimitOverridesMinTimeHint": "Minimumstid (ms) mellem anmodninger. Tilsidesætter standardforsinkelsen for hastighedsbegrænseren.",
"rateLimitOverridesMinTimeLabel": "Min. interval (ms)",
"rateLimitOverridesRpmHint": "Maks. anmodninger pr. minut for denne forbindelse. Tilsidesætter udbyderens standard.",
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/messages/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -5834,6 +5834,8 @@
"rateLimitOverridesSection": "Rate-Limit-Überschreibungen",
"rateLimitOverridesMaxConcurrentHint": "Überschreibung der maximalen gleichzeitigen Anfragen für diese Verbindung. Überschreibt die Obergrenze auf Kontoebene.",
"rateLimitOverridesMaxConcurrentLabel": "Max. gleichzeitig (Rate-Limit)",
"rateLimitOverridesMaxWaitMsHint": "__MISSING__:Maximum time (ms) a request may wait for a rate-limit slot before failing. Overrides the global Resilience setting for this connection only.",
"rateLimitOverridesMaxWaitMsLabel": "__MISSING__:Max Queue Wait (ms)",
"rateLimitOverridesMinTimeHint": "Mindestzeit (ms) zwischen Anfragen. Überschreibt die standardmäßige Rate-Limiter-Verzögerung.",
"rateLimitOverridesMinTimeLabel": "Min. Intervall (ms)",
"rateLimitOverridesRpmHint": "Maximale Anfragen pro Minute für diese Verbindung. Überschreibt den Provider-Standard.",
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -5855,6 +5855,8 @@
"rateLimitOverridesSection": "Rate Limit Overrides",
"rateLimitOverridesMaxConcurrentHint": "Max concurrent requests override for this connection. Overrides the account-level cap.",
"rateLimitOverridesMaxConcurrentLabel": "Max Concurrent (Rate Limit)",
"rateLimitOverridesMaxWaitMsHint": "Maximum time (ms) a request may wait for a rate-limit slot before failing. Overrides the global Resilience setting for this connection only.",
"rateLimitOverridesMaxWaitMsLabel": "Max Queue Wait (ms)",
"rateLimitOverridesMinTimeHint": "Minimum time (ms) between requests. Overrides the default rate limiter delay.",
"rateLimitOverridesMinTimeLabel": "Min Interval (ms)",
"rateLimitOverridesRpmHint": "Max requests per minute for this connection. Overrides the provider default.",
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/messages/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -5834,6 +5834,8 @@
"rateLimitOverridesSection": "Rate Limit Overrides",
"rateLimitOverridesMaxConcurrentHint": "Max concurrent requests override for this connection. Overrides the account-level cap.",
"rateLimitOverridesMaxConcurrentLabel": "Max Concurrent (Rate Limit)",
"rateLimitOverridesMaxWaitMsHint": "__MISSING__:Maximum time (ms) a request may wait for a rate-limit slot before failing. Overrides the global Resilience setting for this connection only.",
"rateLimitOverridesMaxWaitMsLabel": "__MISSING__:Max Queue Wait (ms)",
"rateLimitOverridesMinTimeHint": "Minimum time (ms) between requests. Overrides the default rate limiter delay.",
"rateLimitOverridesMinTimeLabel": "Min Interval (ms)",
"rateLimitOverridesRpmHint": "Max requests per minute for this connection. Overrides the provider default.",
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/messages/fa.json
Original file line number Diff line number Diff line change
Expand Up @@ -5834,6 +5834,8 @@
"rateLimitOverridesSection": "جایگزینی‌های محدودیت نرخ",
"rateLimitOverridesMaxConcurrentHint": "جایگزینی حداکثر درخواست‌های همزمان برای این اتصال. سقف سطح حساب را لغو می‌کند.",
"rateLimitOverridesMaxConcurrentLabel": "حداکثر همزمان (محدودیت نرخ)",
"rateLimitOverridesMaxWaitMsHint": "__MISSING__:Maximum time (ms) a request may wait for a rate-limit slot before failing. Overrides the global Resilience setting for this connection only.",
"rateLimitOverridesMaxWaitMsLabel": "__MISSING__:Max Queue Wait (ms)",
"rateLimitOverridesMinTimeHint": "حداقل زمان (میلی‌ثانیه) بین درخواست‌ها. تاخیر پیش‌فرض محدودکننده نرخ را لغو می‌کند.",
"rateLimitOverridesMinTimeLabel": "حداقل فاصله (میلی‌ثانیه)",
"rateLimitOverridesRpmHint": "حداکثر درخواست در دقیقه برای این اتصال. مقدار پیش‌فرض ارائه‌دهنده را لغو می‌کند.",
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/messages/fi.json
Original file line number Diff line number Diff line change
Expand Up @@ -5834,6 +5834,8 @@
"rateLimitOverridesSection": "Pyyntörajojen ohitukset",
"rateLimitOverridesMaxConcurrentHint": "Samanaikaisten pyyntöjen enimmäismäärän ohitus tälle yhteydelle. Ohittaa tilitason rajoituksen.",
"rateLimitOverridesMaxConcurrentLabel": "Samanaikaisia enintään (pyyntöraja)",
"rateLimitOverridesMaxWaitMsHint": "__MISSING__:Maximum time (ms) a request may wait for a rate-limit slot before failing. Overrides the global Resilience setting for this connection only.",
"rateLimitOverridesMaxWaitMsLabel": "__MISSING__:Max Queue Wait (ms)",
"rateLimitOverridesMinTimeHint": "Vähimmäisaika (ms) pyyntöjen välillä. Ohittaa oletusarvoisen pyyntörajoittimen viiveen.",
"rateLimitOverridesMinTimeLabel": "Vähimmäisväli (ms)",
"rateLimitOverridesRpmHint": "Pyyntöjen enimmäismäärä minuutissa tälle yhteydelle. Ohittaa tarjoajan oletusarvon.",
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/messages/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -5834,6 +5834,8 @@
"rateLimitOverridesSection": "Surcharges des limites de débit",
"rateLimitOverridesMaxConcurrentHint": "Surcharge des requêtes simultanées max pour cette connexion. Remplace la limite au niveau du compte.",
"rateLimitOverridesMaxConcurrentLabel": "Nombre max de requêtes simultanées (limite de débit)",
"rateLimitOverridesMaxWaitMsHint": "__MISSING__:Maximum time (ms) a request may wait for a rate-limit slot before failing. Overrides the global Resilience setting for this connection only.",
"rateLimitOverridesMaxWaitMsLabel": "__MISSING__:Max Queue Wait (ms)",
"rateLimitOverridesMinTimeHint": "Temps minimum (ms) entre les requêtes. Remplace le délai par défaut du limiteur de débit.",
"rateLimitOverridesMinTimeLabel": "Intervalle min (ms)",
"rateLimitOverridesRpmHint": "Requêtes max par minute pour cette connexion. Remplace la valeur par défaut du fournisseur.",
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/messages/gu.json
Original file line number Diff line number Diff line change
Expand Up @@ -5834,6 +5834,8 @@
"rateLimitOverridesSection": "રેટ લિમિટ ઓવરરાઇડ્સ",
"rateLimitOverridesMaxConcurrentHint": "આ કનેક્શન માટે મહત્તમ સમવર્તી વિનંતીઓ ઓવરરાઇડ. એકાઉન્ટ-સ્તરની મર્યાદાને ઓવરરાઇડ કરે છે.",
"rateLimitOverridesMaxConcurrentLabel": "મહત્તમ સમવર્તી (રેટ લિમિટ)",
"rateLimitOverridesMaxWaitMsHint": "__MISSING__:Maximum time (ms) a request may wait for a rate-limit slot before failing. Overrides the global Resilience setting for this connection only.",
"rateLimitOverridesMaxWaitMsLabel": "__MISSING__:Max Queue Wait (ms)",
"rateLimitOverridesMinTimeHint": "વિનંતીઓ વચ્ચેનો ન્યૂનતમ સમય (ms). ડિફૉલ્ટ રેટ લિમિટર વિલંબને ઓવરરાઇડ કરે છે.",
"rateLimitOverridesMinTimeLabel": "ન્યૂનતમ અંતરાલ (ms)",
"rateLimitOverridesRpmHint": "આ કનેક્શન માટે પ્રતિ મિનિટ મહત્તમ વિનંતીઓ. પ્રદાતા ડિફૉલ્ટને ઓવરરાઇડ કરે છે.",
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/messages/he.json
Original file line number Diff line number Diff line change
Expand Up @@ -5834,6 +5834,8 @@
"rateLimitOverridesSection": "עקיפת מגבלות קצב",
"rateLimitOverridesMaxConcurrentHint": "עקיפת מספר הבקשות המקביליות המרבי עבור חיבור זה. עוקף את המגבלה ברמת החשבון.",
"rateLimitOverridesMaxConcurrentLabel": "מקסימום בקשות מקביליות (מגבלת קצב)",
"rateLimitOverridesMaxWaitMsHint": "__MISSING__:Maximum time (ms) a request may wait for a rate-limit slot before failing. Overrides the global Resilience setting for this connection only.",
"rateLimitOverridesMaxWaitMsLabel": "__MISSING__:Max Queue Wait (ms)",
"rateLimitOverridesMinTimeHint": "זמן מינימלי (במילישניות) בין בקשות. עוקף את השהיית מגביל הקצב כברירת מחדל.",
"rateLimitOverridesMinTimeLabel": "מרווח מינימלי (מילישניות)",
"rateLimitOverridesRpmHint": "מקסימום בקשות לדקה עבור חיבור זה. עוקף את ברירת המחדל של הספק.",
Expand Down
Loading
Loading