feat: add abstraction around task
All checks were successful
continuous-integration/drone/push Build is passing

Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
Kasper Juul Hermansen 2024-12-01 14:25:24 +01:00
parent 974e1ee0d6
commit d6fdda0e4e
Signed by: kjuulh
GPG Key ID: D85D7535F18F35FA
4 changed files with 67 additions and 12 deletions

View File

@ -5,6 +5,7 @@ use refresh::AgentRefresh;
pub use config::setup_config; pub use config::setup_config;
pub mod models; pub mod models;
pub(crate) mod task;
mod agent_state; mod agent_state;
mod config; mod config;

View File

@ -1,32 +1,33 @@
use anyhow::Context; use anyhow::Context;
use super::task::{IntoTask, Task};
pub struct Plan {} pub struct Plan {}
impl Plan { impl Plan {
pub fn new() -> Self { pub fn new() -> Self {
Self {} Self {}
} }
pub async fn tasks(&self) -> anyhow::Result<Vec<Task>> { pub async fn tasks(&self) -> anyhow::Result<Vec<impl IntoTask>> {
Ok(vec![Task::new()]) Ok(vec![AptTask::new()])
} }
} }
pub struct Task {} pub struct AptTask {}
impl Task { impl AptTask {
pub fn new() -> Self { pub fn new() -> Self {
Self {} Self {}
} }
}
pub fn id(&self) -> String { #[async_trait::async_trait]
impl Task for AptTask {
fn id(&self) -> String {
"apt".into() "apt".into()
} }
pub async fn should_run(&self) -> anyhow::Result<bool> { async fn execute(&self) -> anyhow::Result<()> {
Ok(true)
}
pub async fn execute(&self) -> anyhow::Result<()> {
let mut cmd = tokio::process::Command::new("apt-get"); let mut cmd = tokio::process::Command::new("apt-get");
cmd.args(["update", "-q"]); cmd.args(["update", "-q"]);
let output = cmd.output().await.context("failed to run apt update")?; let output = cmd.output().await.context("failed to run apt update")?;

View File

@ -1,6 +1,9 @@
use std::collections::BTreeMap; use std::collections::BTreeMap;
use crate::agent::actions::Plan; use crate::agent::{
actions::Plan,
task::{ConcreteTask, IntoTask},
};
#[derive(Clone)] #[derive(Clone)]
pub struct ScheduledTasks {} pub struct ScheduledTasks {}
@ -17,7 +20,12 @@ impl ScheduledTasks {
tracing::info!("scheduling: {}", task); tracing::info!("scheduling: {}", task);
let plan = Plan::new(); let plan = Plan::new();
let tasks = plan.tasks().await?; let tasks: Vec<ConcreteTask> = plan
.tasks()
.await?
.into_iter()
.map(|i| i.into_task())
.collect();
for task in tasks { for task in tasks {
if !task.should_run().await? { if !task.should_run().await? {

View File

@ -0,0 +1,45 @@
use std::sync::Arc;
#[async_trait::async_trait]
pub trait Task {
fn id(&self) -> String;
async fn should_run(&self) -> anyhow::Result<bool> {
Ok(true)
}
async fn execute(&self) -> anyhow::Result<()>;
}
pub trait IntoTask {
fn into_task(self) -> ConcreteTask;
}
#[derive(Clone)]
pub struct ConcreteTask {
inner: Arc<dyn Task + Sync + Send + 'static>,
}
impl ConcreteTask {
pub fn new<T: Task + Sync + Send + 'static>(t: T) -> Self {
Self { inner: Arc::new(t) }
}
}
impl std::ops::Deref for ConcreteTask {
type Target = Arc<dyn Task + Sync + Send + 'static>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl IntoTask for ConcreteTask {
fn into_task(self) -> ConcreteTask {
self
}
}
impl<T: Task + Sync + Send + 'static> IntoTask for T {
fn into_task(self) -> ConcreteTask {
ConcreteTask::new(self)
}
}