tutti_core/supervisor/
main.rs1use tokio::sync::mpsc;
2use tutti_types::{Project, ProjectId};
3
4use crate::{
5 error::{Error, Result},
6 process_manager::ProcessManager,
7 supervisor::{
8 background::SupervisorBackground,
9 commands::{SupervisorCommand, SupervisorEvent},
10 },
11};
12
13#[derive(Debug)]
14pub struct Supervisor {
15 _task: tokio::task::JoinHandle<()>,
16 commands_tx: mpsc::Sender<SupervisorCommand>,
17}
18
19impl Supervisor {
20 pub fn new<P: ProcessManager + Send + Sync + 'static>(
21 process_manager: P,
22 ) -> (Self, mpsc::Receiver<SupervisorEvent>) {
23 let (commands_tx, commands_rx) = mpsc::channel::<SupervisorCommand>(100);
24 let (mut inner, output_rx) =
25 SupervisorBackground::new(process_manager, commands_tx.clone(), commands_rx);
26
27 let task = tokio::spawn(async move {
28 inner.run().await;
29 });
30
31 (
32 Self {
33 _task: task,
34 commands_tx,
35 },
36 output_rx,
37 )
38 }
39
40 pub async fn down(&mut self, project_id: ProjectId) -> Result<()> {
45 self.commands_tx
46 .send(SupervisorCommand::Down { project_id })
47 .await
48 .map_err(|err| Error::Internal(err.to_string()))?;
49
50 Ok(())
51 }
52
53 pub async fn up(&mut self, project: Project, services: Vec<String>) -> Result<()> {
58 tracing::trace!(
59 "Received up command for project {project:?} to start services {services:?}"
60 );
61
62 let project_id = project.id.clone();
63
64 self.commands_tx
65 .send(SupervisorCommand::UpdateConfig {
66 project_id: project_id.clone(),
67 config: project,
68 })
69 .await
70 .map_err(|err| Error::Internal(err.to_string()))?;
71 self.commands_tx
72 .send(SupervisorCommand::Up {
73 project_id: project_id.clone(),
74 services,
75 })
76 .await
77 .map_err(|err| Error::Internal(err.to_string()))?;
78
79 Ok(())
80 }
81}