Skip to content

Eliminate tab-switch freeze after semantic search - #221

Merged
DanielCardonaRojas merged 5 commits into
mainfrom
bookmarks-tab-switch-lag
Aug 13, 2026
Merged

Eliminate tab-switch freeze after semantic search#221
DanielCardonaRojas merged 5 commits into
mainfrom
bookmarks-tab-switch-lag

Conversation

@DanielCardonaRojas

@DanielCardonaRojas DanielCardonaRojas commented Aug 12, 2026

Copy link
Copy Markdown
Owner

Overview

Switching content tabs after a semantic search (Bookmarks → Collections → Bookmarks) froze the UI. The tab-change handler resolved the Bookmarks preview synchronously on the event loop, and that live tree-sitter resolve stalled while a concurrent semantic search saturated the CPU by re-loading its embedding model on every query.

Key changes

  • fix(tui): route the tab-change Bookmarks preview through a background resolve (request_bookmark_preview_now), showing a loading indicator immediately so the event loop never blocks; init/focus-enter and Collections/Tours previews stay synchronous.
  • perf(core): add a process-wide shared_local_provider cache so the embedding model loads once per process instead of reloading on every search, removing the CPU spike that starved the UI.

Test plan

  • cargo test -p codemark-tui (14 e2e + doctests) and cargo test -p codemark-core --features semantic pass.
  • Built codemark-core and codemark-tui with and without the semantic feature; clippy clean on changed code.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Performance

    • Reused local embedding providers across operations, reducing redundant initialization and improving semantic search responsiveness.
  • Bug Fixes

    • Bookmark previews now refresh immediately when switching tabs.
    • Added clear loading feedback while bookmark previews are prepared.
    • Preserved the correct repository context in preview results.
    • Prevented outdated preview results and collection overviews from appearing during navigation.
    • Improved preview transitions when moving between bookmarks, collections, and tours.

DanielCardonaRojas and others added 2 commits August 12, 2026 12:04
Each semantic search built a fresh LocalEmbeddingProvider with an empty
model slot, re-reading the model weights (seconds of CPU) on every query.
That reload was the CPU spike that starved concurrent UI work.

Add a process-wide shared_local_provider cache keyed by model id + cache
dir; the provider embeds through &self (interior Mutexes), so sharing one
Arc across searches and threads is safe. SemanticRepo::provider() now
returns the cached Arc, so the model loads once and stays resident.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Switching content tabs resolved the Bookmarks preview synchronously on the
UI thread (a block_in_place live tree-sitter resolve), blocking the event
loop. Right after a semantic search — when the model load and list-health
fan-out saturate the CPU — switching to Collections and back froze the UI.

Route the tab-change Bookmarks preview through a background resolve instead
(request_bookmark_preview_now), showing a loading indicator immediately so
the previous tab's overview doesn't linger. Init and focus-enter previews
stay synchronous (the e2e snapshots depend on it); Collections/Tours
overviews are DB-only and also stay synchronous.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@inspect-review inspect-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inspect review

Triage: 14 entities analyzed | 0 critical, 0 high, 10 medium, 4 low
Verdict: standard_review

Findings (0)


Reviewed by inspect | Entity-level triage found 0 high-risk changes

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ceea192e-7979-4078-bc09-1588e57a584d

📥 Commits

Reviewing files that changed from the base of the PR and between 4ef1860 and 532ce51.

📒 Files selected for processing (5)
  • GEMINI.md
  • crates/codemark-core/src/embeddings/local.rs
  • crates/codemark-tui/src/browser/events.rs
  • crates/codemark-tui/src/browser/right_pane.rs
  • crates/codemark-tui/src/event.rs
🚧 Files skipped from review as they are similar to previous changes (3)
  • crates/codemark-tui/src/browser/events.rs
  • crates/codemark-tui/src/browser/right_pane.rs
  • crates/codemark-core/src/embeddings/local.rs

📝 Walkthrough

Walkthrough

The change caches local embedding providers by model and cache directory. Semantic repository access now reuses these providers. TUI content-tab changes start bookmark previews asynchronously and preserve synchronous collection and tour previews.

Changes

Embedding provider cache

Layer / File(s) Summary
Process-wide provider caching
crates/codemark-core/src/embeddings/local.rs, crates/codemark-core/src/embeddings/mod.rs, crates/codemark-core/src/storage/semantic_repo.rs, GEMINI.md
A process-wide cache stores shared providers by model and cache directory. SemanticRepo uses shared_local_provider. The semantic module re-exports the function. Embedding lifecycle logging is documented.

Immediate preview routing

Layer / File(s) Summary
Content-tab preview routing
crates/codemark-tui/src/browser/events.rs, crates/codemark-tui/src/browser/mod.rs
Mouse and keyboard content-tab changes use preview_after_tab_change(). Bookmark previews use immediate asynchronous resolution. Collection and tour previews remain synchronous.
Bookmark preview loading and dispatch
crates/codemark-tui/src/browser/right_pane.rs, crates/codemark-tui/src/browser/mod.rs, crates/codemark-tui/src/browser/events.rs, crates/codemark-tui/src/event.rs
Bookmark requests cancel queued work, invalidate stale results, show loading state, and include repository context in preview tasks and PreviewReady events. Accepted previews update the active repository.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Mergeability Score: ⚪ Minimal · up to 532ce

The PR moves bookmark previews off the event loop and reuses the embedding model to prevent tab-switch freezes and repeated CPU spikes; no actionable merge-blocking risk remains.

Sequence Diagram(s)

sequenceDiagram
  participant ContentTab
  participant Browser
  participant RightPane
  participant BookmarkPreviewTask
  ContentTab->>Browser: select bookmark tab
  Browser->>RightPane: begin_bookmark_loading
  Browser->>Browser: cancel queued work and invalidate stale results
  Browser->>BookmarkPreviewTask: spawn preview with repository context
  BookmarkPreviewTask-->>Browser: send PreviewReady with repo_root
  Browser->>RightPane: update active repository and apply preview
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the primary change: fixing the TUI freeze caused by switching tabs after semantic search.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch bookmarks-tab-switch-lag

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR moves bookmark resolution triggered by tab changes off the UI event loop and reuses local embedding providers process-wide.

  • Starts bookmark previews immediately in a background task when switching back to the Bookmarks tab.
  • Invalidates pending bookmark previews before rendering Collection or Tour content.
  • Carries repository ownership through asynchronous preview events for multi-repository routing.
  • Caches embedding providers by model and cache directory to avoid repeatedly loading model weights.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
crates/codemark-tui/src/browser/mod.rs Adds tab-specific asynchronous bookmark preview dispatch and invalidates pending work before synchronous Collection or Tour rendering.
crates/codemark-tui/src/browser/events.rs Routes tab changes through the new preview path and preserves repository ownership in successful asynchronous preview events.
crates/codemark-tui/src/browser/right_pane.rs Adds a bookmark-specific loading transition that clears overview state so loading feedback is immediately visible.
crates/codemark-tui/src/event.rs Extends successful preview events with the owning repository root.
crates/codemark-core/src/embeddings/local.rs Introduces a process-wide provider cache keyed by embedding model and cache directory.
crates/codemark-core/src/storage/semantic_repo.rs Uses shared embedding providers so repeated semantic operations reuse loaded model state.

Sequence Diagram

sequenceDiagram
    participant User
    participant UI as TUI event loop
    participant Worker as Preview worker
    participant Pane as Right pane
    User->>UI: Switch to Bookmarks tab
    UI->>Pane: Show loading state
    UI->>Worker: Resolve selected bookmark with request ID
    Note over UI: Event loop remains responsive
    Worker-->>UI: PreviewReady(request ID, repo root, payload)
    alt Request is still active
        UI->>Pane: Apply preview
    else Request was superseded by another tab
        UI-->>Worker: Discard stale result
    end
Loading

Reviews (3): Last reviewed commit: "chore(core): trace embedding provider ca..." | Re-trigger Greptile

Comment thread crates/codemark-tui/src/browser/mod.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
crates/codemark-tui/src/browser/mod.rs (1)

689-712: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a debug trace for immediate preview dispatch.

Log the immediate preview request after allocating active_preview_request. Use the codemark::ui target and the request ID.

Proposed change
         self.preview_seq = self.preview_seq.wrapping_add(1);
         self.active_preview_request = self.preview_seq;
+        tracing::debug!(
+            target: "codemark::ui",
+            request_id = self.active_preview_request,
+            "starting immediate bookmark preview"
+        );
         self.pending_preview = None;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/codemark-tui/src/browser/mod.rs` around lines 689 - 712, Add a debug
trace in request_bookmark_preview_now immediately after assigning
active_preview_request, using the codemark::ui target and including the
allocated request ID.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/codemark-core/src/embeddings/local.rs`:
- Around line 289-303: Add tracing::debug! events in shared_local_provider for
both cached provider reuse and new provider creation, using target:
"codemark::embeddings" and including relevant context such as the model or cache
key. Document the new codemark::embeddings target in the subsystem table in
GEMINI.md.

In `@crates/codemark-tui/src/browser/mod.rs`:
- Around line 696-711: Ensure the selected repository root is preserved through
the async preview flow anchored by `spawn_preview_task`, `Event::PreviewReady`,
and `RightPane::apply_preview`; carry `repo_root` with the request/result or set
it for the current request before spawning, so successful previews from
non-focused repositories update `active_repo_root` correctly. Add a regression
test covering tab switches across multiple repositories and subsequent
right-pane refresh/action behavior.

---

Nitpick comments:
In `@crates/codemark-tui/src/browser/mod.rs`:
- Around line 689-712: Add a debug trace in request_bookmark_preview_now
immediately after assigning active_preview_request, using the codemark::ui
target and including the allocated request ID.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 27b99347-1eef-4169-8f80-5e25431a991d

📥 Commits

Reviewing files that changed from the base of the PR and between 74b1f3e and 861397c.

📒 Files selected for processing (6)
  • crates/codemark-core/src/embeddings/local.rs
  • crates/codemark-core/src/embeddings/mod.rs
  • crates/codemark-core/src/storage/semantic_repo.rs
  • crates/codemark-tui/src/browser/events.rs
  • crates/codemark-tui/src/browser/mod.rs
  • crates/codemark-tui/src/browser/right_pane.rs

Comment thread crates/codemark-core/src/embeddings/local.rs
Comment thread crates/codemark-tui/src/browser/mod.rs
… tabs

A tab switch to Bookmarks now spawns a background preview and leaves its
request id active. Switching on to Collections/Tours rendered their overview
synchronously without invalidating that request, so a late PreviewReady
could overwrite the overview with stale bookmark content from the prior tab.

Cancel any in-flight/pending bookmark preview when switching to a
synchronously-rendered overview tab (before the no-selection early return, so
an empty target tab is covered too), dropping the stale result on arrival.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@inspect-review inspect-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inspect review

Triage: 14 entities analyzed | 0 critical, 0 high, 10 medium, 4 low
Verdict: standard_review

Findings (0)


Reviewed by inspect | Entity-level triage found 0 high-risk changes

@DanielCardonaRojas

Copy link
Copy Markdown
Owner Author

@greptile review

@DanielCardonaRojas DanielCardonaRojas changed the title fix(tui): eliminate tab-switch freeze after semantic search Eliminate tab-switch freeze after semantic search Aug 13, 2026
DanielCardonaRojas and others added 2 commits August 12, 2026 23:09
The synchronous load_bookmark_live path recorded the previewed bookmark's
owning repo in active_repo_root, but the background PreviewReady path did
not (apply_preview has no db). Under multi-select, a preview from a
non-focused repo left active_repo_root stale, so a later right-pane
refresh/action could resolve against the wrong database. Routing tab
switches through the async path widened this to tab changes too.

Carry repo_root through Event::PreviewReady and set active_repo_root in the
handler, mirroring the synchronous path. Fixes the pre-existing nav-path gap
as well.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Instrument shared_local_provider with tracing::debug! events for cache hit
(reuse) and miss (creation) under a new codemark::embeddings subsystem
target, per the project logging convention; document the target in GEMINI.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@inspect-review inspect-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inspect review

Triage: 18 entities analyzed | 0 critical, 0 high, 13 medium, 5 low
Verdict: standard_review

Findings (0)


Reviewed by inspect | Entity-level triage found 0 high-risk changes

@DanielCardonaRojas
DanielCardonaRojas merged commit c47d509 into main Aug 13, 2026
14 checks passed
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