mirror of
https://github.com/zed-industries/zed.git
synced 2026-06-01 03:14:56 +07:00
Cherry-pick of #54723 to preview ---- Fixes #54618. ## Summary After upgrading from `v0.232.x` to `v0.233.5+`, many users reported that most of their agent threads "disappeared" from the sidebar. The threads are still on disk in the legacy `threads.db` — but they never make it into `sidebar_threads`, which is the only table the new sidebar UI reads from, so they're unreachable from the UI. The root cause is a race between `ThreadStore::reload` and `migrate_thread_metadata`: - `ThreadStore::new` constructs with an empty in-memory `Vec` and kicks off `reload()` as a fire-and-forget task. - `migrate_thread_metadata` runs during `agent_ui::init` and reads `ThreadStore::global(cx).read(cx).entries()` synchronously, without awaiting that reload. - On cold boot the migration observes an empty iterator, early-returns on `to_migrate.is_empty()`, and never populates `sidebar_threads`. The migration runs every launch, so it keeps losing the race forever. Empirically, the only rows that *did* end up in `sidebar_threads` for affected users came from `handle_conversation_event` writing rows when the user actively interacted with a thread. That's why users would typically see a handful of recently-touched threads rather than their full history. ## Fix 1. `ThreadStore` now tracks its current reload as a `Shared<Task<()>>` and exposes it via `reload_task()`. `migrate_thread_metadata` awaits this before reading `entries()`. 2. Move the top-5-per-project unarchive pass out from under the `is_first_migration` guard. Previously the rescue only ran when `sidebar_threads` was empty, which meant any user who had even one pre-existing row (e.g. from interacting with a thread on a prior launch) got every subsequent batch of migrated threads archived with no rescue. Running the rescue per-batch is stateless and idempotent — a user who bounces between older releases and newer ones still gets their top 5 per project surfaced each time a new batch is migrated. No new KVP flag or one-shot backfill is needed: because the migration already dedupes by session_id and runs on every launch, the next cold boot on a fixed build picks up any legacy threads that earlier launches missed. ## Structure The PR is split into two commits to make the diff easy to verify: 1. **Regression test** — fails on `main`, reproduces the cold-boot race by seeding the legacy DB, reinitializing `ThreadStore` to get a fresh empty cache, and running the migration without parking first. 2. **The fix** — gates entries reads on `reload_task().await`, and adjusts the per-batch rescue policy. Updates one existing test's assertions to match the new per-batch rescue policy. ## Validation - The regression test fails on `main`, passes after the fix. - All `agent_ui`, `agent::thread_store`, and `sidebar` lib tests pass. - `./script/clippy -p agent -p agent_ui` is clean. - End-to-end repro with a real on-disk data dir: launched `v0.230.2 → v0.231.2 → v0.232.3 → v0.233.8` as a non-staff user, creating 15 threads and interacting with one, reproduced the reported state (1 thread in sidebar, 14 missing). Launched a debug build of this branch against the same data dir: `Migrating 14 thread store entries` in the log, 15 rows in `sidebar_threads` with 6 unarchived (the interacted-with thread plus the 5 most recent), 9 archived and reachable from the archive view. Release Notes: - Fixed agent threads appearing to be missing after upgrading to the parallel-agents sidebar. The thread-metadata migration was racing against the on-disk thread store's async reload and skipping itself on every launch. Upgrading to this build runs the migration successfully; previously-missing threads are surfaced either in the sidebar (5 most recent per project) or in the archive view. Co-authored-by: Eric Holk <eric@zed.dev> |
||
|---|---|---|
| .. | ||
| src | ||
| Cargo.toml | ||
| LICENSE-GPL | ||