use a2a_protocol_types::message::Message;
use a2a_protocol_types::params::SendMessageConfiguration;
use a2a_protocol_types::push::TaskPushNotificationConfig;
use a2a_protocol_types::task::{ContextId, Task, TaskId, TaskState, TaskStatus};
use super::super::RequestHandler;
use super::decisions::MAX_TASK_HISTORY_MESSAGES;
use crate::error::ServerResult;
use crate::request_context::RequestContext;
pub(super) fn build_initial_task(
task_id: &TaskId,
context_id: &str,
stored_task: Option<&Task>,
message: &Message,
) -> Task {
let continuation = stored_task.filter(|s| s.id == *task_id);
let history = vec![message.clone()];
Task {
id: task_id.clone(),
context_id: ContextId::new(context_id),
status: TaskStatus::with_timestamp(TaskState::Submitted),
history: Some(history),
artifacts: continuation.and_then(|s| s.artifacts.clone()),
metadata: continuation.and_then(|s| s.metadata.clone()),
}
}
pub(super) fn build_request_context(
message: Message,
task_id: TaskId,
context_id: String,
stored_task: Option<Task>,
metadata: Option<serde_json::Value>,
call_context: crate::call_context::CallContext,
) -> RequestContext {
let mut ctx = RequestContext::new(message, task_id, context_id).with_call_context(call_context);
if let Some(stored) = stored_task {
ctx = ctx.with_stored_task(stored);
}
if let Some(meta) = metadata {
ctx = ctx.with_metadata(meta);
}
ctx
}
impl RequestHandler {
pub(super) async fn persist_initial_task(&self, task: &Task) -> ServerResult<()> {
let appended = task.history.clone().unwrap_or_default();
if let Err(e) = self
.task_store
.save_appending_history(task, &appended, MAX_TASK_HISTORY_MESSAGES)
.await
{
self.release_admission(&task.id).await;
return Err(e.into());
}
Ok(())
}
pub(super) async fn register_inline_push_config(
&self,
configuration: Option<&SendMessageConfiguration>,
task_id: &TaskId,
) -> ServerResult<()> {
let Some(inline) = configuration.and_then(|c| c.task_push_notification_config.clone())
else {
return Ok(());
};
let stored = self
.validate_and_store_push_config(TaskPushNotificationConfig {
task_id: Some(task_id.0.clone()),
..inline
})
.await;
if let Err(e) = stored {
self.release_admission(task_id).await;
if let Err(_delete_err) = self.task_store.delete(task_id).await {
trace_warn!(
task_id = %task_id,
error = %_delete_err,
"push config rejected the send, and rolling the task row back failed"
);
}
return Err(e);
}
Ok(())
}
async fn release_admission(&self, task_id: &TaskId) {
self.event_queue_manager.destroy(task_id).await;
self.cancellation_tokens.write().await.remove(task_id);
}
}