Skip to content

Commit

Permalink
Merge pull request #39 from dark0dave/feature/timeout
Browse files Browse the repository at this point in the history
feat(timeout): Add timeout
  • Loading branch information
dark0dave authored Dec 2, 2023
2 parents 1ee0d9e + 1625266 commit 8102734
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 17 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,13 @@ Options:
-l, --language <LANGUAGE>
Game Language [default: en_US]
-d, --depth <DEPTH>
Depth to walk folder structure [default: 3]
Depth to walk folder structure [env: DEPTH=] [default: 3]
-s, --skip-installed
Compare against installed weidu log, note this is best effort
Compare against installed weidu log, note this is best effort [env: SKIP_INSTALLED=]
-a, --abort-on-warnings
If a warning occurs in the weidu child process exit
If a warning occurs in the weidu child process exit [env: ABORT_ON_WARNINGS=]
-t, --timeout <TIMEOUT>
Timeout time per mod in seconds, default is 1 hour [env: TIMEOUT=] [default: 3600]
-h, --help
Print help
-V, --version
Expand Down
10 changes: 7 additions & 3 deletions src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,20 @@ pub struct Args {
pub language: String,

/// Depth to walk folder structure
#[clap(long, short, default_value = "3")]
#[clap(env, long, short, default_value = "3")]
pub depth: usize,

/// Compare against installed weidu log, note this is best effort
#[clap(long, short, action=ArgAction::SetTrue)]
#[clap(env, long, short, action=ArgAction::SetTrue)]
pub skip_installed: bool,

/// If a warning occurs in the weidu child process exit
#[clap(long, short, action=ArgAction::SetTrue)]
#[clap(env, long, short, action=ArgAction::SetTrue)]
pub abort_on_warnings: bool,

/// Timeout time per mod in seconds, default is 1 hour
#[clap(env, long, short, default_value = "3600")]
pub timeout: usize,
}

fn parse_absolute_path(arg: &str) -> Result<PathBuf, String> {
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ fn main() {
&args.game_directory,
&weidu_mod,
&args.language,
args.timeout,
) {
InstallationResult::Fail(message) => {
panic!(
Expand Down
1 change: 1 addition & 0 deletions src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pub enum State {
RequiresInput { question: String },
InProgress,
TimedOut,
Completed,
CompletedWithErrors { error_details: String },
CompletedWithWarnings,
Expand Down
30 changes: 22 additions & 8 deletions src/weidu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ use std::{
panic,
path::PathBuf,
process::{Child, ChildStdout, Command, Stdio},
sync::mpsc::{self, Receiver, TryRecvError},
sync::{
atomic::{AtomicUsize, Ordering},
mpsc::{self, Receiver, TryRecvError},
Arc,
},
thread,
};

Expand Down Expand Up @@ -42,6 +46,7 @@ pub fn install(
game_directory: &PathBuf,
weidu_mod: &ModComponent,
language: &str,
timeout: usize,
) -> InstallationResult {
let weidu_args = generate_args(weidu_mod, language);
let mut command = Command::new(weidu_binary);
Expand All @@ -54,16 +59,16 @@ pub fn install(
.spawn()
.expect("Failed to spawn weidu process");

handle_io(child)
handle_io(child, timeout)
}

pub fn handle_io(mut child: Child) -> InstallationResult {
pub fn handle_io(mut child: Child, timeout: usize) -> InstallationResult {
let mut weidu_stdin = child.stdin.take().unwrap();
let wait_counter = Arc::new(AtomicUsize::new(0));
let raw_output_receiver = create_output_reader(child.stdout.take().unwrap());
let (sender, parsed_output_receiver) = mpsc::channel::<State>();
parse_raw_output(sender, raw_output_receiver);
parse_raw_output(sender, raw_output_receiver, wait_counter.clone(), timeout);

let mut wait_counter = 0;
loop {
match parsed_output_receiver.try_recv() {
Ok(state) => {
Expand All @@ -80,6 +85,13 @@ pub fn handle_io(mut child: Child) -> InstallationResult {
.expect("Failed to send final ENTER to weidu process");
return InstallationResult::Fail(error_details);
}
State::TimedOut => {
log::error!(
"Weidu process seem to have been running for {} seconds, exiting",
timeout
);
return InstallationResult::Fail("Timed out".to_string());
}
State::CompletedWithWarnings => {
log::warn!("Weidu process seem to have completed with warnings");
weidu_stdin
Expand All @@ -103,11 +115,13 @@ pub fn handle_io(mut child: Child) -> InstallationResult {
}
}
Err(TryRecvError::Empty) => {
log::info!("{}\r", ".".repeat(wait_counter));
log::info!(
"{}\r",
".".repeat(wait_counter.load(Ordering::Relaxed) % 10)
);
std::io::stdout().flush().expect("Failed to flush stdout");

wait_counter += 1;
wait_counter %= 10;
wait_counter.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
sleep(1000);

std::io::stdout().flush().expect("Failed to flush stdout");
Expand Down
19 changes: 16 additions & 3 deletions src/weidu_parser.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
use std::{
sync::mpsc::{Receiver, Sender, TryRecvError},
sync::{
atomic::{AtomicUsize, Ordering},
mpsc::{Receiver, Sender, TryRecvError},
Arc,
},
thread,
};

Expand Down Expand Up @@ -40,7 +44,12 @@ enum ParserState {
LookingForInterestingOutput,
}

pub fn parse_raw_output(sender: Sender<State>, receiver: Receiver<String>) {
pub fn parse_raw_output(
sender: Sender<State>,
receiver: Receiver<String>,
wait_count: Arc<AtomicUsize>,
timeout: usize,
) {
let mut current_state = ParserState::LookingForInterestingOutput;
let mut question = String::new();
sender
Expand Down Expand Up @@ -101,7 +110,11 @@ pub fn parse_raw_output(sender: Sender<State>, receiver: Receiver<String>) {
question = String::new();
}
_ => {
// TODO: Exit here if we come here too much
if wait_count.load(Ordering::Relaxed) >= timeout {
sender
.send(State::TimedOut)
.expect("Could send timeout error");
}
// there is no new weidu output and we are not waiting for any, so there is nothing to do
}
}
Expand Down

0 comments on commit 8102734

Please sign in to comment.