systemd_transient/
reusable.rs1use crate::error::SystemdTransientError;
2use crate::watch::exit_of;
3use crate::{SystemdTransientManager, TransientUnitHandle, UnitExit, UnitProperty, UnitStatus};
4
5#[derive(Debug)]
6pub struct ReusableTransientUnit {
7 pub(crate) name: String,
8 pub(crate) props: Vec<UnitProperty>,
9 pub(crate) unit_handle: Option<TransientUnitHandle>,
10 pub(crate) systemd_manager: SystemdTransientManager,
11}
12
13impl ReusableTransientUnit {
14 pub async fn start(&mut self) -> Result<(), SystemdTransientError> {
17 if let Some(handle) = &self.unit_handle
18 && exit_of(&handle.unit.active_state().await?).is_none()
19 {
20 return Err(SystemdTransientError::UnitAlreadyRunning {
21 name: handle.name.clone(),
22 });
23 }
24 self.release().await?;
26
27 let handle = self
28 .systemd_manager
29 .start(&self.name, self.props.clone())
30 .await?;
31 self.unit_handle = Some(handle);
32
33 Ok(())
34 }
35
36 pub async fn adopt(&mut self) -> Result<bool, SystemdTransientError> {
41 if self.unit_handle.is_none() {
42 self.unit_handle = self.systemd_manager.adopt(&self.name).await?;
43 }
44 Ok(self.unit_handle.is_some())
45 }
46
47 pub async fn stop(&mut self) -> Result<UnitExit, SystemdTransientError> {
48 let exit = self.handle()?.stop().await?;
50 self.release().await?;
51
52 Ok(exit)
53 }
54
55 pub async fn wait_for_exit(&self) -> Result<UnitExit, SystemdTransientError> {
56 self.handle()?.wait_for_exit().await
57 }
58
59 pub fn status(&self) -> UnitStatus {
61 match &self.unit_handle {
62 None => UnitStatus::Idle,
63 Some(h) => h.watch.current().into(),
64 }
65 }
66
67 pub async fn release(&mut self) -> Result<(), SystemdTransientError> {
69 if let Some(h) = self.unit_handle.take() {
70 h.release().await?;
71 }
72 Ok(())
73 }
74
75 fn handle(&self) -> Result<&TransientUnitHandle, SystemdTransientError> {
76 self
77 .unit_handle
78 .as_ref()
79 .ok_or_else(|| SystemdTransientError::UnitNotRunning {
80 name: self.name.clone(),
81 })
82 }
83}