use std::sync::Arc;
use a2a_protocol_types::error::A2aResult;
use a2a_protocol_types::events::StreamResponse;
use a2a_protocol_types::task::TaskId;
use super::super::RequestHandler;
use super::decisions::second_send_blocked;
use crate::error::{ServerError, ServerResult};
use crate::streaming::{InMemoryQueueReader, InMemoryQueueWriter, QueueLease};
pub(super) type LeasedQueue = (
Arc<InMemoryQueueWriter>,
InMemoryQueueReader,
Option<tokio::sync::mpsc::Receiver<A2aResult<StreamResponse>>>,
);
impl RequestHandler {
pub(super) async fn reject_in_flight_send(&self, task_id: &TaskId) -> ServerResult<()> {
let blocked = self
.cancellation_tokens
.read()
.await
.get(task_id)
.is_some_and(second_send_blocked);
if blocked {
return Err(ServerError::UnsupportedOperation(format!(
"task {task_id} is already being processed; \
wait for it to reach input-required or a terminal state before sending again"
)));
}
Ok(())
}
pub(super) async fn lease_event_queue(
&self,
task_id: &TaskId,
use_background: bool,
) -> ServerResult<LeasedQueue> {
let capacity = self
.tenant_limits()
.and_then(|limits| limits.event_queue_capacity);
match self
.event_queue_manager
.lease(task_id, use_background, capacity)
.await
{
QueueLease::Created {
writer,
reader,
persistence_rx,
} => Ok((writer, reader, persistence_rx)),
QueueLease::Existing => Err(ServerError::UnsupportedOperation(format!(
"task {task_id} is already being processed; wait for it to reach \
input-required or a terminal state before sending again"
))),
QueueLease::CapacityExhausted => {
let cap = self
.event_queue_manager
.max_concurrent_queues()
.map_or_else(String::new, |n| format!(" ({n})"));
Err(ServerError::Overloaded(format!(
"server at maximum concurrent stream capacity{cap}; retry later"
)))
}
}
}
}