use async_trait::async_trait;
use crate::error::Result;
use crate::runtime_build::RuntimeBuildId;
use super::{FlowTask, FlowTaskLease};
#[async_trait]
pub trait FlowTaskDispatcher: Send + Sync {
async fn dispatch(&self, task: FlowTask) -> Result<()>;
fn has_runtime_build_route(&self, required_build_id: Option<&RuntimeBuildId>) -> bool {
required_build_id.is_none()
}
fn ensure_runtime_build_route(&self, required_build_id: Option<&RuntimeBuildId>) -> Result<()> {
if self.has_runtime_build_route(required_build_id) {
return Ok(());
}
Err(crate::FlowError::RuntimeBuildRouteNotFound {
required_build_id: required_build_id.cloned(),
})
}
async fn dispatch_for_runtime_build(
&self,
required_build_id: Option<&RuntimeBuildId>,
task: FlowTask,
) -> Result<()> {
self.ensure_runtime_build_route(required_build_id)?;
self.dispatch(task).await
}
}
#[async_trait]
pub trait FlowTaskQueue: Send + Sync {
async fn enqueue(&self, task: FlowTask) -> Result<()>;
async fn lease(&self) -> Result<Option<FlowTaskLease>>;
async fn heartbeat(&self, lease_id: &str) -> Result<String>;
async fn ack(&self, lease_id: &str) -> Result<()>;
async fn requeue_inflight(&self) -> Result<usize> {
Ok(0)
}
async fn dequeue(&self) -> Result<Option<FlowTask>> {
let Some(lease) = self.lease().await? else {
return Ok(None);
};
let task = lease.task.clone();
self.ack(&lease.lease_id).await?;
Ok(Some(task))
}
async fn len(&self) -> Result<usize>;
async fn is_empty(&self) -> Result<bool> {
Ok(self.len().await? == 0)
}
}
#[async_trait]
impl<T> FlowTaskDispatcher for T
where
T: FlowTaskQueue + ?Sized,
{
async fn dispatch(&self, task: FlowTask) -> Result<()> {
FlowTaskQueue::enqueue(self, task).await
}
}