feat(benchmark): auto launching verdaccio (#155)

This commit is contained in:
Khải
2023-10-17 19:49:28 +07:00
committed by GitHub
parent 768e4eb39b
commit cbb0dbaa9b
3 changed files with 137 additions and 1 deletions

View File

@@ -12,6 +12,10 @@ pub struct CliArgs {
#[clap(long, short, default_value = "http://localhost:4873")]
pub registry: String,
/// Automatically launch verdaccio if local registry doesn't response.
#[clap(long, short = 'V')]
pub verdaccio: bool,
/// Path to the git repository of pacquet.
#[clap(long, short = 'R', default_value = ".")]
pub repository: PathBuf,

View File

@@ -1,5 +1,6 @@
mod cli_args;
mod fixtures;
mod verdaccio;
mod verify;
mod work_env;
@@ -8,6 +9,7 @@ async fn main() {
let cli_args::CliArgs {
scenario,
registry,
verdaccio,
repository,
package_json,
hyperfine_options,
@@ -20,7 +22,22 @@ async fn main() {
std::fs::create_dir_all(&work_env).expect("create work env");
}
let work_env = std::fs::canonicalize(work_env).expect("get absolute path to work env");
verify::ensure_virtual_registry(&registry).await;
let verdaccio = if verdaccio {
verify::ensure_program("verdaccio");
verdaccio::VerdaccioOptions {
client: &Default::default(),
listen: &registry,
stdout: &work_env.join("verdaccio.stdout.log"),
stderr: &work_env.join("verdaccio.stderr.log"),
max_retries: 10,
retry_delay: tokio::time::Duration::from_millis(500),
}
.spawn_if_necessary()
.await
} else {
verify::ensure_virtual_registry(&registry).await;
None
};
verify::ensure_git_repo(&repository);
verify::validate_revision_list(&revisions);
verify::ensure_program("bash");
@@ -39,4 +56,5 @@ async fn main() {
package_json,
}
.run();
drop(verdaccio); // terminate verdaccio if exists
}

View File

@@ -0,0 +1,114 @@
use crate::verify::ensure_program;
use pipe_trait::Pipe;
use reqwest::Client;
use std::{
fs::File,
path::Path,
process::{Child, Command, Stdio},
};
use tokio::time::{sleep, Duration};
#[derive(Debug)]
pub struct Verdaccio {
process: Child,
}
impl Drop for Verdaccio {
fn drop(&mut self) {
let Verdaccio { process } = self;
let pid = process.id();
eprintln!("info: Terminating verdaccio with the kill command (kill {pid})...");
match Command::new("kill").arg(process.id().to_string()).output() {
Err(error) => {
eprintln!("warn: Failed to terminate verdaccio with the kill command: {error}");
}
Ok(output) => {
if output.status.success() {
eprintln!("info: Verdaccio terminated");
return;
}
let stderr = String::from_utf8_lossy(&output.stderr);
eprintln!("warn: Failed to terminate verdaccio with the kill command: {stderr}");
}
}
eprintln!("info: Terminating verdaccio with SIGKILL...");
if let Err(error) = process.kill() {
eprintln!("warn: Failed to terminate verdaccio with SIGKILL: {error}");
} else {
eprintln!("info: Verdaccio terminated");
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct VerdaccioOptions<'a> {
pub client: &'a Client,
pub listen: &'a str,
pub stdout: &'a Path,
pub stderr: &'a Path,
pub max_retries: usize,
pub retry_delay: Duration,
}
impl<'a> VerdaccioOptions<'a> {
async fn is_registry_ready(self) -> bool {
let VerdaccioOptions { client, listen, .. } = self;
let Err(error) = client.head(listen).send().await else {
return true;
};
if error.is_connect() {
eprintln!("info: {error}");
return false;
}
panic!("{error}");
}
async fn wait_for_registry(self) {
let VerdaccioOptions { max_retries, retry_delay, .. } = self;
let mut retries = max_retries;
while !self.is_registry_ready().await {
retries = retries.checked_sub(1).unwrap_or_else(|| {
panic!("Failed to check for the registry for {max_retries} times")
});
sleep(retry_delay).await;
}
}
async fn spawn(self) -> Verdaccio {
let VerdaccioOptions { listen, stdout, stderr, .. } = self;
ensure_program("verdaccio");
let process = Command::new("verdaccio")
.arg("--listen")
.arg(listen)
.stdin(Stdio::null())
.stdout(File::create(stdout).expect("create file for stdout"))
.stderr(File::create(stderr).expect("create file for stderr"))
.spawn()
.expect("spawn verdaccio");
self.wait_for_registry().await;
Verdaccio { process }
}
pub async fn spawn_if_necessary(self) -> Option<Verdaccio> {
let VerdaccioOptions { listen, .. } = self;
if self.is_registry_ready().await {
eprintln!("info: {listen} is already available");
None
} else {
eprintln!("info: spawning verdaccio...");
self.spawn().await.pipe(Some)
}
}
}