diff --git a/.env.example b/.env.example index 69e1c1a3b0..d05df17a18 100644 --- a/.env.example +++ b/.env.example @@ -2204,9 +2204,9 @@ APP_LOG_TO_FILE=true # Also configurable from Dashboard > Settings > Feature Flags. # OMNIROUTE_CONTROL_PLANE_PROXY_DIRECT_FALLBACK=false -# Rate limit maximum wait time before failing a request (ms). Default: 15000 (15s) +# Rate limit maximum wait time before failing a request (ms). Default: 30000 (30s) # Used by: open-sse/services/rateLimitManager.ts -# RATE_LIMIT_MAX_WAIT_MS=15000 +# RATE_LIMIT_MAX_WAIT_MS=30000 # Limiter-managed execution backstop (Bottleneck `expiration`): bounds a job's # post-dispatch execution, never queue wait. Must stay ABOVE upstream diff --git a/docs/reference/ENVIRONMENT.md b/docs/reference/ENVIRONMENT.md index 0d01b66a54..d7ab660823 100644 --- a/docs/reference/ENVIRONMENT.md +++ b/docs/reference/ENVIRONMENT.md @@ -1116,7 +1116,7 @@ Anthropic-compatible provider instead. | `PROXY_AUTO_REMOVE_AFTER` | `3` | `src/lib/proxyHealth/scheduler.ts` | Consecutive failures before the scheduler auto-removes a proxy (when `PROXY_AUTO_REMOVE=true`). | | `PROXY_AUTO_DISABLE` | `false` | `src/lib/proxyHealth/scheduler.ts` | Set `true` to let the scheduler soft-disable (status `dead`, never deleted) a proxy after repeated consecutive failures, instead of removing it. Non-destructive alternative to `PROXY_AUTO_REMOVE`: the proxy drops out of pool/rotation resolution immediately (the alive-status filter used by scope-pool resolution already excludes it) and is automatically re-activated once it starts passing probes again. Shares the `PROXY_AUTO_REMOVE_AFTER` threshold. If both flags are `true`, `PROXY_AUTO_REMOVE` wins. | | `OMNIROUTE_CONTROL_PLANE_PROXY_DIRECT_FALLBACK` | `false` | `src/shared/constants/featureFlagDefinitions.ts` | Allow OAuth and provider validation flows to bypass a pinned proxy and connect directly when proxy reachability pre-checks fail. Effective precedence is Feature Flags DB override > env var > default. | -| `RATE_LIMIT_MAX_WAIT_MS` | `15000` (15s) | `open-sse/services/rateLimitManager.ts` | Max time to wait on a 429 before failing the request. | +| `RATE_LIMIT_MAX_WAIT_MS` | `30000` (30s) | `open-sse/services/rateLimitManager.ts` | Max time to wait on a 429 before failing the request. | | `RATE_LIMIT_EXECUTION_MAX_WAIT_MS` | `600000` (10 min) | `open-sse/services/rateLimitManager.ts` | Ceiling for how long an admitted request may stay in execution before its rate-limit reservation expires — decoupled from the queue-wait budget so slow fetch-start on non-incremental gateways does not time out (#12027). | | `RATE_LIMIT_MAX_QUEUE_DEPTH` | `0` (disabled) | `open-sse/services/rateLimitManager.ts` | Queue admission cap: reject with a 429 `queue_full` once this many requests are already queued. `0` = unbounded (default). | | `RATE_LIMIT_AUTO_ENABLE` | _(unset)_ | `open-sse/services/rateLimitManager.ts` | Force the auto-enable rate limit safety net on/off regardless of the persisted Dashboard setting. Accepts `true`/`1`/`on` to force on, `false`/`0`/`off` to force off. | diff --git a/src/lib/resilience/settings.ts b/src/lib/resilience/settings.ts index ddb67220a5..a76de7b65a 100644 --- a/src/lib/resilience/settings.ts +++ b/src/lib/resilience/settings.ts @@ -43,8 +43,8 @@ export type { } from "./settings/types"; export const DEFAULT_REQUEST_QUEUE_MAX_WAIT_MS = (() => { - const parsed = Number(process.env.RATE_LIMIT_MAX_WAIT_MS || "15000"); - return Number.isFinite(parsed) && parsed > 0 ? Math.trunc(parsed) : 15000; + const parsed = Number(process.env.RATE_LIMIT_MAX_WAIT_MS || "30000"); + return Number.isFinite(parsed) && parsed > 0 ? Math.trunc(parsed) : 30000; })(); // Limiter-managed execution backstop (Bottleneck `expiration`). Deliberately diff --git a/tests/unit/ratelimit-admission-control-6593.test.ts b/tests/unit/ratelimit-admission-control-6593.test.ts index cdad084a32..060b6d53b0 100644 --- a/tests/unit/ratelimit-admission-control-6593.test.ts +++ b/tests/unit/ratelimit-admission-control-6593.test.ts @@ -177,10 +177,10 @@ test("#6593 withRateLimit: default maxQueueDepth=0 preserves unbounded-queue beh // --- Default maxWaitMs ---------------------------------------------------- -test("#6593 DEFAULT_REQUEST_QUEUE_MAX_WAIT_MS is 15s absent RATE_LIMIT_MAX_WAIT_MS", () => { +test("#6593 DEFAULT_REQUEST_QUEUE_MAX_WAIT_MS is 30s absent RATE_LIMIT_MAX_WAIT_MS", () => { assert.equal(process.env.RATE_LIMIT_MAX_WAIT_MS, undefined); - assert.equal(resilienceSettings.DEFAULT_REQUEST_QUEUE_MAX_WAIT_MS, 15000); - assert.equal(resilienceSettings.DEFAULT_RESILIENCE_SETTINGS.requestQueue.maxWaitMs, 15000); + assert.equal(resilienceSettings.DEFAULT_REQUEST_QUEUE_MAX_WAIT_MS, 30000); + assert.equal(resilienceSettings.DEFAULT_RESILIENCE_SETTINGS.requestQueue.maxWaitMs, 30000); }); test("requestQueue.executionMaxWaitMs defaults to a 10-minute backstop, separate from maxWaitMs", () => {