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

149 lines
5.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AXIS Web/WASM OPFS 页面临时缓存设计
## 目标
页面刷新或 Worker 重启后,恢复用户需要的页面上下文,同时不把页面缓存误认为 LinuxCNC 运行时权威。所有 G-code、Task、TP、运动学、轴值、HAL、IO、工具、探针和错误状态仍由 LinuxCNC WASM checkpoint/recovery 恢复;OPFS 临时 JSON 只保存页面上下文和可重新提交给 WASM 的程序草稿。
## 分层
~~~mermaid
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 解析。
## 文件布局
```text
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 记录
```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 假状态。
## 生命周期
~~~mermaid
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 |
验证命令:
```text
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。