Files
viexp/docs/decisions/ADR-005-async-adoption.md
T

1.9 KiB
Raw Blame History

type, adr, status, date, supersedes, tags
type adr status date supersedes tags
decision 005 accepted 2026-10-17
adr
async
tokio
threads

ADR-005: adopt async gradually — sync core, then threads, then tokio

Context

Ranger's fatal flaw is a synchronous loop that stats every file inline (research/ranger-deep-dive). yazi proves tokio solves it but is a lot of machinery to learn while also learning Rust. lf (Go goroutines) shows threads alone already keep a UI responsive.

Options considered

Option Pros Cons
Gradual: sync → std threads + channels → tokio learnable steps; working product at every stage one refactor of the preview pipeline in Sprint 8
tokio from day 1 final architecture sooner async lifetimes + borrow checker + TUI at once = frustration barrier
threads-only forever simpler mental model ecosystem (notify bridges, timeouts, process spawning) is tokio-first

Decision

  • Sprints 1–5: synchronous core. The TUI loop owns all state; directory loading and file ops are fast enough synchronously for a first product.
  • Sprints 6–7: previews move to std::thread + std::sync::mpsc — UI stays responsive, ownership lessons are explicit.
  • Sprint 8: adopt tokio for the full preview/media pipeline (yazi architecture: runtime workers marshal results to the single-threaded UI actor via a channel). Introduce cancellation via a generation-counter ("ticket") pattern before adopting tokio abort.

Consequences

  • Positive: each concurrency model is learned in isolation; no big-bang async rewrite of the UI.
  • Negative: preview pipeline is written twice (thread → task) — accepted as a deliberate learning repetition (Kaufman: quantity of practice beats premature perfection).
  • Mitigations: keep the preview pipeline behind a small interface (Previewer trait, ADR-002) so the swap is local, not global.