use std::sync::Arc;
use std::time::Duration;
use async_trait::async_trait;
use serde_json::Value;
use thiserror::Error;
use crate::context::CancelSignal;
use super::log::LogWriter;
use super::model::{BundleId, JobId, RunId};
use super::store::Store;
#[async_trait]
pub trait JobHandler: Send + Sync + 'static {
fn kind(&self) -> &str;
fn input_schema(&self) -> Option<Value> {
None
}
fn max_concurrent(&self) -> Option<usize> {
None
}
fn timeout(&self) -> Option<Duration> {
None
}
async fn run(&self, ctx: JobContext) -> Result<JobOutput, JobError>;
async fn cancel(&self, _job_id: JobId) -> Result<(), JobError> {
Ok(())
}
}
pub struct JobContext {
pub job_id: JobId,
pub run_id: RunId,
pub bundle_id: Option<BundleId>,
pub inputs: Value,
pub cancel: CancelSignal,
pub log: LogWriter,
pub store: Arc<dyn Store>,
}
#[derive(Clone, Debug)]
pub struct JobOutput {
pub value: Value,
pub findings_count: Option<usize>,
}
impl JobOutput {
pub fn new(value: Value) -> Self {
Self {
value,
findings_count: None,
}
}
}
#[derive(Debug, Error)]
pub enum JobError {
#[error("{0}")]
Failed(String),
#[error("cancelled")]
Cancelled,
#[error("timeout")]
Timeout,
#[error("io: {0}")]
Io(#[from] std::io::Error),
}
impl JobError {
pub fn failed(msg: impl Into<String>) -> Self {
Self::Failed(msg.into())
}
}