Skip to content

Commit ee4331d

Browse files
committed
create a trait and factorize
1 parent 97489fe commit ee4331d

File tree

4 files changed

+107
-46
lines changed

4 files changed

+107
-46
lines changed

Cargo.lock

+19-18
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/spfs-cli/cmd-monitor/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,4 @@ spfs-cli-common = { workspace = true }
2828
tokio = { version = "1.20", features = ["rt", "rt-multi-thread"] }
2929
tracing = { workspace = true }
3030
url = "2.2"
31+
futures = "0.3.30"

crates/spfs-cli/cmd-monitor/src/cmd_monitor.rs

+20-28
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@ use tokio::signal::unix::{signal, SignalKind};
1818
use tokio::signal::windows::ctrl_c;
1919
use tokio::time::timeout;
2020

21+
mod signal;
22+
#[cfg(unix)]
23+
use signal::unix_signal_handler::UnixSignalHandler as SignalHandlerImpl;
24+
#[cfg(windows)]
25+
use windows_signal_handler::WindowsSignalHandler as SignalHandlerImpl;
26+
27+
use signal::SignalHandler;
28+
29+
30+
2131
fn main() -> Result<()> {
2232
// because this function exits right away it does not
2333
// properly handle destruction of data, so we put the actual
@@ -144,32 +154,16 @@ impl CmdMonitor {
144154
}
145155

146156
pub async fn run_async(&mut self, config: &spfs::Config) -> Result<i32> {
147-
#[cfg(unix)]
148-
let mut interrupt = signal(SignalKind::interrupt())
149-
.map_err(|err| Error::process_spawn_error("signal()", err, None))?;
150-
#[cfg(windows)]
151-
let mut interrupt =
152-
ctrl_c().map_err(|err| Error::process_spawn_error("ctrl_c()", err, None))?;
153-
#[cfg(unix)]
154-
let mut quit = signal(SignalKind::quit())
155-
.map_err(|err| Error::process_spawn_error("signal()", err, None))?;
156-
#[cfg(windows)]
157-
let mut quit = ctrl_c().map_err(|err| Error::process_spawn_error("ctrl_c()", err, None))?;
158-
#[cfg(unix)]
159-
let mut terminate = signal(SignalKind::terminate())
160-
.map_err(|err| Error::process_spawn_error("signal()", err, None))?;
161-
#[cfg(windows)]
162-
let mut terminate =
163-
ctrl_c().map_err(|err| Error::process_spawn_error("ctrl_c()", err, None))?;
164-
157+
let signal_future = SignalHandlerImpl::build_signal_future();
158+
165159
let repo = spfs::open_repository(&self.runtime_storage).await?;
166160
let storage = spfs::runtime::Storage::new(repo)?;
167161
let runtime = storage.read_runtime(&self.runtime).await?;
168162
tracing::trace!("read runtime from storage repo");
169-
163+
170164
let mut owned = spfs::runtime::OwnedRuntime::upgrade_as_monitor(runtime).await?;
171165
tracing::trace!("upgraded to owned runtime, waiting for empty runtime");
172-
166+
173167
let fut = spfs::monitor::wait_for_empty_runtime(&owned, config);
174168
let res = tokio::select! {
175169
res = fut => {
@@ -178,18 +172,16 @@ impl CmdMonitor {
178172
}
179173
// we explicitly catch any signal related to interruption
180174
// and will act by cleaning up the runtime early
181-
_ = terminate.recv() => Err(spfs::Error::String("Terminate signal received, cleaning up runtime early".to_string())),
182-
_ = interrupt.recv() => Err(spfs::Error::String("Interrupt signal received, cleaning up runtime early".to_string())),
183-
_ = quit.recv() => Err(spfs::Error::String("Quit signal received, cleaning up runtime early".to_string())),
175+
_ = signal_future => Err(spfs::Error::String("Signal received, cleaning up runtime early".to_string())),
184176
};
185177
tracing::trace!("runtime empty of processes ");
186-
178+
187179
// need to reload the runtime here to get any changes made to
188180
// the runtime while it was running so we don't blast them the
189181
// next time this process saves the runtime state.
190182
tracing::trace!("reloading runtime data before cleanup");
191183
owned.reload_state_from_storage().await?;
192-
184+
193185
// try to set the running to false to make this
194186
// runtime easier to identify as safe to delete
195187
// if the automatic cleanup fails. Any error
@@ -198,12 +190,12 @@ impl CmdMonitor {
198190
if let Err(err) = owned.save_state_to_storage().await {
199191
tracing::error!("failed to save runtime: {err:?}");
200192
}
201-
193+
202194
tracing::trace!("tearing down and exiting");
203195
if let Err(err) = spfs::exit_runtime(&owned).await {
204196
tracing::error!("failed to tear down runtime: {err:?}");
205197
}
206-
198+
207199
tracing::trace!(
208200
"{} runtime data",
209201
if owned.is_durable() {
@@ -224,7 +216,7 @@ impl CmdMonitor {
224216
} else if let Err(err) = owned.delete().await {
225217
tracing::error!("failed to clean up runtime data: {err:?}")
226218
}
227-
219+
228220
res?;
229221
Ok(0)
230222
}
+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
use futures::future::Future;
2+
use std::pin::Pin;
3+
use spfs::Error;
4+
5+
pub trait SignalHandler {
6+
fn build_signal_future() -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send>>;
7+
}
8+
9+
#[cfg(unix)]
10+
pub mod unix_signal_handler {
11+
use super::*;
12+
use tokio::signal::unix::{signal, SignalKind};
13+
14+
pub struct UnixSignalHandler;
15+
16+
impl SignalHandler for UnixSignalHandler {
17+
fn build_signal_future() -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send>> {
18+
Box::pin(async move {
19+
let mut interrupt = signal(SignalKind::interrupt())
20+
.map_err(|err| Error::process_spawn_error("signal()", err, None))?;
21+
let mut quit = signal(SignalKind::quit())
22+
.map_err(|err| Error::process_spawn_error("signal()", err, None))?;
23+
let mut terminate = signal(SignalKind::terminate())
24+
.map_err(|err| Error::process_spawn_error("signal()", err, None))?;
25+
26+
futures::future::select_all(vec![
27+
Box::pin(interrupt.recv()),
28+
Box::pin(quit.recv()),
29+
Box::pin(terminate.recv()),
30+
])
31+
.await;
32+
33+
Ok(())
34+
})
35+
}
36+
}
37+
}
38+
39+
#[cfg(windows)]
40+
pub mod windows_signal_handler {
41+
use super::*;
42+
use tokio::signal::ctrl_c;
43+
44+
pub struct WindowsSignalHandler;
45+
46+
impl SignalHandler for WindowsSignalHandler {
47+
fn build_signal_future() -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send>> {
48+
Box::pin(async move {
49+
let mut interrupt = ctrl_c()
50+
.map_err(|err| Error::process_spawn_error("ctrl_c()", err, None))?;
51+
let mut quit = ctrl_c()
52+
.map_err(|err| Error::process_spawn_error("ctrl_c()", err, None))?;
53+
let mut terminate = ctrl_c()
54+
.map_err(|err| Error::process_spawn_error("ctrl_c()", err, None))?;
55+
56+
futures::future::select_all(vec![
57+
Box::pin(interrupt),
58+
Box::pin(quit),
59+
Box::pin(terminate),
60+
])
61+
.await;
62+
63+
Ok(())
64+
})
65+
}
66+
}
67+
}

0 commit comments

Comments
 (0)