Files
linuxcncWebWASM/docs/linuxcnc-axis-web-wasm-opfs-ui-cache.md

5.6 KiB
Raw Permalink Blame History

AXIS Web/WASM OPFS 页面临时缓存设计

目标

页面刷新或 Worker 重启后,恢复用户需要的页面上下文,同时不把页面缓存误认为 LinuxCNC 运行时权威。所有 G-code、Task、TP、运动学、轴值、HAL、IO、工具、探针和错误状态仍由 LinuxCNC WASM checkpoint/recovery 恢复;OPFS 临时 JSON 只保存页面上下文和可重新提交给 WASM 的程序草稿。

分层

flowchart LR
    UI[React 页面状态<br/>页签 / 相机 / 图层 / 编辑器] -->|UI_STATE_SAVE| WC[ReactWorkerClient]
    WC -->|Worker message| W[Dedicated Worker]
    W --> OPFS[OPFS 双槽位临时 JSON]
    OPFS -->|UI_STATE_LOAD| W
    W --> WC
    WC --> UI
    P[POWER OFF response] --> W
    W --> CP[WASM power-off checkpoint]
    CP --> OPFS
    OPFS -->|LOAD_WORKSPACE| W
    W --> WASM[LinuxCNC WASM restore]
    WASM --> R[Task/TP/pose/IO snapshot]
    R --> UI

缓存范围

允许写入 UI 临时 JSON 的字段:

  • selectedAxis、leftTab、rightTab;
  • view、zoom、rotateMode;
  • coordType、displayType、metric;
  • preview layers;
  • casePath、program.path、program.source;
  • cache schema version、context_id、generation、saved_at_ms、state_hash。

禁止由 UI JSON 直接恢复并驱动运动的字段:

  • task state/mode/program status;
  • TP queue、active segment、velocity、acceleration、jerk;
  • XYZAC pose、J0..J4 joints、RTCP/FK/IK state;
  • HAL、spindle、coolant、tool、probe、home/limit、fault;
  • operation ledger、event cursor 和已提交副作用。

这些字段必须来自 WASM checkpoint;缓存的 program.source 重新恢复时也必须再次发送 PROGRAM_LOAD,由 WASM interpreter 解析。

文件布局

OPFS root/
  linuxcnc-web-wasm/
    ui-state/
      xyzac-trt/
        state-a.json
        state-b.json
        manifest.json
      xyzac-trt-power-off/
        state-a.json
        state-b.json
        manifest.json

state-a.json 和 state-b.json 轮换写入。写新槽位成功并 flush 后才更新 manifest;任一写入中断时,旧槽位仍可读取。读取时验证两个槽位,选择 generation 最大且 hash 正确的记录。

JSON 记录

{
  "schema": "linuxcnc-ui-temp-json.v1",
  "context_id": "linuxcnc-2.10.0-pre0-wasm-m1-py-c1",
  "key": "xyzac-trt",
  "generation": 12,
  "saved_at_ms": 1770000000000,
  "state": {
    "version": 1,
    "leftTab": "manual",
    "rightTab": "preview",
    "view": "p",
    "zoom": 1,
    "program": { "path": "browser/demo.ngc", "source": "..." }
  },
  "state_hash": "fnv1a64:...",
  "record_hash": "fnv1a64:..."
}

约束:单记录最大 1 MiB,程序缓存最大 900 KiB,缓存 TTL 为 7 天;超限、过期、JSON 损坏、schema/context/hash 不匹配时返回 empty/blocked,不能回退到旧 UI 假状态。

生命周期

sequenceDiagram
    participant A as App.tsx
    participant C as WorkerClient
    participant W as Worker
    participant O as OPFS
    participant X as WASM
    A->>C: ensureSession
    C->>W: HELLO / SESSION_ATTACH
    A->>C: UI_STATE_LOAD
    C->>W: custom Worker cache request
    W->>O: scan slots + verify hash/TTL
    O-->>W: newest valid UI state
    W-->>C: UI_STATE_RESULT
    C-->>A: restore tabs/camera/editor draft
    A->>W: LOAD_WORKSPACE
    W->>O: load power-off checkpoint if present
    W->>X: restore WASM task/TP/program/IO
    X-->>W: authoritative snapshot
    W-->>A: state snapshot
    A->>C: debounced UI_STATE_SAVE
    C->>W: save state JSON
    W->>O: write inactive slot, flush, update manifest

高频 SIM_STEP 不写 OPFS。页面状态变化使用 500ms 防抖;程序编辑器输入连续变化只保存最后一个稳定版本。POWER OFF 的 WASM checkpoint 由 Worker 在收到成功回执后写入专用 key;下一次 LOAD_WORKSPACE 由 Worker 自动读取并交给 WASM restore。

安全和一致性

  1. React 不访问 navigator.storage、WASM 指针或 OPFS 文件。
  2. Worker 是 OPFS 唯一写者;所有消息串行处理,避免控制命令和缓存写入竞争。
  3. UI_STATE_RESULT 不进入 CNC state reducer,不改变 protocol sequence、task tick 或运动状态。
  4. UI cache 的 program.source 只能作为输入草稿;加载和预览仍必须由 WASM PROGRAM_LOAD 生成。
  5. OPFS 不可用时,页面显示可诊断的 blocked/empty 状态,不使用 localStorage 或静默内存替代。
  6. 清理只删除 UI 临时槽位;不会删除 WASM checkpoint、事件日志或程序运行状态。

代码和测试

能力 文件
双槽位 JSON、TTL、hash、OPFS API web/worker/opfs-ui-state.mjs
Worker-only 路由、断电 checkpoint web/worker/opfs-worker-bridge.mjs
React UI 状态读写调用 web/react/src/worker-client.ts、web/react/src/App.tsx
浏览器 Worker 入口 web/react/src/sim-worker-entry.ts、web/worker/sim-worker.mjs
单元回归 web/worker/test_opfs_ui_state.mjs
原生 OPFS 能力探针 web/workspace/opfs-runtime.mjs、web/app/browser-opfs-probe.html

验证命令:

node web/worker/test_opfs_ui_state.mjs
npm run typecheck --prefix web/react
npm run build --prefix web/react

真实浏览器还需验证 OPFS quota、Worker reload、坏槽位、过期记录和离线启动;这些属于独立的浏览器恢复 oracle,不等同于 UI cache 单元测试通过。

已完成的线上浏览器样例:scripts/test_xyzac_opfs_browser.mjs 在 20260903-linuxcnc-wasm-opfs-r30 上验证视角、DRO 页签、A 轴选择刷新后恢复;实际 OPFS 文件为 state-b.json/manifest.json,localStorage 为空,浏览器错误为 0。quota、崩溃和离线 oracle 仍独立保留为 pending。