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 shutdown(&mut self) -> Result<()> {
58 self.commands_tx
59 .send(SupervisorCommand::Shutdown)
60 .await
61 .map_err(|err| Error::Internal(err.to_string()))?;
62
63 Ok(())
64 }
65
66 pub async fn up(&mut self, project: Project, services: Vec<String>) -> Result<()> {
71 tracing::trace!(
72 "Received up command for project {project:?} to start services {services:?}"
73 );
74
75 let project_id = project.id.clone();
76
77 self.commands_tx
78 .send(SupervisorCommand::UpdateConfig {
79 project_id: project_id.clone(),
80 config: project,
81 })
82 .await
83 .map_err(|err| Error::Internal(err.to_string()))?;
84 self.commands_tx
85 .send(SupervisorCommand::Up {
86 project_id: project_id.clone(),
87 services,
88 })
89 .await
90 .map_err(|err| Error::Internal(err.to_string()))?;
91
92 Ok(())
93 }
94}