pub struct HandlerLimits {
pub max_id_length: usize,
pub max_metadata_size: usize,
pub max_cancellation_tokens: usize,
pub max_token_age: Duration,
pub push_delivery_timeout: Duration,
pub max_artifacts_per_task: usize,
pub max_context_locks: usize,
pub max_push_configs_per_task: usize,
pub max_parts_per_artifact: usize,
pub max_total_push_configs: usize,
pub subscribe_reattach_interval: Duration,
pub subscribe_max_idle: Duration,
}Expand description
Configurable limits for the request handler.
All fields have sensible defaults. Create with HandlerLimits::default()
and override individual values as needed.
§Example
use a2a_protocol_server::handler::HandlerLimits;
let limits = HandlerLimits::default()
.with_max_id_length(2048)
.with_max_metadata_size(2 * 1024 * 1024);Fields§
§max_id_length: usizeMaximum allowed length for task/context IDs. Default: 1024.
max_metadata_size: usizeMaximum allowed serialized size for metadata fields in bytes. Default: 1 MiB.
max_cancellation_tokens: usizeMaximum cancellation token map entries before cleanup sweep. Default: 10,000.
A sweep threshold, not a hard bound: the sweep only evicts cancelled or aged-out entries whose executor is gone — a token belonging to a live task is never removed, so with more than this many tasks genuinely in flight the map tracks the in-flight count instead.
max_token_age: DurationMaximum age for cancellation tokens. Default: 1 hour.
push_delivery_timeout: DurationTimeout for individual push webhook deliveries. Default: 5 seconds.
Bounds how long the handler waits for a single push notification delivery to complete, preventing one slow webhook from blocking all subsequent deliveries.
max_artifacts_per_task: usizeMaximum number of artifacts per task. Default: 1000.
Prevents unbounded memory growth and O(n²) serialization cost when executors emit many artifacts. Once the limit is reached, new artifact updates are rejected.
max_context_locks: usizeMaximum number of per-context locks before cleanup. Default: 10,000.
Context locks serialize concurrent SendMessage requests for the same
context_id. Stale entries (where no other reference is held) are
pruned when this limit is reached. Like
max_cancellation_tokens this is a
prune threshold, not a hard bound — entries currently held by
in-flight requests are never pruned.
max_push_configs_per_task: usizeMaximum number of push notification configs per task. Default: 100.
Enforced by the handler on CreateTaskPushNotificationConfig so the cap
applies uniformly across all store backends. Without it, the SQL
stores (which do not self-enforce) let a client mint unbounded configs
for a single task — a disk-exhaustion vector, and a delivery-amplification
vector since every stream event fans out to all of a task’s configs.
Updating an existing config (same id) does not count against the cap.
max_parts_per_artifact: usizeMaximum number of parts a single artifact may accumulate. Default: 10,000.
max_artifacts_per_task bounds the artifact count, but a stream of
TaskArtifactUpdateEvents with append: true grows one artifact’s
parts without bound. Since executors routinely stream model output
derived from attacker-influenced prompts, this bounds the cumulative
per-artifact (and thus per-task) size. Appends that would exceed the cap
are dropped.
max_total_push_configs: usizeGlobal ceiling on the total number of push configs a store may hold (per-tenant for tenant-scoped stores). Default: 100,000.
Complements max_push_configs_per_task: the per-task cap alone lets a
client mint configs for unboundedly many distinct task ids (100 each),
growing a SQL-backed table without limit. Enforced whenever the store
reports a count (see PushConfigStore::count);
stores that do not report one are unaffected.
subscribe_reattach_interval: DurationHow often a SubscribeToTask stream re-checks whether its task has
finished, once the current turn’s event queue has closed. Default: 250ms.
A task’s queue lives only as long as one executor invocation, so an
agent that parks a task in input_required closes the queue at every
turn boundary. Spec §3.1.6 requires the stream to run until a
terminal state, so it waits here for the next turn rather than
ending. Only an idle stream pays this cost — a live queue delivers
events immediately.
subscribe_max_idle: DurationHow long a SubscribeToTask stream waits for a parked task to make
progress before ending. Default: 5 minutes.
Without a bound, a task left in input_required forever would pin a
connection forever. Ending the stream is safe: §3.5.2 makes
reconnection an expected flow, and the client gets a fresh snapshot
when it resubscribes.
Implementations§
Source§impl HandlerLimits
impl HandlerLimits
Sourcepub const fn with_subscribe_reattach_interval(
self,
interval: Duration,
) -> HandlerLimits
pub const fn with_subscribe_reattach_interval( self, interval: Duration, ) -> HandlerLimits
Sets how often an idle SubscribeToTask stream re-checks its task.
Sourcepub const fn with_subscribe_max_idle(self, max_idle: Duration) -> HandlerLimits
pub const fn with_subscribe_max_idle(self, max_idle: Duration) -> HandlerLimits
Sets how long a SubscribeToTask stream waits on a parked task.
Sourcepub const fn with_max_id_length(self, length: usize) -> HandlerLimits
pub const fn with_max_id_length(self, length: usize) -> HandlerLimits
Sets the maximum allowed length for task/context IDs.
Sourcepub const fn with_max_metadata_size(self, size: usize) -> HandlerLimits
pub const fn with_max_metadata_size(self, size: usize) -> HandlerLimits
Sets the maximum serialized size for metadata fields in bytes.
Sourcepub const fn with_max_cancellation_tokens(self, max: usize) -> HandlerLimits
pub const fn with_max_cancellation_tokens(self, max: usize) -> HandlerLimits
Sets the maximum cancellation token map entries before cleanup.
Sourcepub const fn with_max_token_age(self, age: Duration) -> HandlerLimits
pub const fn with_max_token_age(self, age: Duration) -> HandlerLimits
Sets the maximum age for cancellation tokens.
Sourcepub const fn with_push_delivery_timeout(
self,
timeout: Duration,
) -> HandlerLimits
pub const fn with_push_delivery_timeout( self, timeout: Duration, ) -> HandlerLimits
Sets the timeout for individual push webhook deliveries.
Sourcepub const fn with_max_artifacts_per_task(self, max: usize) -> HandlerLimits
pub const fn with_max_artifacts_per_task(self, max: usize) -> HandlerLimits
Sets the maximum number of artifacts per task.
Sourcepub const fn with_max_push_configs_per_task(self, max: usize) -> HandlerLimits
pub const fn with_max_push_configs_per_task(self, max: usize) -> HandlerLimits
Sets the maximum number of push notification configs per task.
Sourcepub const fn with_max_total_push_configs(self, max: usize) -> HandlerLimits
pub const fn with_max_total_push_configs(self, max: usize) -> HandlerLimits
Sets the global (per-tenant for tenant stores) ceiling on total push notification configs. Enforced only when the store reports a count.
Sourcepub const fn with_max_parts_per_artifact(self, max: usize) -> HandlerLimits
pub const fn with_max_parts_per_artifact(self, max: usize) -> HandlerLimits
Sets the maximum number of parts a single artifact may accumulate.
Sourcepub const fn with_max_context_locks(self, max: usize) -> HandlerLimits
pub const fn with_max_context_locks(self, max: usize) -> HandlerLimits
Sets the maximum number of per-context locks before cleanup.
Trait Implementations§
Source§impl Clone for HandlerLimits
impl Clone for HandlerLimits
Source§fn clone(&self) -> HandlerLimits
fn clone(&self) -> HandlerLimits
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for HandlerLimits
impl Debug for HandlerLimits
Source§impl Default for HandlerLimits
impl Default for HandlerLimits
Source§fn default() -> HandlerLimits
fn default() -> HandlerLimits
Auto Trait Implementations§
impl Freeze for HandlerLimits
impl RefUnwindSafe for HandlerLimits
impl Send for HandlerLimits
impl Sync for HandlerLimits
impl Unpin for HandlerLimits
impl UnsafeUnpin for HandlerLimits
impl UnwindSafe for HandlerLimits
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> FutureExt for T
impl<T> FutureExt for T
Source§fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
Source§fn with_current_context(self) -> WithContext<Self> ⓘ
fn with_current_context(self) -> WithContext<Self> ⓘ
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request