Skip to content

feat: isolate different backends - #1093

Open
dfshfghj wants to merge 7 commits into
devfrom
fix/multi-backend
Open

feat: isolate different backends#1093
dfshfghj wants to merge 7 commits into
devfrom
fix/multi-backend

Conversation

@dfshfghj

@dfshfghj dfshfghj commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator

Issue for this PR

Closes #

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

根据所选后端对前端状态和导航行为进行作用域划分,确保在本地与非本地服务器之间切换时,不再复用相同的侧边栏、布局或会话状态。更新了后端切换逻辑,在激活目标服务器之前安全地重置导航状态;

  • 添加针对服务器作用域的存储辅助工具,用于管理前端持久化状态。
  • 根据后端标识(backend key)对项目、侧边栏、布局及会话相关的前端状态进行作用域划分。
  • 更新全局同步子存储(global sync child stores),使其包含后端标识信息。
  • 添加 switchServer 辅助函数,确保在切换后端时,先离开绑定于旧后端的路由,再激活新服务器。
  • 更新服务器对话框及状态浮窗(popover)的切换行为,统一使用通用的切换流程。
  • 同时向本地后端和当前选定后端发送 /global/ping 请求,以确保非本地后端的租约/心跳状态也能得到刷新。

If you paste a large clearly AI generated description here your PR may be IGNORED or CLOSED!

How did you verify your code works?

  • bun typecheck from packages/app
  • bun run test from packages/app

Screenshots / recordings

If this is a UI change, please include a screenshot or recording.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

If you do not follow this template your PR will be automatically rejected.

@code-JDS

code-JDS commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

/oc review

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

下面是对 PR #1093(feat: isolate different backends)的审查。

一、PR 变更梳理

新增工具

  • utils/server-scope.tsserverHash(FNV-1a 校验和)、serverScopedKey(追加 \nserver:<hash>)、serverSessionKey(追加 //server:<hash>)。作用是把任意存储/会话键按后端标识隔离。
  • utils/server-switch.tsswitchServer 辅助函数,先执行 done()(导航离开旧路由),再轮询 path() 直到路由变化或 500ms 超时,然后执行 later()(激活新后端)。意图是"先解绑旧路由,再切服务器"。

app.tsx

  • ServerKey<Show when={server.key}>{children}</Show> 改为 keyed 渲染属性 {(_key) => <>{children}</>},使 server.key 一变就整体重挂载其下所有 Provider(GlobalSDK/GlobalSync/Router)。直观效果:切换后端时旧后端的内存状态(会话、消息、子存储)全部销毁重建。
  • 新增 ServerTracker 组件 + AppInterface.onServerChange 回调,把当前活动后端对象向上回传给宿主(entry.tsx)。

server.tsx

  • 删除模块级 _pingPaused/pingPaused 导出。
  • 新增 normalize(把 string/HttpBase/Any 统一成 Any)、keyOfupsert(input, {active?})(支持只入库不立即激活)。add 退化为 upsert 的包装。StoredServer 类型放宽到 ServerConnection.Any。直观效果:新增服务器时可先入库再在导航完成后激活,避免在旧路由组件上重挂载。

entry.tsx

  • ping 由"仅本地、被 pingPaused 抑制"改为"同时 ping 本地与活动非本地目标",并对带密码的目标加 Basic Auth 头。release/pagehide 同步释放两端租约。直观效果:用户切到不健康的远端后端时,本地 sidecar 不再因租约过期被 idle 退出。

存储键作用域化(约 15 个文件)

  • global-sync.tsxprojectCache/recentCache 改用 Persist.global(serverScopedKey(...)),并向 createChildStoreManager 传入 server 字段;onDisposeclearSessionPrefetchDirectory 改用作用域键。
  • child-store.ts:vcs/project/icon 的 Persist.workspace 改用 serverScopedKey(directory, input.server),且删除了 vcs.v1/project.v1/icon.v1 legacy 数组。
  • layout.tsx:新增 parseSessionKey/sessionKeyForServersessionPathdropSessionStatekey.split("/") 改为 parseSessionKeylayout.page 全局持久化改用作用域键并去掉 layout.page.v1 legacy。
  • file.tsxtreeExpandStore 读写、viewCache.loadlayout.tabs 全部改用 storage()/sessionKeyForServer
  • local.tsxmodel-selection 持久化、handoff Map 键全部作用域化。
  • permission.tsxacceptKey/directoryAcceptKey 的 directory 参数改用 scope(directory)
  • prompt.tsx/comments.tsx:会话缓存键作用域化(commentsdecodeSessionKeylastIndexOf("\n"),与新键兼容)。
  • sync.tsx:预取缓存的 directory 参数统一走 prefetch(directory)
  • terminal.tsxgetWorkspaceTerminalCacheKey/Persist.workspace 作用域化;legacy = server ? [] : getLegacyTerminalStorageKeys(...)
  • pages/layout.tsxreading-session.tsxsession.tsxsession-layout.tssidebar-branch-view.tsx:会话/布局键作用域化。
  • dialog-select-server.tsx/status-popover.tsx:切换流程统一走 switchServer,并在切换成功后弹出 toast。

二、合理性与有效性判断

整体设计("ServerKey 重挂载清内存 + 键作用域隔离存储 + 导航后再激活 + 双目标 ping")是自洽且能实现后端隔离目标的。commentslastIndexOf("\n") 解析与新键兼容、handoff 的读写两侧都已作用域化、预取缓存在 sync/layout/onDispose 三处的读写一致——这些细节处理得当。pingPaused 的移除也确实修复了一个潜在缺陷(远端不健康会误杀本地租约)。

三、侵入性与副作用

  1. [High] 存量客户端状态迁移缺失。 server.key 在 web 入口恒为 getDefaultUrl() 返回的非空 URL,故 serverHash 恒有值,serverScopedKey 对所有用户(含仅用本地后端者)都会追加 \nserver:<hash>,使存储键/workspaceStorage 文件名与旧版不同。同时多处直接丢弃了 legacy 数组(globalSync.project.v1layout.page.v1model-selection.v1vcs.v1/project.v1/icon.v1 等),且未新增"旧未作用域键 → 新作用域键"的迁移。升级后用户会丢失:项目列表/最近会话缓存(可重新拉取)、布局状态、模型选择、文件树展开、终端标签/回滚、权限自动接受设置、评论、每会话 prompt/file-view 状态。其中布局/模型选择/终端/权限偏好属配置型状态,丢失影响明显。根源在于作用域化时只改了键、未补迁移路径。

  2. [Medium] 终端 legacy 迁移被全局禁用。 legacy = server ? [] : ...,而 server.key 恒非空,故 legacy 恒为 [],旧格式终端迁移对所有用户失效。即便保留 legacy,Persist.workspace 的 legacy 机制只读 direct store,无法跨 workspaceStorage 文件迁移,所以终端状态在升级时确实会丢失。

  3. [Medium] onDispose 作用域竞态。 ServerKey 重挂载时旧 GlobalSyncProvider 销毁,但此刻 server.key 已是新值,onDisposeclearSessionPrefetchDirectory(serverScopedKey(directory, server.key)) 清理的是新后端的键;旧后端的预取缓存条目(模块级 Map)不会被清,需等 15s TTL 过期。自愈但存在短暂陈旧/内存滞留。

  4. [Low] switchServer 死代码与脆弱性。 note/detail 定义但从未使用;轮询 location.pathname,若已在 "/" 则 start === current,需等满 500ms 超时才执行 later(),给切换增加无谓延迟;若导航失败则会在旧路由上触发重挂载。

  5. [Low] upsert 冗余三元与边界。 两个分支完全相同,input.type 判断无意义;ssh 类型在 http.url 为空时不会提前 return。

  6. [Low] permission.tsx 冗余 ?? scope(directory) 在 directory 真值时恒返回字符串,scope(directory) ?? directory?? 永不触发。

  7. [架构] child-store.tschildren 内存 Map 仍以原始 directory 为键,而持久化以 scoped directory 为键——不一致。 当前靠 ServerKey 重挂载清空内存 Map 规避了跨后端串数据,但这是一处隐式依赖,未来若有不经重挂载的复用路径会暴露问题。

四、用户数据 .db 文件审查

前端(packages/app)无任何 sqlite/drizzle/better-sqlite3/libsql/bun:sqlite 引用,.db 的 schema、迁移、路径、读写全在 packages/opencode 服务端。本 PR 不触及服务端,不改 schema/迁移/存储路径/读写行为。多目标 ping 不会让本地服务端写 .db;相反,移除 pingPaused 避免了本地租约被误杀、本地服务端被 idle 退出,对 .db 完整性更安全(减少运行中被终止的可能)。预取缓存在切换瞬间可能短暂陈旧(≤15s),仅影响前端 UX,不影响 .db 数据。无损坏/兼容性/回滚风险。

五、自动更新审查

自动更新全链路(web.check/download/install/mirror/waitForReloadwindow.location.reload)经 req/endpoint 绑定 getCurrentUrl()=本地后端,本 PR 未改动 req/endpoint/web/getCurrentUrl/boot 的更新绑定,故检测/下载/安装/重启/版本比较/渠道/回滚均不受影响。onServerChange 仅设置 ping 目标,不触及更新流向。PR 移除 pingPaused 后,本地租约不再因远端后端不健康而被暂停,本地 sidecar 更稳定,24h 更新轮询与 reload 更可靠。无负面影响。

六、平衡评述

PR 以"重挂载 + 键作用域 + 双目标 ping"实现隔离,系统性强、覆盖面广;但代价是大规模改写存储键且无迁移,对存量用户造成一次性的客户端状态清空——这更接近"一次性切割"而非"最小侵入"。受影响多为可重建缓存尚可接受,但终端/布局/模型选择/权限偏好等配置型状态应补迁移或至少在 PR 说明中显式标注升级影响。

@dfshfghj
dfshfghj force-pushed the fix/multi-backend branch from 80b45e9 to 047608d Compare July 7, 2026 16:22
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

CI/CD-related files cannot be changed in pull requests unless the author is listed in .github/cicd-admins.txt.

Violating files:

  • packages/app/src/context/layout.test.ts
  • packages/app/src/context/terminal.test.ts

This guard reads the protected list from .github/cicd-protected-files.txt.

@code-JDS

code-JDS commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

/oc review

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

I have the full diff. Now let me explore the local codebase to understand the context, particularly around Persist (storage/db), ServerConnection, checksum, the local server setup, and the auto-update mechanism.

@dfshfghj
dfshfghj force-pushed the fix/multi-backend branch from 047608d to 369f0cf Compare July 16, 2026 10:44
@code-JDS

code-JDS commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

/oc review

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Now I have the full diff. Let me explore the local codebase to understand the context of key areas being changed.

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.

2 participants