From d6fdda0e4e896da1460be0ff9b7a561bdbbaeca4 Mon Sep 17 00:00:00 2001 From: kjuulh Date: Sun, 1 Dec 2024 14:25:24 +0100 Subject: [PATCH] feat: add abstraction around task Signed-off-by: kjuulh --- crates/churn/src/agent.rs | 1 + crates/churn/src/agent/actions.rs | 21 ++++----- .../src/agent/handlers/scheduled_tasks.rs | 12 ++++- crates/churn/src/agent/task.rs | 45 +++++++++++++++++++ 4 files changed, 67 insertions(+), 12 deletions(-) create mode 100644 crates/churn/src/agent/task.rs diff --git a/crates/churn/src/agent.rs b/crates/churn/src/agent.rs index d5282db..352dcb5 100644 --- a/crates/churn/src/agent.rs +++ b/crates/churn/src/agent.rs @@ -5,6 +5,7 @@ use refresh::AgentRefresh; pub use config::setup_config; pub mod models; +pub(crate) mod task; mod agent_state; mod config; diff --git a/crates/churn/src/agent/actions.rs b/crates/churn/src/agent/actions.rs index f7512a8..2fabf57 100644 --- a/crates/churn/src/agent/actions.rs +++ b/crates/churn/src/agent/actions.rs @@ -1,32 +1,33 @@ use anyhow::Context; +use super::task::{IntoTask, Task}; + pub struct Plan {} impl Plan { pub fn new() -> Self { Self {} } - pub async fn tasks(&self) -> anyhow::Result> { - Ok(vec![Task::new()]) + pub async fn tasks(&self) -> anyhow::Result> { + Ok(vec![AptTask::new()]) } } -pub struct Task {} +pub struct AptTask {} -impl Task { +impl AptTask { pub fn new() -> Self { Self {} } +} - pub fn id(&self) -> String { +#[async_trait::async_trait] +impl Task for AptTask { + fn id(&self) -> String { "apt".into() } - pub async fn should_run(&self) -> anyhow::Result { - Ok(true) - } - - pub async fn execute(&self) -> anyhow::Result<()> { + async fn execute(&self) -> anyhow::Result<()> { let mut cmd = tokio::process::Command::new("apt-get"); cmd.args(["update", "-q"]); let output = cmd.output().await.context("failed to run apt update")?; diff --git a/crates/churn/src/agent/handlers/scheduled_tasks.rs b/crates/churn/src/agent/handlers/scheduled_tasks.rs index 776c815..048e4db 100644 --- a/crates/churn/src/agent/handlers/scheduled_tasks.rs +++ b/crates/churn/src/agent/handlers/scheduled_tasks.rs @@ -1,6 +1,9 @@ use std::collections::BTreeMap; -use crate::agent::actions::Plan; +use crate::agent::{ + actions::Plan, + task::{ConcreteTask, IntoTask}, +}; #[derive(Clone)] pub struct ScheduledTasks {} @@ -17,7 +20,12 @@ impl ScheduledTasks { tracing::info!("scheduling: {}", task); let plan = Plan::new(); - let tasks = plan.tasks().await?; + let tasks: Vec = plan + .tasks() + .await? + .into_iter() + .map(|i| i.into_task()) + .collect(); for task in tasks { if !task.should_run().await? { diff --git a/crates/churn/src/agent/task.rs b/crates/churn/src/agent/task.rs new file mode 100644 index 0000000..a3349f2 --- /dev/null +++ b/crates/churn/src/agent/task.rs @@ -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 { + Ok(true) + } + async fn execute(&self) -> anyhow::Result<()>; +} + +pub trait IntoTask { + fn into_task(self) -> ConcreteTask; +} + +#[derive(Clone)] +pub struct ConcreteTask { + inner: Arc, +} + +impl ConcreteTask { + pub fn new(t: T) -> Self { + Self { inner: Arc::new(t) } + } +} + +impl std::ops::Deref for ConcreteTask { + type Target = Arc; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl IntoTask for ConcreteTask { + fn into_task(self) -> ConcreteTask { + self + } +} + +impl IntoTask for T { + fn into_task(self) -> ConcreteTask { + ConcreteTask::new(self) + } +}