proc_heim/process/
scoped_process_handle.rs1use std::time::Duration;
2use std::{fmt::Debug, sync::Arc};
3
4use crate::manager::{
5 GetLogsError, GetProcessInfoError, KillProcessError, LogsQuery, ProcessId, ProcessInfo,
6 ReadMessageError, ReceiveMessageError, WriteMessageError,
7};
8
9use tokio::task::JoinHandle;
10use tokio_stream::Stream;
11
12use super::message::Message;
13use super::ProcessHandle;
14
15#[derive(Clone, Debug)]
21pub struct ScopedProcessHandle {
22 handle: ProcessHandle,
23 instance_counter: Arc<()>,
24}
25
26impl ScopedProcessHandle {
27 pub fn new(handle: ProcessHandle) -> Self {
29 Self {
30 handle,
31 instance_counter: Arc::new(()),
32 }
33 }
34
35 pub fn id(&self) -> &ProcessId {
37 self.handle.id()
38 }
39
40 pub async fn send_message<M>(&self, message: M) -> Result<(), WriteMessageError>
42 where
43 M: Into<Message>,
44 {
45 self.handle.send_message(message).await
46 }
47
48 pub async fn subscribe_message_stream(
50 &self,
51 ) -> Result<impl Stream<Item = Result<Message, ReceiveMessageError>>, ReadMessageError> {
52 self.handle.subscribe_message_stream().await
53 }
54
55 pub async fn get_logs_stdout(&self, query: LogsQuery) -> Result<Vec<String>, GetLogsError> {
57 self.handle.get_logs_stdout(query).await
58 }
59
60 pub async fn get_logs_stderr(&self, query: LogsQuery) -> Result<Vec<String>, GetLogsError> {
62 self.handle.get_logs_stderr(query).await
63 }
64
65 pub async fn get_process_info(&self) -> Result<ProcessInfo, GetProcessInfoError> {
67 self.handle.get_process_info().await
68 }
69
70 pub fn wait(
72 &self,
73 poll_interval: Duration,
74 ) -> JoinHandle<Result<ProcessInfo, GetProcessInfoError>> {
75 self.handle.wait(poll_interval)
76 }
77
78 pub async fn kill(&self) -> Result<(), KillProcessError> {
80 self.handle.kill().await
81 }
82}
83
84impl Drop for ScopedProcessHandle {
85 fn drop(&mut self) {
86 if Arc::strong_count(&self.instance_counter) == 1
87 && !self.handle.handle.try_kill(*self.id())
88 {
89 let handle = self.handle.clone();
90 tokio::spawn(async move {
91 handle
92 .handle
93 .kill_with_timeout(*handle.id(), Duration::from_millis(200))
94 .await
95 });
96 }
97 }
98}
99
100impl From<ProcessHandle> for ScopedProcessHandle {
101 fn from(handle: ProcessHandle) -> Self {
102 Self::new(handle)
103 }
104}