Web: a failed render worker start no longer shifts the other workers' slots (#229)
This commit is contained in:
parent
b70ae1741e
commit
d35d0a3dd2
|
|
@ -332,11 +332,46 @@ impl CacheWatch {
|
|||
}
|
||||
}
|
||||
|
||||
/// Hands out the positions that render workers will have in the main thread's worker list.
|
||||
/// A worker that fails to start gets no position, so the position a callback captures stays the
|
||||
/// index of its own worker in that list (#229).
|
||||
#[derive(Debug, Default)]
|
||||
pub struct WorkerSlots {
|
||||
next: usize,
|
||||
}
|
||||
|
||||
impl WorkerSlots {
|
||||
/// The position the worker being started will have, if it comes up.
|
||||
pub fn peek(&self) -> usize {
|
||||
self.next
|
||||
}
|
||||
|
||||
/// The worker at [`Self::peek`] came up and was added to the list.
|
||||
pub fn commit(&mut self) {
|
||||
self.next += 1;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use lightcraft_engine::Session;
|
||||
|
||||
// Issue #229: a failed worker attempt must not shift the positions of the workers after it
|
||||
#[test]
|
||||
fn a_failed_worker_attempt_leaves_no_gap_in_the_slots() {
|
||||
let mut slots = WorkerSlots::default();
|
||||
let mut taken = Vec::new();
|
||||
for attempt_ok in [false, true, true, true] {
|
||||
let i = slots.peek();
|
||||
if attempt_ok {
|
||||
taken.push(i);
|
||||
slots.commit();
|
||||
}
|
||||
}
|
||||
assert_eq!(taken, vec![0, 1, 2]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clearing_index_changes_disk_namespace_and_survives_restart() {
|
||||
let key = lightcraft_preview::hash_bytes(b"thumbnail");
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ use wasm_bindgen::JsCast;
|
|||
use wasm_bindgen::prelude::*;
|
||||
|
||||
use crate::backend::Backend;
|
||||
use crate::wire::{CacheWatch, ThumbIndex, WireJob, WorkerCore, thumb_storage_key};
|
||||
use crate::wire::{CacheWatch, ThumbIndex, WireJob, WorkerCore, WorkerSlots, thumb_storage_key};
|
||||
|
||||
/// Storage key of the thumbnail index.
|
||||
pub const THUMB_INDEX: &str = "thumbs/index.json";
|
||||
|
|
@ -245,14 +245,17 @@ impl Workers {
|
|||
log::warn!("render workers: no compiled module on the page (window.lightcraftModule); rendering on the main thread");
|
||||
return w;
|
||||
}
|
||||
for i in 0..n {
|
||||
let mut slots = WorkerSlots::default();
|
||||
for attempt in 0..n {
|
||||
// The callbacks name their worker by its place in `workers`; a failed attempt takes none.
|
||||
let i = slots.peek();
|
||||
let opts = web_sys::WorkerOptions::new();
|
||||
opts.set_type(web_sys::WorkerType::Module);
|
||||
opts.set_name(&format!("lightcraft-render-{i}"));
|
||||
opts.set_name(&format!("lightcraft-render-{attempt}"));
|
||||
let worker = match web_sys::Worker::new_with_options("./worker.js", &opts) {
|
||||
Ok(x) => x,
|
||||
Err(e) => {
|
||||
log::warn!("render worker {i}: {e:?}");
|
||||
log::warn!("render worker {attempt}: {e:?}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
|
@ -268,10 +271,15 @@ impl Workers {
|
|||
set(&init, "module", &module);
|
||||
set(&init, "store", &store.into());
|
||||
if let Err(e) = worker.post_message(&init) {
|
||||
log::warn!("render worker {i}: {e:?}");
|
||||
log::warn!("render worker {attempt}: {e:?}");
|
||||
// It never joins the list, so it must not answer to the index of the next worker.
|
||||
worker.set_onmessage(None);
|
||||
worker.set_onerror(None);
|
||||
worker.terminate();
|
||||
continue;
|
||||
}
|
||||
w.0.borrow_mut().workers.push(W { worker, ready: false, dead: false, busy: None });
|
||||
slots.commit();
|
||||
}
|
||||
w
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue