Files
memind/docs/regression-guards/mindspace-remote-page-sync-and-thumbnail.md
john d3239ff292 fix: MindSpace remote sync, thumbnail fallback, and Plaza URL guards
Ensure page sync runs via pageSyncService in remote mode, fall back to
workspace HTML when storage assets are missing, and prevent production
Portal from linking to loopback Plaza URLs baked in at build time.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-05 07:57:04 +08:00

4.0 KiB
Raw Permalink Blame History

MindSpace Remote 页面同步与缩略图回归守卫

日期:2026-07-05

事故症状

  1. 缩略图 500GET /api/mindspace/v1/pages/:pageId/thumbnail 返回 500;日志/storage 为 ENOENT,但 MindSpace/<userId>/public/*.html 仍存在。
  2. 页面列表缺新生成页103 生产 MINDSPACE_SERVER_ADAPTER=remote 时,Agent 新生成的 public/*.html 不出现在「最近页面 / 全部页面」。
  3. 误判:容易把缺页当成「MindSpace 路径解析错误」或「改回 local adapter 就能修缩略图」——两者根因不同。

根因

缩略图 500

  • h5_page_records / h5_asset_versions.storage_key 指向 data/mindspace/users/.../*.md
  • 磁盘上该 storage 文件可能已丢失或未写入(历史 sync、清理、quota、迁移)。
  • 页面 snapshot 仍保留 relative_path: public/index.html,工作区 HTML 是真实内容来源。
  • loadPageThumbnailContext / getPage只读 storage,会在 remote 8082 上直接抛错 → Portal 返回 500。

Remote 下缺页

  • Portal GET /mindspace/v1/pages 会调用 syncUserGeneratedPages(),将 public/*.html 入库。
  • 曾存在 if (adapterKind === 'remote') return;,导致 8082 独立部署后 sync 永不执行
  • 测试环境多为 local,sync 正常 → 生产/测试行为不一致。

必须保留的行为

1. Workspace HTML fallback(读内容)

mindspace-pages.mjs 中,读取页面 content / 缩略图 HTML 时:

  1. 优先读 storage_key 对应文件;
  2. ENOENTpage_type === 'html' 且 snapshot 有 relative_path → 回退读 resolvePublishDir(h5Root, userId) 下对应 HTML
  3. getPagerenderThumbnail 共用 readPageContentWithWorkspaceFallback,禁止只修一处。

2. Remote 也执行 page sync

  1. 抽出 mindspace-page-sync-service.mjspageSyncService.syncUserGeneratedPages(userId)
  2. 写入 mindspace-server-adapter-contract.mjspageSyncService binding
  3. Local8082 / Portal 内直接跑 syncGeneratedPagesFromPublicAssets
  4. RemotePortal 通过 RPC 调 8082 的 pageSyncService.syncUserGeneratedPages
  5. server.mjs 禁止在 remote 模式 early-return 跳过 sync。

触发点(保持不变):

  • GET /mindspace/v1/pages 列表前
  • 聊天 Finish 后(onAfterFinish

3. 103 拓扑约束

  • Portal8081MINDSPACE_SERVER_ADAPTER=remote
  • MindSpace Service8082,跑 local adapter(含 pageSyncService + storage + h5Root
  • 用户 HTML/Users/john/Project/Memind/MindSpace/<userId>/public/
  • Storagedata/mindspace/users/<userId>/...

禁止用「改回 Portal local adapter」作为生产长期方案;只可用于本地对比验证。

排查入口

# 1. 页面 DB 记录 vs storage vs workspace
mysql ... # h5_page_records + h5_page_versions.source_snapshot_json + h5_asset_versions.storage_key

# 2. storage 是否存在
ls -la data/mindspace/users/<userId>/pages/<assetId>/versions/

# 3. workspace HTML 是否存在
ls -la MindSpace/<userId>/public/

# 4. 8082 健康与 adapter
curl -s http://127.0.0.1:8082/health

# 5. 缩略图 RPC(需登录态;或直接在 8082 侧调 pageService.renderThumbnail
curl -I 'https://m.tkmind.cn/api/mindspace/v1/pages/<pageId>/thumbnail'

改相关文件前必跑

npm run verify:mindspace-page-sync-guards
node --test mindspace-page-sync-service.test.mjs mindspace-pages.test.mjs

Checklist(发 103 前)

  • mindspace-pages.mjs 含 workspace fallback
  • pageSyncService 在 contract + local runtime + remote proxy 中齐全
  • server.mjs 无 remote sync skip
  • 8082 与 Portal 均发布8082 承载 renderThumbnail + sync
  • 用真实 pageId 验证 thumbnail 200 + 列表含新页

相关单测

  • mindspace-page-sync-service.test.mjs
  • mindspace-pages.test.mjsstorage 缺失时 thumbnail / getPage fallback
  • mindspace-page-sync.test.mjspublic dir → DB

代码内标记

搜索 REGRESSION GUARD: mindspace-page-sync-thumbnail 定位内联说明。