Skip to content

Commit

Permalink
Address process booting determinism
Browse files Browse the repository at this point in the history
The method we're using to launch a daemon process does not give us guarantees that `agentmon_loop --path` will be executed by the time the process boots. To address this we can loop and re-check for some period of time.

This method utilizes the output log from agentmon loop as directed by the spawn daemon command.
  • Loading branch information
schneems committed Sep 12, 2023
1 parent 7cf566a commit c78629e
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 18 deletions.
29 changes: 16 additions & 13 deletions buildpacks/ruby/src/bin/agentmon_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,22 @@ fn main() {
});

match agentmon.try_exists() {
Ok(true) => loop {
match run(&agentmon, &agentmon_args) {
Ok(status) => {
eprintln!("Process completed with status={status}, sleeping {SLEEP_FOR:?}");
}
Err(error) => {
eprintln!(
"Process could not run due to error. {error}, sleeping {SLEEP_FOR:?}"
);
}
};
sleep(SLEEP_FOR);
},
Ok(true) => {
eprintln!("Booting agentmon_loop");
loop {
match run(&agentmon, &agentmon_args) {
Ok(status) => {
eprintln!("Process completed with status={status}, sleeping {SLEEP_FOR:?}");
}
Err(error) => {
eprintln!(
"Process could not run due to error. {error}, sleeping {SLEEP_FOR:?}"
);
}
};
sleep(SLEEP_FOR);
}
}
Ok(false) => {
eprintln!("Path does not exist {path}", path = agentmon.display());
exit(1);
Expand Down
26 changes: 21 additions & 5 deletions buildpacks/ruby/tests/integration_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use libcnb_test::{
ContainerContext, TestRunner,
};
use std::thread;
use std::time::Duration;
use std::time::{Duration, Instant};
use thiserror::__private::DisplayAsDisplay;
use ureq::Response;

Expand Down Expand Up @@ -125,17 +125,33 @@ fn test_barnes_app() {
ContainerConfig::new()
.entrypoint("launcher")
.envs(vec![
("HEROKU_METRICS_URL", "example.com"),
("DYNO", "web.1"),
("PORT", "1234"),
("AGENTMON_DEBUG", "1"),
("HEROKU_METRICS_URL", "example.com"),
])
.command(["ps x"]),
.command(["while true; do sleep 1; done"]),
|container| {
let log_output = container.logs_wait();
let boot_message = "Booting agentmon_loop";
let mut agentmon_log = String::new();

let started = Instant::now();
while started.elapsed() < Duration::from_secs(20) {
if agentmon_log.contains(boot_message) {
break;
}

std::thread::sleep(frac_seconds(0.1));
agentmon_log = container
.shell_exec("cat /layers/heroku_ruby/metrics_agent/output.log")
.stdout;
}

let log_output = container.logs_now();
println!("{}", log_output.stdout);
println!("{}", log_output.stderr);

assert_contains!(log_output.stdout, "agentmon_loop --path");
assert_contains!(agentmon_log, boot_message);
},
);
},
Expand Down

0 comments on commit c78629e

Please sign in to comment.