implement correct status handling and add snakemake profile

This commit is contained in:
Johannes Heuel
2022-09-17 18:55:37 +02:00
parent 6e925b731e
commit a4a84844fa
11 changed files with 833 additions and 67 deletions

View File

@@ -10,4 +10,11 @@ path = "../zoidberg_lib"
version = "0.1.0"
[dependencies]
reqwest = { version = "0.11", features = ["blocking", "json"] }
# reqwest = { version = "0.11", features = ["blocking", "json"] }
reqwest = { version = "0.11"}
serde_json = "1.0.85"
retry = "2.0.0"
reqwest-retry = "0.1.5"
reqwest-middleware = "0.1.6"
tokio = { version = "1", features = ["full"] }
clap = "3.2.22"

View File

@@ -1,8 +1,11 @@
use core::time::Duration;
use reqwest::blocking::Client;
use reqwest::header;
use clap::{App, Arg};
use reqwest::{header, Client, ClientBuilder};
use std::error::Error;
use std::process::Command;
use std::time::Duration;
use std::{thread, time};
use zoidberg_lib::types::Update;
use zoidberg_lib::types::{Job, RegisterResponse, Status, Update};
fn build_client(secret: &str) -> Client {
let cookie = format!("secret={}", secret);
@@ -14,53 +17,122 @@ fn build_client(secret: &str) -> Client {
.unwrap_or_else(|_| panic!("invalid header value {}", &cookie)),
);
Client::builder()
.default_headers(headers)
ClientBuilder::new()
.timeout(Duration::from_secs(15))
.default_headers(headers)
.build()
.expect("Could not create HTTP client")
.expect("Could not create client")
}
fn main() {
// test get request to index
let res = build_client("some_secret")
.get("http://localhost:8080/")
.send()
.expect("Could not send get request");
#[derive(Debug)]
struct Worker {
id: i32,
}
println!("Status: {}", res.status());
println!("Headers:\n{:#?}", res.headers());
let body = res.text().unwrap();
println!("Body:\n{}", body);
(0..10).for_each(|_| {
// test get request to /register
impl Worker {
async fn new(server: &str) -> Result<Worker, Box<dyn Error>> {
let res = build_client("some_secret")
.get("http://localhost:8080/register")
.get(format!("{}/register", server))
.send()
.expect("Could not send get request");
.await?;
let body = res.text().await?;
let r: RegisterResponse = serde_json::from_str(&body)?;
println!("registered worker with id: {}", &r.id);
Ok(Worker { id: r.id })
}
async fn update(self: &Self, jobs: &[Job]) -> Result<(), Box<dyn Error>> {
let updates: Vec<Update> = jobs
.iter()
.map(|job| Update {
worker: self.id,
job: job.id,
status: job.status.clone(),
})
.collect();
let body = build_client("some_secret")
.post("http://localhost:8080/update")
.json(&updates)
.send()
.await?
.text()
.await?;
println!("Status: {}", res.status());
println!("Headers:\n{:#?}", res.headers());
let body = res.text().unwrap();
println!("Body:\n{}", body);
});
Ok(())
}
// test post request to /update
let update = Update {
id: 99,
status: "hi".to_string(),
};
async fn fetch(self: &Self) -> Result<Vec<Job>, Box<dyn Error>> {
let res = build_client("some_secret")
.get("http://localhost:8080/fetch")
.send()
.await?;
let body = res.text().await?;
let jobs: Vec<Job> = serde_json::from_str(&body)?;
Ok(jobs)
}
let res = build_client("some_secret")
.post("http://localhost:8080/update")
.json(&update)
.send()
.expect("Could not send get request");
async fn run(self: &Self, job: &Job) -> Result<(), Box<dyn Error>> {
let output = Command::new("bash").arg("-c").arg(&job.cmd).output()?;
println!("Status: {}", res.status());
println!("Headers:\n{:#?}", res.headers());
let body = res.text().unwrap();
println!("Body:\n{}", body);
println!(
"command: {}\nstdout: {}\nstderr: {}",
&job.cmd,
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);
match output.status.success() {
true => Ok(()),
false => Err(Box::from("Job failed")),
}
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
const VERSION: &str = env!("CARGO_PKG_VERSION");
let matches = App::new("Zoidberg client")
.version(VERSION)
.author("Johannes Heuel")
.arg(
Arg::with_name("server")
.takes_value(true)
.required(true)
.help("Set Zoidberg server address"),
)
.get_matches();
let server = matches.value_of("server").unwrap();
let client = Worker::new(server).await.expect("Could not create client");
let pause = time::Duration::from_secs(0);
let long_pause = time::Duration::from_secs(2);
let extra_long_pause = time::Duration::from_secs(4);
loop {
if let Ok(jobs) = client.fetch().await {
// if there are no jobs, wait a little longer
if jobs.len() == 0 {
thread::sleep(long_pause);
}
for job in jobs {
let status = match client.run(&job).await {
Ok(()) => Status::Completed,
Err(..) => Status::Failed,
};
let n = &[Job { status, ..job }];
if let Err(error) = client.update(n).await {
println!("Could not update job: {}", error);
}
}
} else {
// wait a little longer whenever job fetching fails
thread::sleep(extra_long_pause);
}
thread::sleep(pause);
}
}