Implement /api/runner/status

This commit is contained in:
Joscha 2023-08-10 18:47:44 +02:00
parent 5c8c037417
commit c713abc5d3
11 changed files with 296 additions and 29 deletions

91
src/server/web/api.rs Normal file
View file

@ -0,0 +1,91 @@
mod auth;
use std::sync::{Arc, Mutex};
use askama_axum::{IntoResponse, Response};
use axum::{
extract::State,
headers::{authorization::Basic, Authorization},
http::StatusCode,
routing::post,
Json, Router, TypedHeader,
};
use sqlx::SqlitePool;
use time::OffsetDateTime;
use crate::{
config::Config,
server::{
runners::{RunnerInfo, Runners},
BenchRepo, Server,
},
shared::{BenchMethod, RunnerRequest, ServerResponse, Work},
somehow,
};
async fn post_status(
TypedHeader(auth): TypedHeader<Authorization<Basic>>,
State(config): State<&'static Config>,
State(db): State<SqlitePool>,
State(bench_repo): State<Option<BenchRepo>>,
State(runners): State<Arc<Mutex<Runners>>>,
Json(request): Json<RunnerRequest>,
) -> somehow::Result<Response> {
let name = match auth::authenticate(config, auth) {
Ok(name) => name,
Err(response) => return Ok(response),
};
let now = OffsetDateTime::now_utc();
let queue = sqlx::query_scalar!(
"\
SELECT hash FROM queue \
ORDER BY priority DESC, unixepoch(date) DESC, hash ASC \
"
)
.fetch_all(&db)
.await?;
let mut guard = runners.lock().unwrap();
guard.clean(now);
if !guard.verify(&name, &request.secret) {
return Ok((StatusCode::UNAUTHORIZED, "invalid secret").into_response());
}
guard.update(
name.clone(),
RunnerInfo::new(request.secret, now, request.status),
);
let work = match request.request_work {
true => guard.find_free_work(&queue),
false => None,
};
let abort_work = guard.should_abort_work(&name);
drop(guard);
// Find new work
let work = if let Some(hash) = work {
let bench = match bench_repo {
Some(bench_repo) => BenchMethod::BenchRepo {
hash: bench_repo.0.to_thread_local().head_id()?.to_string(),
},
None => BenchMethod::Internal,
};
Some(Work {
hash: hash.to_string(),
bench,
})
} else {
None
};
Ok(Json(ServerResponse { work, abort_work }).into_response())
}
pub fn router(server: &Server) -> Router<Server> {
if server.repo.is_none() {
return Router::new().route("/api/runner/status", post(post_status));
}
// TODO Add routes
Router::new()
}