Skip to main content

RestLimits

Struct RestLimits 

Source
pub struct RestLimits {
Show 15 fields pub max_sessions: usize, pub max_one_shot_concurrency: usize, pub max_session_call_concurrency: usize, pub max_session_call_concurrency_per_session: usize, pub max_poll_timeout: Duration, pub min_stream_poll_timeout: Duration, pub max_text_turn_duration: Duration, pub max_text_turn_output_bytes: usize, pub max_request_body_bytes: usize, pub pending_request_ttl: Duration, pub max_pending_requests_per_session: usize, pub events_channel_capacity: usize, pub idle_session_ttl: Duration, pub compatibility_ttl: Duration, pub sse_keep_alive_interval: Duration,
}
Expand description

Resource limits used by the default REST backend and route layer.

Every field has a hardcoded default (below) and can be overridden independently via a CODEX_APP_SERVER_REST_* environment variable through RestLimits::from_env / RestLimits::try_from_env. A variable that is absent falls back to the field’s default; a variable that is present but fails to parse is a hard error (RestLimitsEnvError), never a silent fallback - a malformed override that quietly reverts to the default is exactly how an operator ships a 10x-wrong limit and never notices.

FieldEnv varDefault
max_sessionsCODEX_APP_SERVER_REST_MAX_SESSIONS16
max_one_shot_concurrencyCODEX_APP_SERVER_REST_MAX_ONE_SHOT_CONCURRENCY4
max_session_call_concurrencyCODEX_APP_SERVER_REST_MAX_SESSION_CALL_CONCURRENCY64
max_session_call_concurrency_per_sessionCODEX_APP_SERVER_REST_MAX_SESSION_CALL_CONCURRENCY_PER_SESSION8
max_poll_timeoutCODEX_APP_SERVER_REST_MAX_POLL_TIMEOUT_MS30000 (30s)
min_stream_poll_timeoutCODEX_APP_SERVER_REST_MIN_STREAM_POLL_TIMEOUT_MS250
max_text_turn_durationCODEX_APP_SERVER_REST_MAX_TEXT_TURN_DURATION_MS600000 (10m)
max_text_turn_output_bytesCODEX_APP_SERVER_REST_MAX_TEXT_TURN_OUTPUT_BYTES1048576 (1 MiB)
max_request_body_bytesCODEX_APP_SERVER_REST_MAX_REQUEST_BODY_BYTES2097152 (2 MiB)
pending_request_ttlCODEX_APP_SERVER_REST_PENDING_REQUEST_TTL_MS600000 (10m)
max_pending_requests_per_sessionCODEX_APP_SERVER_REST_MAX_PENDING_REQUESTS_PER_SESSION64
events_channel_capacityCODEX_APP_SERVER_REST_EVENTS_CHANNEL_CAPACITY1024
idle_session_ttlCODEX_APP_SERVER_REST_IDLE_SESSION_TTL_MS1800000 (30m)
compatibility_ttlCODEX_APP_SERVER_REST_COMPATIBILITY_TTL_MS30000 (30s)
sse_keep_alive_intervalCODEX_APP_SERVER_REST_SSE_KEEP_ALIVE_MS15000 (15s)

Fields§

§max_sessions: usize

Maximum number of concurrently open stateful bridge sessions (POST /v1/sessions). Enforced both by a semaphore in crate::rest::CodexRestBackend and by an explicit pre-check in the route handler (so a full backend rejects before spawning a process). Env: CODEX_APP_SERVER_REST_MAX_SESSIONS. Default: 16.

§max_one_shot_concurrency: usize

Maximum number of one-shot requests (POST /v1/text-turn, POST /v1/call/{method}) running at once; each spawns its own short-lived Codex process. Env: CODEX_APP_SERVER_REST_MAX_ONE_SHOT_CONCURRENCY. Default: 4.

§max_session_call_concurrency: usize

Maximum number of in-flight POST /v1/sessions/{sessionId}/call/* calls across all sessions combined. Env: CODEX_APP_SERVER_REST_MAX_SESSION_CALL_CONCURRENCY. Default: 64.

§max_session_call_concurrency_per_session: usize

Maximum number of in-flight POST /v1/sessions/{sessionId}/call/* calls for a single session. Env: CODEX_APP_SERVER_REST_MAX_SESSION_CALL_CONCURRENCY_PER_SESSION. Default: 8.

§max_poll_timeout: Duration

Upper bound on ?timeoutMs= for both GET /v1/sessions/{sessionId}/events and GET /v1/sessions/{sessionId}/events/stream; a larger requested value is clamped down to this. Env: CODEX_APP_SERVER_REST_MAX_POLL_TIMEOUT_MS. Default: 30000 (30s).

§min_stream_poll_timeout: Duration

Lower bound on ?timeoutMs= for GET /v1/sessions/{sessionId}/events/stream only; a smaller requested value is clamped up to this.

The long-poll route has no floor on purpose (timeoutMs=0 there is a legitimate “is anything waiting right now?” non-blocking poll, paced by one HTTP round trip per call). A stream has no such pacing and no use for a zero timeout, so without a floor one request can drive an unbounded run of back-to-back backend polls. Costs real events nothing: the timeout only bounds the idle wait, so this just caps how often an idle stream emits timeout frames. Env: CODEX_APP_SERVER_REST_MIN_STREAM_POLL_TIMEOUT_MS. Default: 250.

§max_text_turn_duration: Duration

Wall-clock budget for POST /v1/text-turn to reach a terminal turn state; the turn is interrupted and the request fails with RestError::TimedOut past this point. Env: CODEX_APP_SERVER_REST_MAX_TEXT_TURN_DURATION_MS. Default: 600000 (10m).

§max_text_turn_output_bytes: usize

Byte cap on accumulated turn output for POST /v1/text-turn; the turn is interrupted and the request fails with RestError::PayloadTooLarge past this point. This is the response-byte-cap knob for the REST layer - the crate has no other hardcoded response size limit to promote (see the rest implementation notes for what was audited). Env: CODEX_APP_SERVER_REST_MAX_TEXT_TURN_OUTPUT_BYTES. Default: 1048576 (1 MiB).

§max_request_body_bytes: usize

Cap on the size of a request body, applied to every route via axum’s DefaultBodyLimit. A request whose body exceeds this is rejected with 413 Payload Too Large before any handler runs.

This is the input-side counterpart to Self::max_text_turn_output_bytes: without it, the only bound on an incoming prompt or raw-call params object is axum’s own silent 2 MiB default, which is neither documented nor tunable. Making it an explicit RestLimits field keeps the “every limit has a default and an env override” contract true on the request side too. Env: CODEX_APP_SERVER_REST_MAX_REQUEST_BODY_BYTES. Default: 2097152 (2 MiB, matching axum’s historical default).

§pending_request_ttl: Duration

How long a server-originated request surfaced by GET /v1/sessions/{sessionId}/events(/stream) stays answerable via POST .../requests/{requestKey}/result or .../error before it expires with RestError::Gone (also capped by the app-server’s own reply deadline for that request, whichever is sooner). Env: CODEX_APP_SERVER_REST_PENDING_REQUEST_TTL_MS. Default: 600000 (10m).

§max_pending_requests_per_session: usize

Maximum number of not-yet-replied-to server requests a single session will hold at once; beyond this, new ones are rejected (with a JSON-RPC error sent back to the app-server on the caller’s behalf) rather than buffered without bound. Env: CODEX_APP_SERVER_REST_MAX_PENDING_REQUESTS_PER_SESSION. Default: 64.

§events_channel_capacity: usize

Capacity of each REST-spawned session’s internal event channel - exactly the channel documented on crate::EventStream, applied via crate::SessionOptions::with_events_capacity to every session this backend spawns (POST /v1/text-turn, POST /v1/sessions, and session-less POST /v1/call/{method}). REST/SSE consumers reading events over a network are exactly the “slow or stalled consumer” case that channel’s bound and drop policy exist for: notifications are dropped once it’s full, but server-originated requests always get a fallback error reply first rather than being lost - see crate::EventStream’s doc comment for the exact per-variant policy. A 0 value is rejected when the session is actually spawned (see crate::CodexAppServerClient::spawn_with_events_capacity), not silently accepted here. Env: CODEX_APP_SERVER_REST_EVENTS_CHANNEL_CAPACITY. Default: 1024 (matching DEFAULT_EVENTS_CHANNEL_CAPACITY).

§idle_session_ttl: Duration

How long a stateful bridge session may sit with no in-flight operation before it is pruned (and its codex app-server process torn down) on the next backend access. Env: CODEX_APP_SERVER_REST_IDLE_SESSION_TTL_MS. Default: 1800000 (30m).

§compatibility_ttl: Duration

How long a GET /v1/compatibility result is cached before the next call re-runs the (blocking, codex --version-invoking) check. Env: CODEX_APP_SERVER_REST_COMPATIBILITY_TTL_MS. Default: 30000 (30s).

§sse_keep_alive_interval: Duration

Interval between SSE keep-alive frames sent by GET /v1/sessions/{sessionId}/events/stream while no real event is ready. Passed straight through to axum’s KeepAlive::interval. Env: CODEX_APP_SERVER_REST_SSE_KEEP_ALIVE_MS. Default: 15000 (15s, matching axum’s own KeepAlive default - set explicitly here rather than relied upon, so this crate’s behavior doesn’t silently change if axum’s default ever does).

Implementations§

Source§

impl RestLimits

Source

pub fn from_env() -> Self

Builds RestLimits from CODEX_APP_SERVER_REST_* environment variables, using RestLimits::default for any variable that is absent.

§Panics

Panics (via RestLimitsEnvError’s Display) if any CODEX_APP_SERVER_REST_* variable is set but fails to parse. See RestLimits::try_from_env to handle that case without a panic - this constructor exists for the common case of one-shot process startup, where a malformed limit should abort startup loudly rather than be silently downgraded to the default or handled by caller code that has to remember to check.

Source

pub fn try_from_env() -> Result<Self, RestLimitsEnvError>

Builds RestLimits from CODEX_APP_SERVER_REST_* environment variables, using RestLimits::default for any variable that is absent, and returning RestLimitsEnvError for the first variable that is present but fails to parse.

Trait Implementations§

Source§

impl Clone for RestLimits

Source§

fn clone(&self) -> RestLimits

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for RestLimits

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for RestLimits

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> FromRef<T> for T
where T: Clone,

§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more