Follow-up to #50, which fixed response routing in WorkerBridge but deliberately left cancellation out of scope.
Problem
The worker processes self.onmessage synchronously to completion (src/worker/sdfWorker.ts:165). There is no way to drop queued or in-progress work. Every request now settles, but a 256³ export still blocks every evaluate queued behind it — the viewport stalls for the duration of an export.
evalSeq only discards results. The work itself always runs. Editing the tree ten times during an export queues ten full evaluations that will all execute after it finishes, and nine of their results get thrown away.
Options
Cancel message + cooperative checks. Keep a set of cancelled rids in the worker; check it inside the recursion in evaluateCPUWithProgress (sdfWorker.ts:93) and in the simplifyMesh progress callback. Cancels queued work cheaply and interrupts in-progress work at the next check. Requires threading the check through the hot loops, and granularity is bounded by how often you check.
Terminate and respawn. worker.terminate() kills in-progress work immediately, then construct a fresh Worker. Simple and total, but pays worker startup on every cancel and drops every other in-flight request — so the bridge would have to reject them all, and the ready handshake has to be re-awaited.
Second worker for exports. Sidesteps head-of-line blocking entirely rather than cancelling: evaluates never queue behind an export. Doesn't help with rapid successive evaluates superseding each other, and doubles worker memory.
These compose — a dedicated export worker plus cooperative cancellation for evaluates may be the right end state.
Notes
The correlation-id map in WorkerBridge already gives cancellation a place to hook: a cancelled request needs to be settled (rejected, or resolved with null) and removed from pending, preserving the HandlerAgreesWithSettled invariant documented in specs/README.md.
Worth extending specs/WorkerBridgeFixed.tla once an approach is chosen. The interesting property is not just "cancelled requests settle" but that a cancel racing with an in-flight completion does not settle the request twice or strand it — which is exactly the shape of bug the original spec caught.
Follow-up to #50, which fixed response routing in
WorkerBridgebut deliberately left cancellation out of scope.Problem
The worker processes
self.onmessagesynchronously to completion (src/worker/sdfWorker.ts:165). There is no way to drop queued or in-progress work. Every request now settles, but a 256³ export still blocks every evaluate queued behind it — the viewport stalls for the duration of an export.evalSeqonly discards results. The work itself always runs. Editing the tree ten times during an export queues ten full evaluations that will all execute after it finishes, and nine of their results get thrown away.Options
Cancel message + cooperative checks. Keep a set of cancelled
rids in the worker; check it inside the recursion inevaluateCPUWithProgress(sdfWorker.ts:93) and in thesimplifyMeshprogress callback. Cancels queued work cheaply and interrupts in-progress work at the next check. Requires threading the check through the hot loops, and granularity is bounded by how often you check.Terminate and respawn.
worker.terminate()kills in-progress work immediately, then construct a freshWorker. Simple and total, but pays worker startup on every cancel and drops every other in-flight request — so the bridge would have to reject them all, and thereadyhandshake has to be re-awaited.Second worker for exports. Sidesteps head-of-line blocking entirely rather than cancelling: evaluates never queue behind an export. Doesn't help with rapid successive evaluates superseding each other, and doubles worker memory.
These compose — a dedicated export worker plus cooperative cancellation for evaluates may be the right end state.
Notes
The correlation-id map in
WorkerBridgealready gives cancellation a place to hook: a cancelled request needs to be settled (rejected, or resolved withnull) and removed frompending, preserving theHandlerAgreesWithSettledinvariant documented inspecs/README.md.Worth extending
specs/WorkerBridgeFixed.tlaonce an approach is chosen. The interesting property is not just "cancelled requests settle" but that a cancel racing with an in-flight completion does not settle the request twice or strand it — which is exactly the shape of bug the original spec caught.