Skip to content

fix: share-next discards unsubscribes and accumulates listeners per instance reload #501

Description

@LeXwDeX

Why

深度审计确认(服务端唯一确认级内存泄露):packages/opencode/src/share/share-next.ts:187-214 的 5 个 yield* watch(...)(Session.Updated / MessageV2.Updated / PartUpdated / Session.Diff / Session.Deleted)丢弃了 events.listen 返回的 Unsubscribe。listener 被 push 进 EventV2 进程级单例的数组(packages/core/src/event.ts:698-705),唯一移除途径是调用返回的 Unsubscribe——被丢弃即永不移除。

InstanceState(ScopedCache)dispose → 重挂载(worker.reload()configUpdateserver.instance.disposed 重连)每轮 +5 listener,闭包持有 _ctxcache(含已清空 map 与 state 骨架)永久驻留;且进程内每个事件都要跑过所有陈旧 listener 的 directory 过滤(CPU 税)。

Scope

  • packages/opencode/src/share/share-next.ts:171-214watch 定义与 5 个调用点)
  • finalizer 位置:同文件 :154-163(现有 finalizer 只清 cache.queue/cache.shared,不含退订)

Approach

  • 收集 5 个 watch() 返回的 Unsubscribe,在 InstanceState.make 闭包的 Effect.addFinalizer 中逐一调用
  • 或在 events.listen 层提供 scoped 包装(Effect.acquireRelease(listen, (unsub) => unsub)),使订阅生命周期自动绑定实例 scope(对其他调用点亦有益,但本 issue 限定 share-next)

Acceptance

  • 回归测试:构造实例 → dispose → 重建,断言 EventV2 listener 计数不增长(spy 或暴露计数)
  • 既有 share/event 相关测试全绿(packages/opencode/test/ 相关文件)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions