Skip to content

perf(tui): offload task archive to background worker#194

Merged
HonestMajority merged 1 commit into
mainfrom
async-task-archive-tui
May 20, 2026
Merged

perf(tui): offload task archive to background worker#194
HonestMajority merged 1 commit into
mainfrom
async-task-archive-tui

Conversation

@HonestMajority
Copy link
Copy Markdown
Owner

Summary

  • Archiving a task synchronously killed tmux sessions, removed worktrees, archived attached agents, and rewrote meta — enough work to freeze the TUI event loop for hundreds of ms after Enter on the confirmation.
  • Reuse the existing respawn async pattern: App::archive_task now does only sync UI work (remove row, mark in-progress, clamp selection, status) and offloads use_cases::archive_task via tokio::task::spawn_blocking. Results are drained from a new mpsc channel by apply_archive_results in the main loop.
  • refresh_tasks_for_project filters out task ids in archive_in_progress so the 1Hz refresh can't resurrect the row before the worker writes archived_at.
  • No use_cases changes; scope deliberately narrow per researcher recommendation tui-blocking-archive-ops.

Test plan

  • cargo fmt -- --check
  • cargo clippy --all-targets -- -D warnings
  • cargo test (all suites pass; 17 + 38 + 3 + 3 + 16 + 8 + 7 + 32 + 5 + 3 + 6 + 19 + 2 + 20)
  • New focused test archive_task_marks_in_progress_and_refresh_does_not_re_add_task proves the in-progress filter gates the refresh
  • New focused test archive_task_inserts_task_id_into_archive_in_progress covers the synchronous side-effects
  • Existing archive clamp tests still pass

🤖 Generated with Claude Code

Archiving a task synchronously kills tmux sessions, removes worktrees,
archives attached agents and rewrites meta — enough work to stall the
TUI event loop and freeze rendering for hundreds of ms.

Reuse the respawn async pattern: `archive_in_progress` tracks task ids
currently being archived; `archive_task` removes the row from
`self.tasks` synchronously, marks the id in-progress, clamps selection,
and spawns `use_cases::archive_task` via `tokio::spawn_blocking`. The
result channel is drained by `apply_archive_results` from the main
loop, which clears the in-progress entry and surfaces success/failure
to the status line.

`refresh_tasks_for_project` filters out in-progress task ids so the
periodic disk-backed refresh cannot flicker the row back between the
optimistic remove and the worker writing `archived_at`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@HonestMajority HonestMajority merged commit d7d88b7 into main May 20, 2026
1 check passed
@HonestMajority HonestMajority deleted the async-task-archive-tui branch May 20, 2026 13:05
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.

1 participant