Skip to content

Daemon: async providers, scoped caches, refresh dedup, cancellation #18

Closed

Description

@axisrow

Part of #14 (delivery step 3). Depends on the request-scoped extraction; parallel with the lifecycle issue.

Что сделать

  • Async providers in shared mode: Git (git.ts), usage/Keychain (usage-fetch.ts), custom-command (custom-command.ts) via async child_process — sync child-process APIs block the event loop and would let one slow command stall every session.
  • Custom-command capture: adapt custom-command-capture.ts to an asynchronous result in the daemon, retaining output limits, timeouts, EPIPE handling and descendant/process-group cleanup. Do not call the sync Node-spawning helper unchanged inside the server.
  • Git review cache: route the detached refresh path through the same async scheduler instead of re-entering the Node executable. Audit remaining providers for self-spawns and caller-global state (one-process invariant). Legacy sync path stays for one-shot mode.
  • Prefetch: gather data for configured widgets into RenderContext before synchronous widget formatting consumes it (existing registry/formatter/parser reused).
  • Scoped caches (epic table): key by absolute config path + revision / auth profile + credential generation / worktree + cwd / canonical transcript identity. In-flight refresh dedup per key; account/profile separation before any memory-cache fast return; TTL zero still executes per eligible request; missing credentials never select another profile's cached usage.
  • Transcript reuse: validated whole-analysis reuse via file identity/size/mtime/replacement; invalidation tests for truncation, replacement, compaction, partial trailing records, subagent updates. No unconditional full rescan of unchanged files. Incremental tail parsing stays out (conditional follow-up).
  • Concurrency: bounded queues; at most one active + one newest pending render per exact display context; superseded requests resolved explicitly; provider work cancelled when it has no remaining consumers without killing shared refreshes; a slow command or usage fetch never blocks cached responses of other sessions.
  • Bounded memory: cap caches, active jobs and idle retention; never retain full envs, tokens or transcript contents in diagnostics.

Файлы

src/utils/git.ts, src/utils/git-review-cache.ts, src/utils/custom-command.ts, src/utils/custom-command-capture.ts, src/utils/usage-fetch.ts, src/utils/jsonl-metrics.ts, src/daemon/, src/types/RenderContext.ts.

Эталон

PR #9 (jsonl test discipline for truncation/compaction edge cases), PR #2 (provider cost discipline).

Acceptance (from epic)

Simultaneous different configs/accounts/worktrees/widths cannot exchange data; account switch/logout invalidates relevant caches; one slow/hung command does not stall other sessions; memory stays bounded and is reclaimed after idle.

Оценка

  • LOC: ~700–1000 (src ~550 / tests ~350)
  • Размер: XL
  • Время (код): ~100–180 мин
  • Время (review): ~90–120 мин (база 45–60 ×2: concurrency + subprocess management)
  • Время (итого): ~190–300 мин

Priority: medium.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions