use the query parameter to store the bisection id to allow refreshes

This commit is contained in:
nora 2022-11-25 22:54:09 +01:00
parent edcda4d5b5
commit 43e63d28d2
No known key found for this signature in database
2 changed files with 79 additions and 37 deletions

View file

@ -85,18 +85,45 @@ impl<T> Struct<T> {
></textarea> ></textarea>
<script> <script>
let BASE_URL = `${document.location}`; let BASE_URL = `${document.location}`.split("?")[0];
if (!BASE_URL.endsWith("/")) { if (!BASE_URL.endsWith("/")) {
// ugh, i hate url paths and their subtle interactions with things // ugh, i hate url paths and their subtle interactions with things
BASE_URL = `${BASE_URL}/`; BASE_URL = `${BASE_URL}/`;
} }
// The important HTML elements.
const htmlStatus = document.getElementById("status"); const htmlStatus = document.getElementById("status");
const htmlResult = document.getElementById("result"); const htmlResult = document.getElementById("result");
const htmlCode = document.getElementById("code");
// A list of all ongoing fetches in fetchAndUpdate.
const fetches = [];
let bisecting = false; let bisecting = false;
initialLoad();
document.getElementById("bisect-form").addEventListener("submit", (e) => {
e.preventDefault();
submitForm();
});
async function initialLoad() {
const params = document.location.search;
const urlParams = new URLSearchParams(params);
const bisection = urlParams.get("bisection");
if (bisection) {
const response = await fetchAndUpdate(bisection);
if (!response) {
fatal(`Bisection with ID \`${bisection}\` not found.`);
return;
}
code.value = response.code;
}
}
// Report a fatal error to the console and screen.
function fatal(err, ...extra) { function fatal(err, ...extra) {
console.error(err, ...(extra || [])); console.error(err, ...(extra || []));
htmlStatus.innerHTML = `ERROR: ${err}`; htmlStatus.innerHTML = `ERROR: ${err}`;
@ -123,16 +150,13 @@ impl&lt;T&gt; Struct&lt;T&gt; {
bisect(options); bisect(options);
} }
document.getElementById("bisect-form").addEventListener("submit", (e) => {
e.preventDefault();
submitForm();
});
async function bisect(options) { async function bisect(options) {
if (bisecting) { if (bisecting) {
return; return;
} }
fetches.forEach((fetchId) => clearTimeout(fetchId));
bisecting = true; bisecting = true;
htmlStatus.classList.remove("error"); htmlStatus.classList.remove("error");
@ -167,6 +191,11 @@ impl&lt;T&gt; Struct&lt;T&gt; {
} }
const data = await fetched.json(); const data = await fetched.json();
jobId = data?.job_id; jobId = data?.job_id;
const urlParams = new URLSearchParams(window.location.search);
urlParams.set("bisection", jobId);
window.location.search = urlParams;
if (!jobId) { if (!jobId) {
fatal("Received invalid response", data); fatal("Received invalid response", data);
return; return;
@ -176,38 +205,51 @@ impl&lt;T&gt; Struct&lt;T&gt; {
return; return;
} }
async function tryFetch() { fetchAndUpdate(jobId);
let response; }
try {
const fetched = await fetch(`${BASE_URL}bisect/${jobId}`); async function fetchAndUpdate(jobId) {
if (!fetched.ok) { htmlStatus.innerHTML = `Waiting for result, job id=${jobId}`;
fatal("Failed to fetch", fetched); htmlStatus.classList.remove("hidden");
return;
} let response;
response = await fetched.json(); try {
} catch (e) { const fetched = await fetch(`${BASE_URL}bisect/${jobId}`);
fatal(e); if (!fetched.ok) {
fatal("Failed to fetch bisection.", fetched);
return; return;
} }
response = await fetched.json();
if (response.status.status !== "InProgress") { } catch (e) {
bisecting = false; fatal(e);
console.log(response.status.output); return;
htmlStatus.classList.add("hidden");
htmlResult.classList.remove("hidden");
htmlResult.value = response.status.output;
htmlStatus.innerHTML = `Bisected job ${jobId}`;
} else {
console.log("Waiting for bisection", response.status.status);
setTimeout(tryFetch, 3000);
}
} }
tryFetch(); if (!response) {
console.log("Waiting for bisection", response.status.status);
const timeout = setTimeout(() => fetchAndUpdate(jobId), 3000);
fetches.push(timeout);
return response;
}
htmlStatus.innerHTML = `Waiting for result, job id=${jobId}`; const status = response.status;
if (response.status.status !== "InProgress") {
bisecting = false;
console.log(response.status.output);
htmlStatus.classList.add("hidden");
htmlResult.classList.remove("hidden");
htmlResult.value = response.status.output;
htmlStatus.innerHTML = `Bisected job ${jobId}`;
} else {
console.log("Waiting for bisection", response.status.status);
const timeout = setTimeout(() => fetchAndUpdate(jobId), 3000);
fetches.push(timeout);
}
return response;
} }
</script> </script>
</body> </body>

View file

@ -22,7 +22,7 @@ use tracing::{error, info, metadata::LevelFilter};
use tracing_subscriber::EnvFilter; use tracing_subscriber::EnvFilter;
use uuid::Uuid; use uuid::Uuid;
type SendChannel = Arc<Mutex<mpsc::Sender<Job>>>; type SendChannel = Arc<Mutex<mpsc::SyncSender<Job>>>;
type Conn = Arc<Mutex<Connection>>; type Conn = Arc<Mutex<Connection>>;
#[tokio::main] #[tokio::main]
@ -37,7 +37,7 @@ async fn main() -> color_eyre::Result<()> {
) )
.init(); .init();
let (job_queue_send, job_queue_recv) = mpsc::channel(); // FIXME: make this a sync_channel because bounds are cool let (job_queue_send, job_queue_recv) = mpsc::sync_channel(10);
let sqlite_db = env::var("SQLITE_DB").unwrap_or_else(|_| "bisect.sqlite".to_string()); let sqlite_db = env::var("SQLITE_DB").unwrap_or_else(|_| "bisect.sqlite".to_string());
@ -62,7 +62,7 @@ async fn main() -> color_eyre::Result<()> {
std::thread::spawn(|| bisect::bisect_worker(job_queue_recv, worker_conn)); std::thread::spawn(|| bisect::bisect_worker(job_queue_recv, worker_conn));
info!("Starting up server"); info!("Starting up server on port 4000");
axum::Server::bind(&"0.0.0.0:4000".parse().unwrap()) axum::Server::bind(&"0.0.0.0:4000".parse().unwrap())
.serve(app.into_make_service()) .serve(app.into_make_service())