diff options
| author | Can Celik <ogulcancelik@gmail.com> | 2026-07-25 04:26:55 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-07-25 04:26:55 +0300 |
| commit | d4e0dd3d903c50d2edb8c3cec71952a83989b310 (patch) | |
| tree | c90ec43a08fab1fc79e1d6db865c723877a051af /src/app/mod.rs | |
| parent | b33e5f973fc89381aa4ac72b3a31fa087ec66e23 (diff) | |
perf: eliminate repeated workspace git discovery (#1842)
* perf: eliminate repeated workspace git discovery
refs #1838
* fix: keep workspace labels current without extra redraws
refs #1838
* fix: retain discovered workspace git metadata
refs #1838
Diffstat (limited to 'src/app/mod.rs')
| -rw-r--r-- | src/app/mod.rs | 50 |
1 files changed, 45 insertions, 5 deletions
diff --git a/src/app/mod.rs b/src/app/mod.rs index 84f6d917..c2d479b3 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -12,6 +12,7 @@ mod api; mod api_helpers; mod config_io; mod creation; +mod git_refresh; mod ids; mod input; mod popup; @@ -38,6 +39,7 @@ pub(crate) const HEADLESS_ANIMATION_TICK_STEP: u32 = 8; pub(crate) const SELECTION_AUTOSCROLL_INTERVAL: Duration = Duration::from_millis(30); const RESIZE_POLL_INTERVAL: Duration = Duration::from_millis(100); const GIT_REMOTE_STATUS_REFRESH_INTERVAL: Duration = Duration::from_millis(1500); +const GIT_REPO_DISCOVERY_REFRESH_INTERVAL: Duration = Duration::from_secs(5 * 60); const AUTO_UPDATE_CHECK_INTERVAL: Duration = Duration::from_secs(30 * 60); const PENDING_AGENT_RESUME_THEME_WAIT: Duration = Duration::from_millis(750); const SESSION_SAVE_DEBOUNCE: Duration = Duration::from_secs(5); @@ -110,8 +112,10 @@ pub struct App { pub(crate) copy_feedback_deadline: Option<Instant>, pub(crate) last_api_notification_at: Option<Instant>, pub(crate) last_git_remote_status_refresh: Instant, + pub(crate) last_git_repo_discovery_refresh: Instant, pub(crate) git_refresh_in_flight: bool, pub(crate) git_refresh_due_after_in_flight: bool, + pub(crate) git_identity_refresh_requested: bool, pub(crate) git_status_cache: HashMap<std::path::PathBuf, crate::workspace::GitStatusCacheEntry>, pub(crate) pending_api_worktree_creates: HashMap<std::path::PathBuf, u64>, pub(crate) pending_api_worktree_removes: HashMap<String, u64>, @@ -736,8 +740,10 @@ impl App { event_tx, event_rx, last_git_remote_status_refresh: Instant::now() - GIT_REMOTE_STATUS_REFRESH_INTERVAL, + last_git_repo_discovery_refresh: Instant::now(), git_refresh_in_flight: false, git_refresh_due_after_in_flight: false, + git_identity_refresh_requested: false, git_status_cache: HashMap::new(), pending_api_worktree_creates: HashMap::new(), pending_api_worktree_removes: HashMap::new(), @@ -892,10 +898,11 @@ impl App { pub(crate) fn handle_internal_event_with_prefix_sync( &mut self, event: crate::events::AppEvent, - ) { + ) -> bool { let previous_mode = self.state.mode; - self.handle_internal_event(event); + let changed = self.handle_internal_event_with_render_impact(event); self.sync_prefix_input_source(previous_mode); + changed } #[cfg(test)] @@ -1126,8 +1133,9 @@ impl App { match event { LoopEvent::Timer => {} LoopEvent::Internal(ev) => { - self.handle_internal_event_with_prefix_sync(ev); - needs_render = true; + if self.handle_internal_event_with_prefix_sync(ev) { + needs_render = true; + } } LoopEvent::Api(msg) => { if self.handle_api_request_message(*msg) { @@ -2131,6 +2139,20 @@ mod tests { } #[test] + fn unchanged_git_status_event_has_no_render_impact() { + let mut app = test_app(); + app.git_refresh_in_flight = true; + + let changed = app.handle_internal_event_with_prefix_sync(AppEvent::GitStatusRefreshed { + results: Vec::new(), + cache_updates: Vec::new(), + }); + + assert!(!changed); + assert!(!app.git_refresh_in_flight); + } + + #[test] fn git_status_event_clears_in_flight_refresh() { let mut app = test_app(); app.git_refresh_in_flight = true; @@ -2157,7 +2179,10 @@ mod tests { app.handle_internal_event(AppEvent::GitStatusRefreshed { results: vec![crate::workspace::WorkspaceGitStatus { workspace_id, - resolved_identity_cwd, + resolved_identity_cwd: resolved_identity_cwd.clone(), + status_cache_key: resolved_identity_cwd, + demand: crate::workspace::GitStatusRefreshDemand::ALL, + auto_label: "one".into(), branch: Some("render-dirty-test".into()), ahead_behind: Some((1, 0)), space: None, @@ -2388,6 +2413,21 @@ mod tests { } #[test] + fn unchanged_git_status_drain_has_no_render_impact() { + let mut app = test_app(); + app.git_refresh_in_flight = true; + app.event_tx + .try_send(AppEvent::GitStatusRefreshed { + results: Vec::new(), + cache_updates: Vec::new(), + }) + .unwrap(); + + assert!(!app.drain_internal_events()); + assert!(!app.git_refresh_in_flight); + } + + #[test] fn internal_event_drain_limits_work_per_tick() { let mut app = test_app(); for i in 0..=APP_EVENT_DRAIN_LIMIT { |
