pub struct RequestHandler { /* private fields */ }Expand description
The core protocol logic handler.
Orchestrates task lifecycle, event streaming, push notifications, and interceptor chains for all A2A methods.
RequestHandler is not generic — it stores the executor as
Arc<dyn AgentExecutor>, enabling dynamic dispatch and simplifying
the downstream API (dispatchers, builder, etc.).
§Store ownership
Stores are held as Arc<dyn TaskStore> / Arc<dyn PushConfigStore>
rather than Box<dyn ...> so that they can be cheaply cloned into
background tasks (e.g. the streaming push-delivery processor).
Implementations§
Source§impl RequestHandler
impl RequestHandler
Sourcepub fn activated_extensions(
&self,
headers: &HashMap<String, String>,
) -> Vec<String>
pub fn activated_extensions( &self, headers: &HashMap<String, String>, ) -> Vec<String>
Returns the activated extension set for a request: the intersection of
the client’s A2A-Extensions declaration and the card’s declared
extensions, in request order. HTTP dispatchers echo this back in the
response A2A-Extensions header (official-SDK convention) so clients
know which requested extensions the agent honored.
Source§impl RequestHandler
impl RequestHandler
Sourcepub async fn active_queue_count(&self) -> usize
pub async fn active_queue_count(&self) -> usize
Number of event queues currently alive.
One queue exists per in-flight task and is destroyed when the task finishes, so under steady traffic this tracks concurrency rather than throughput. A value that climbs with cumulative request count — instead of settling — means queues are not being reclaimed.
Exposed for monitoring and for the sustained-load tests. The
Metrics::on_queue_depth_change
callback reports the same quantity as it changes; this is the pull-based
counterpart, for a gauge scrape or a health page.
Sourcepub async fn task_count(&self) -> A2aResult<u64>
pub async fn task_count(&self) -> A2aResult<u64>
Sourcepub async fn cancellation_token_count(&self) -> usize
pub async fn cancellation_token_count(&self) -> usize
Number of registered cancellation tokens.
One is registered per in-flight task and removed when it finishes, so
like active_queue_count this should settle
under steady traffic rather than climb. It has its own bound
(max_cancellation_tokens), so a leak here eventually rejects new work
rather than only consuming memory — which makes it worth watching
directly.
Sourcepub async fn task_store_health(&self) -> A2aResult<()>
pub async fn task_store_health(&self) -> A2aResult<()>
Probes the task store, for readiness checks.
Answers the one question a readiness probe needs: can this replica reach the dependency it cannot serve a request without? A liveness probe deliberately cannot answer that — making liveness depend on a downstream turns that downstream’s outage into a restart loop across every replica, which is how a degraded service becomes an unavailable one.
Implemented as count, which every bundled store answers
with a cheap query. It performs no write, so a store at its capacity
limit still reports healthy — capacity is not the same question as
reachability, and conflating them would drain traffic from a cluster
that was merely full.
§Errors
Returns whatever the store returned. Callers exposing this over HTTP
should surface
metric_label
rather than the message, which may name a host or a connection string.
Source§impl RequestHandler
impl RequestHandler
Sourcepub async fn on_cancel_task(
&self,
params: CancelTaskParams,
headers: Option<&HashMap<String, String>>,
) -> ServerResult<Task>
pub async fn on_cancel_task( &self, params: CancelTaskParams, headers: Option<&HashMap<String, String>>, ) -> ServerResult<Task>
Source§impl RequestHandler
impl RequestHandler
Sourcepub async fn on_get_extended_agent_card(
&self,
headers: Option<&HashMap<String, String>>,
) -> ServerResult<AgentCard>
pub async fn on_get_extended_agent_card( &self, headers: Option<&HashMap<String, String>>, ) -> ServerResult<AgentCard>
Source§impl RequestHandler
impl RequestHandler
Sourcepub async fn on_get_task(
&self,
params: TaskQueryParams,
headers: Option<&HashMap<String, String>>,
) -> ServerResult<Task>
pub async fn on_get_task( &self, params: TaskQueryParams, headers: Option<&HashMap<String, String>>, ) -> ServerResult<Task>
Handles GetTask. Returns ServerError::TaskNotFound if missing.
§Errors
Returns ServerError::TaskNotFound if the task does not exist.
Source§impl RequestHandler
impl RequestHandler
Sourcepub async fn on_list_tasks(
&self,
params: ListTasksParams,
headers: Option<&HashMap<String, String>>,
) -> ServerResult<TaskListResponse>
pub async fn on_list_tasks( &self, params: ListTasksParams, headers: Option<&HashMap<String, String>>, ) -> ServerResult<TaskListResponse>
Source§impl RequestHandler
impl RequestHandler
Sourcepub async fn on_resubscribe(
&self,
params: TaskIdParams,
headers: Option<&HashMap<String, String>>,
) -> ServerResult<InMemoryQueueReader>
pub async fn on_resubscribe( &self, params: TaskIdParams, headers: Option<&HashMap<String, String>>, ) -> ServerResult<InMemoryQueueReader>
Source§impl RequestHandler
impl RequestHandler
Sourcepub async fn on_send_message(
&self,
params: MessageSendParams,
streaming: bool,
headers: Option<&HashMap<String, String>>,
) -> ServerResult<SendMessageResult>
pub async fn on_send_message( &self, params: MessageSendParams, streaming: bool, headers: Option<&HashMap<String, String>>, ) -> ServerResult<SendMessageResult>
Handles SendMessage / SendStreamingMessage.
The optional headers map carries HTTP request headers for
interceptor access-control decisions (e.g. Authorization).
§Errors
Returns ServerError if task creation or execution fails.
Source§impl RequestHandler
impl RequestHandler
Sourcepub async fn on_set_push_config(
&self,
config: TaskPushNotificationConfig,
headers: Option<&HashMap<String, String>>,
) -> ServerResult<TaskPushNotificationConfig>
pub async fn on_set_push_config( &self, config: TaskPushNotificationConfig, headers: Option<&HashMap<String, String>>, ) -> ServerResult<TaskPushNotificationConfig>
Handles CreateTaskPushNotificationConfig.
§Errors
Returns ServerError::PushNotSupported if no push sender is configured.
Sourcepub async fn on_get_push_config(
&self,
params: GetPushConfigParams,
headers: Option<&HashMap<String, String>>,
) -> ServerResult<TaskPushNotificationConfig>
pub async fn on_get_push_config( &self, params: GetPushConfigParams, headers: Option<&HashMap<String, String>>, ) -> ServerResult<TaskPushNotificationConfig>
Handles GetTaskPushNotificationConfig.
§Errors
Returns ServerError::PushNotSupported if the agent card does not
advertise push notifications, or ServerError::TaskNotFound if the
requested configuration does not exist (spec §3.1.8).
Sourcepub async fn on_list_push_configs(
&self,
task_id: &str,
tenant: Option<&str>,
headers: Option<&HashMap<String, String>>,
) -> ServerResult<Vec<TaskPushNotificationConfig>>
pub async fn on_list_push_configs( &self, task_id: &str, tenant: Option<&str>, headers: Option<&HashMap<String, String>>, ) -> ServerResult<Vec<TaskPushNotificationConfig>>
Sourcepub async fn on_delete_push_config(
&self,
params: DeletePushConfigParams,
headers: Option<&HashMap<String, String>>,
) -> ServerResult<()>
pub async fn on_delete_push_config( &self, params: DeletePushConfigParams, headers: Option<&HashMap<String, String>>, ) -> ServerResult<()>
Handles DeleteTaskPushNotificationConfig.
§Errors
Returns a ServerError if the delete operation fails.
Source§impl RequestHandler
impl RequestHandler
Sourcepub async fn shutdown(&self) -> ShutdownReport
pub async fn shutdown(&self) -> ShutdownReport
Initiates graceful shutdown of the handler.
This method:
- Cancels all in-flight tasks by signalling their cancellation tokens.
- Destroys all event queues, causing readers to see EOF.
After calling shutdown(), new requests will still be accepted but
in-flight tasks will observe cancellation. The caller should stop
accepting new connections after calling this method.
Returns a ShutdownReport describing whether the executor’s cleanup
hook finished. This method does not wait for queues to drain, so
queues_force_destroyed is always 0 — use
shutdown_with_timeout when
in-flight work should be given a chance to finish.
Sourcepub async fn shutdown_with_timeout(&self, timeout: Duration) -> ShutdownReport
pub async fn shutdown_with_timeout(&self, timeout: Duration) -> ShutdownReport
Initiates graceful shutdown, returning within timeout.
Cancels all in-flight tasks, waits for event queues to drain, and then runs the executor’s cleanup hook — all inside the one budget. This gives executors a chance to finish writing final events before the queues are torn down.
§timeout is the total, not a per-phase allowance
It was a per-phase allowance until 2026-08-19: the drain loop ran to
now + timeout and then on_shutdown was given a fresh full
timeout, so the call could take twice what the caller asked for.
Measured on paused time with an undrainable queue and a cleanup hook
that never returns, shutdown_with_timeout(30s) took 60s — exactly
2×.
That is not an academic overshoot. The number an operator puts here is
the number they put in terminationGracePeriodSeconds, and a process
that overruns it is SIGKILLed part-way through the cleanup this method
exists to perform — truncating precisely the streams a graceful
shutdown was protecting.
So the drain phase and the cleanup hook now share one deadline. If draining consumes the whole budget, cleanup is given what is left, which may be nothing; that is reported rather than papered over, because “your queues would not drain” and “your cleanup hook hung” are different problems and the caller can see which they had.
Returns a ShutdownReport: a non-zero queues_force_destroyed means
the deadline passed with work still in flight, and
executor_cleanup_completed == false means the executor’s cleanup hook
was abandoned. Both are invisible from the outside otherwise, which is
how a rollout can truncate every in-flight stream without anyone
noticing.
Source§impl RequestHandler
impl RequestHandler
Sourcepub fn tenant_resolver(&self) -> Option<&dyn TenantResolver>
pub fn tenant_resolver(&self) -> Option<&dyn TenantResolver>
Returns the tenant resolver, if configured.
Use this in dispatchers or middleware to resolve the tenant identity
from a CallContext before processing a request.
Sourcepub const fn tenant_config(&self) -> Option<&PerTenantConfig>
pub const fn tenant_config(&self) -> Option<&PerTenantConfig>
Returns the per-tenant limits this handler enforces, if any were set.
The handler applies them itself; this accessor is for inspection, and
for handing the same configuration to
RateLimitInterceptor::with_tenant_config,
which is where rate_limit_rps is applied. See
tenant_config.
Trait Implementations§
Auto Trait Implementations§
impl !RefUnwindSafe for RequestHandler
impl !UnwindSafe for RequestHandler
impl Freeze for RequestHandler
impl Send for RequestHandler
impl Sync for RequestHandler
impl Unpin for RequestHandler
impl UnsafeUnpin for RequestHandler
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> 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