use aion_awl::{CompiledHarness, WorkerDecl};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct HarnessQueue {
pub task_queue: String,
pub harness: CompiledHarness,
}
#[derive(Debug, thiserror::Error)]
pub enum HarnessQueueError {
#[error(
"the deployed package's archived AWL document could not be parsed, so this server \
cannot tell whether it declares a built-in agent worker: {message}"
)]
Parse {
message: String,
},
#[error(
"task queue `{task_queue}` declares a `harness` section that is not complete: {message}. \
Nothing was minted for it — fix the section, run `aion awl check`, and deploy again"
)]
Harness {
task_queue: String,
message: String,
},
#[error(
"task queue `{task_queue}` declares a `harness` section but every one of its actions \
({actions}) carries a declared `run` body, which the server executes from the deployed \
contract. There is nothing on that queue for an agent worker to serve, so none was \
minted"
)]
NoServiceableAction {
task_queue: String,
actions: String,
},
}
pub fn harness_queues(source: &str) -> Result<Vec<HarnessQueue>, HarnessQueueError> {
let document = aion_awl::parse(source).map_err(|error| HarnessQueueError::Parse {
message: error.to_string(),
})?;
let mut queues = Vec::new();
for worker in &document.workers {
if worker.harness.is_none() {
continue;
}
queues.push(read_queue(worker)?);
}
Ok(queues)
}
fn read_queue(worker: &WorkerDecl) -> Result<HarnessQueue, HarnessQueueError> {
let compiled =
aion_awl::compile_harness(worker).map_err(|error| HarnessQueueError::Harness {
task_queue: worker.name.clone(),
message: error.to_string(),
})?;
let Some(harness) = compiled else {
return Err(HarnessQueueError::Harness {
task_queue: worker.name.clone(),
message: "the section vanished between the presence test and the compile".to_owned(),
});
};
let bodied: Vec<&str> = worker
.actions
.iter()
.filter(|action| action.body.is_some())
.map(|action| action.name.as_str())
.collect();
if bodied.len() == worker.actions.len() {
return Err(HarnessQueueError::NoServiceableAction {
task_queue: worker.name.clone(),
actions: if bodied.is_empty() {
"the queue declares none".to_owned()
} else {
bodied.join(", ")
},
});
}
Ok(HarnessQueue {
task_queue: worker.name.clone(),
harness,
})
}
#[cfg(test)]
#[path = "queues_tests.rs"]
mod tests;