mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-26 02:57:34 -06:00
Job workers remembered the files they were sent by path and byte length, so footage replaced by different bytes of the same length at the same path was never resent: a Render Queue export through a reused worker rendered the old image while the page showed the new one. Frame workers remembered paths only, so they never got a replacement at all. Every write of a stored file now gets a version, and both kinds of worker remember the version they were sent. Tests: versions_change_with_every_write (store) and apps/effectcraft-web/tests/workers.mjs (Node, fake Worker: the replacement is sent once, an unchanged file not again). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018gnTnH3Jmk5zr4tMq1Mc9f
57 lines
2.1 KiB
JavaScript
57 lines
2.1 KiB
JavaScript
// Job-worker plumbing of the web app (js/host.js) under Node with a fake Worker,
|
|
// no browser or Wasm build needed:
|
|
//
|
|
// node apps/effectcraft-web/tests/workers.mjs
|
|
//
|
|
// - A reused worker is sent a file again when it was replaced, even by one of the same size
|
|
// (#218), and not when it is unchanged.
|
|
// Exits non-zero on failure.
|
|
import assert from "node:assert/strict";
|
|
import { dirname, join } from "node:path";
|
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
|
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
globalThis.self = globalThis;
|
|
|
|
// A Worker that starts on "init" and finishes each job at once.
|
|
let failStart = false;
|
|
const workers = [];
|
|
class FakeWorker {
|
|
constructor() {
|
|
this.posted = [];
|
|
this.terminated = false;
|
|
workers.push(this);
|
|
}
|
|
postMessage(m) {
|
|
this.posted.push(m);
|
|
setTimeout(() => {
|
|
if (m.type === "init") {
|
|
if (failStart) this.onerror?.({ message: "worker failed to start" });
|
|
else this.onmessage?.({ data: { type: "ready" } });
|
|
} else if (m.type === "job") {
|
|
this.onmessage?.({ data: { type: "reply", json: "{}", done: true } });
|
|
}
|
|
});
|
|
}
|
|
terminate() {
|
|
this.terminated = true;
|
|
}
|
|
}
|
|
globalThis.Worker = FakeWorker;
|
|
|
|
const host = await import(pathToFileURL(join(here, "../js/host.js")));
|
|
const run = (id, files) =>
|
|
new Promise((resolve) => host.workerRun(id, "{}", files, "http://localhost/", (kind, json) => kind !== "file" && resolve({ kind, json })));
|
|
const sent = (w) => w.posted.filter((m) => m.type === "file").map((m) => m.bytes[0]);
|
|
|
|
// #218: equal-length replacement.
|
|
const red = new Uint8Array(512).fill(1);
|
|
const blue = new Uint8Array(512).fill(2);
|
|
assert.equal((await run(1, [["/collision.png", red, 1]])).kind, "reply");
|
|
assert.equal((await run(2, [["/collision.png", blue, 2]])).kind, "reply");
|
|
assert.equal((await run(3, [["/collision.png", blue, 2]])).kind, "reply");
|
|
assert.equal(workers.length, 1, "the worker is reused");
|
|
assert.deepEqual(sent(workers[0]), [1, 2], "the replacement is sent once, the unchanged file not again");
|
|
|
|
console.log("workers: ok");
|