Skip to content

refactor(worker/base): Terminate/Kill/Wait lock-get-nil pattern DRY extraction #511

@hrygo

Description

@hrygo

Background

internal/worker/base/ 提供 BaseWorker、Conn、MetadataHandler — 所有 Worker 适配器的共享基座。子模块 claudecode/、opencodeserver/、proc/ 已独立分析。本次聚焦 base 层的架构质量。

Scope: dry — cycle 151 (模块分析通过 1)
Key files: base/worker.go


Finding Summary

Category Critical High Medium Low
DRY 0 0 1 0
合计 0 0 1 0

Findings

DRY

base-worker-lock-proc-nil-repeat

Severity: Medium | Confidence: High | ROI: Medium
Location: base/worker.go:63-80, base/worker.go:84-101, base/worker.go:105-123

Problem: Terminate、Kill、Wait 三个方法重复相同的 lock-get-proc-unlock / operate / lock-nil-proc-unlock 模式,共 18 次 Lock/Unlock 调用。对锁模式的任何 bug 修复(如操作后添加 nil-guard)必须在 3 个方法中同步应用。

Current Pattern:

func (w *BaseWorker) Terminate(ctx context.Context) error {
    w.Mu.Lock()
    proc := w.Proc
    w.Mu.Unlock()
    if proc == nil { return nil }
    if err := proc.Terminate(ctx, GracefulShutdownTimeout); err != nil {
        return fmt.Errorf("base: terminate: %w", err)
    }
    w.Mu.Lock()
    w.Proc = nil
    w.Mu.Unlock()
    return nil
}
// Kill and Wait are structurally identical, differing only in:
// - the proc method called (Kill vs Terminate vs Wait)
// - the nil-return value (nil vs nil vs (-1, error))
// - whether Proc is nil'd on error (Wait does NOT nil Proc on error)

Proposed Fix:

func (w *BaseWorker) withProc(fn func(*proc.Manager) error) error {
    w.Mu.Lock()
    p := w.Proc
    w.Mu.Unlock()
    if p == nil { return nil }
    if err := fn(p); err != nil { return err }
    w.Mu.Lock()
    w.Proc = nil
    w.Mu.Unlock()
    return nil
}

func (w *BaseWorker) Terminate(ctx context.Context) error {
    return w.withProc(func(p *proc.Manager) error {
        if err := p.Terminate(ctx, GracefulShutdownTimeout); err != nil {
            return fmt.Errorf("base: terminate: %w", err)
        }
        return nil
    })
}

Acceptance Criteria:

  • 提取 withProc 辅助方法统一 lock-get-operate-nil-set 模式
  • Terminate、Kill、Wait 使用 withProc 委托
  • Wait 保持不 nil Proc on error 的语义
  • go test -race ./internal/worker/base/... 通过
  • make test 零回归

Implementation Priority

Finding Priority Effort Risk Impact
base-worker-lock-proc-nil-repeat P1 Small Low 消除 3 处锁模式重复,统一维护点

Recommended starting point: withProc 提取 — 小改动,消除锁模式分散风险


Out of Scope

  • Capabilities 8 方法胖接口 — 仅 2 个外部调用,拆分增加复杂度
  • SessionInfo 25 字段膨胀 — 有意 DTO 设计,拆分需级联修改所有适配器
  • Health 签名不匹配 — 有意设计,BaseWorker 无法自发现类型
  • Worker/顶层 + base/ 其余 SOLID/coupling 分析 — 整体架构质量优秀

Verification

  • make test 通过,无回归
  • go test -race ./internal/worker/base/... 通过
  • Terminate/Kill/Wait 行为不变

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Medium: tech debt, refactoring, improvementsarchitectureDomain: design patterns, coupling, separation of concernsarea/workerScope: Claude Code/OCS/Pi adapters, base workerrefactorRefactor: DRY, SOLID, code quality improvements

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions