Skip to content

Switch the site to the Rust planner, in a Web Worker (port stage 12b) - #174

Merged
wormeyman merged 1 commit into
mainfrom
port/stage-12b
Oct 21, 2026
Merged

wormeyman merged 1 commit into
mainfrom
port/stage-12b

Conversation

@wormeyman

@wormeyman wormeyman commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

Stage 12b of #138. Merging this PR deploys the live site. After the merge, https://oilfieldplanner.factorygamefan.com plans with the Rust module instead of the .NET WASM bundle.

What changes

  • Build. npm run build-wasm runs cargo build --release -p planner-wasm --target wasm32-unknown-unknown inside rust/, so the pinned toolchain applies. It then copies planner.js and planner_wasm.wasm into src/vue/src/lib/planner-wasm/. That folder is gitignored except for planner.d.ts. Vite gives the .wasm and the worker hashed names under /assets/, which already have the one-year immutable cache. The /framework/ copy and its _headers note are gone.
  • Web Worker with a fallback. wasmPlanner.ts keeps the same plan(json) and normalize(json). It plans in a module Worker (plannerWorker.ts). If the worker fails to construct, reports an error, or doesn't answer its first request within 15 seconds, planning moves to the main thread for good and one warning is logged. Requests that were waiting on the worker run again on the main thread. Add ?planner=main-thread to the URL to force the fallback. Errors reach callers the same way as before. The old worker problem was .NET's runtime deadlocking in create(). The Rust module has no runtime, so that problem doesn't apply.
  • CI. The build-vue job and deploy-cloudflare.yml build the Rust module instead of the .NET publish. The deploy workflow's PR path filter is now rust/**, src/vue/** and the workflow file. The bundle check now requires the hashed .wasm and worker in dist/assets, and fails if anything still points at /framework/. The devcontainer job builds the planner on the runner, because its image has no Rust yet (stage 13). The .NET test jobs and projects are unchanged.
  • Docs. CLAUDE.md (build-wasm, Deployment headers, BrowserWasm) and README.md.

Checks

  • npm ci, npm run build-wasm, npm run build and npm test (51 tests) pass locally. Prettier and eslint are clean on the changed files.
  • Same output as the live site. Headless Chromium ran the 61 small-list blueprints through the real UI with the default options. Both the Worker path and the forced fallback match the live .NET site on all 61: same blueprint JSON, same plan table. The 61 results are all different and non-empty, so the match is not trivial.
Worker Forced fallback Live .NET site
First plan 156 ms 156 ms 1,146 ms
All 61 plans 6.6 s 6.2 s 11.5 s
Biggest big-list field 7.6 s 7.5 s 26.7 s
Longest page freeze during that plan none 7.4 s 26.6 s

The 61-plan times include the UI's own work, so the planner's own speed-up is larger than these numbers show.

  • Served by wrangler dev: no /framework/ requests. The .wasm came from /assets/ with Cache-Control: public, max-age=31536000, immutable.

Before merging

  • This PR is the first time CI builds the Rust module on GitHub's runners. Wait for this PR's "Deploy to Cloudflare Workers" run (build and check, no deploy) to pass.
  • Only headless Chromium was tested. Firefox and Safari were not.
  • Stage 13 cleanup: the root .gitignore still lists src/vue/public/framework/, and the devcontainer image should get Rust when .NET leaves it.

🤖 Generated with Claude Code

https://claude.ai/code/session_01PTSQFMEdmByebgkoa9RiqH

Summary by CodeRabbit

  • New Features
    • Updated the in-browser planner to use a Rust-based WebAssembly engine.
    • Planner calculations now run in a background worker to keep the interface responsive.
    • Added automatic fallback to main-thread execution if the worker cannot start or encounters an error.
    • Added an optional URL setting to force main-thread planner execution.
  • Documentation
    • Updated setup, deployment, and architecture documentation to reflect the new planner runtime and browser-based execution.

The site now loads rust/planner-wasm instead of the .NET WASM bundle.
npm run build-wasm builds it with cargo (inside rust/, so the pinned
toolchain applies) and copies planner.js and planner_wasm.wasm into
src/lib/planner-wasm, where Vite gives the .wasm a hashed name under
/assets/. /framework/ and its _headers note are gone.

wasmPlanner.ts keeps plan() and normalize(). It plans in a module
Worker (plannerWorker.ts) and falls back for good to the main thread
if the worker fails to construct, errors, or does not answer init
within 15 s. ?planner=main-thread forces the fallback.

CI and the deploy workflow build the Rust module instead of the .NET
publish, and the bundle check now looks for the hashed .wasm and
worker. The devcontainer job builds the planner on the runner until
the image gets Rust in stage 13. The .NET test jobs are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PTSQFMEdmByebgkoa9RiqH
@coderabbitai

coderabbitai Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 58de2359-08f1-4c7c-83c7-03825ef7a818
📥 Commits

Reviewing files that changed from the base of the PR and between 554f058 and 039bb3d.

📒 Files selected for processing: 12
  • .github/workflows/ci.yml
  • .github/workflows/deploy-cloudflare.yml
  • .github/workflows/devcontainer.yml
  • CLAUDE.md
  • README.md
  • src/vue/package.json
  • src/vue/public/_headers
  • src/vue/src/lib/planner-wasm/.gitignore
  • src/vue/src/lib/planner-wasm/planner.d.ts
  • src/vue/src/lib/plannerWorker.ts
  • src/vue/src/lib/wasmPlanner.ts
  • src/vue/vite.config.ts

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

📝 Walkthrough

The Vue planner now uses a Rust WebAssembly module through a Web Worker, with main-thread fallback. CI and deployment workflows build the module and check generated assets. Project documentation now describes the Rust planner and its asset handling.

Changes: Rust Planner WASM

Layer / File(s) Summary
Planner WASM package and worker protocol
src/vue/src/lib/planner-wasm/*, src/vue/src/lib/plannerWorker.ts, src/vue/package.json
The WASM declarations define initialization, planning, and normalization operations. The worker dispatches these operations and returns results or serialized errors. The build script compiles the Rust planner and copies its WASM output into the Vue library.
Worker execution and fallback
src/vue/src/lib/wasmPlanner.ts, src/vue/vite.config.ts
The planner wrapper routes requests through the worker when available and retries worker-loss failures on the main thread. It supports forced main-thread execution and falls back after worker startup errors or a 15-second initialization timeout. Vite emits workers as ES modules.
Build, deployment, and documentation
.github/workflows/ci.yml, .github/workflows/deploy-cloudflare.yml, .github/workflows/devcontainer.yml, CLAUDE.md, README.md, src/vue/public/_headers
The workflows build the Rust planner before Vue and deployment checks for hashed planner WASM and worker assets. Documentation describes Rust WASM builds, worker execution, fallback behavior, and caching for hashed assets.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant wasmPlanner
  participant plannerWorker
  participant RustPlannerWasm
  wasmPlanner->>plannerWorker: Send init request
  plannerWorker->>RustPlannerWasm: Initialize module
  RustPlannerWasm-->>plannerWorker: Initialization result
  plannerWorker-->>wasmPlanner: Reply with request ID
  wasmPlanner->>plannerWorker: Send plan or normalize request
  plannerWorker->>RustPlannerWasm: Run requested operation
  RustPlannerWasm-->>plannerWorker: Return JSON result
  plannerWorker-->>wasmPlanner: Reply with result or error
Loading
Merge Risk: ⚪ Minimal · up to 039bb

No actionable issue remains identified; the change is mergeable after normal checks.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 9 functions across 4 files. (8 skipped: 8 … Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: migrating the site to the Rust planner and running it in a Web Worker.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 9 functions across 4 files. (8 skipped: 8 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@wormeyman
wormeyman merged commit 0532d92 into main Oct 21, 2026
9 checks passed
@wormeyman
wormeyman deleted the port/stage-12b branch October 21, 2026 10:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant