Skip to content

perf(desktop): parallelize git status checks and optimize file scanning#679

Merged
Kitenite merged 3 commits intomainfrom
consider-git-checks
Jan 8, 2026
Merged

perf(desktop): parallelize git status checks and optimize file scanning#679
Kitenite merged 3 commits intomainfrom
consider-git-checks

Conversation

@Kitenite
Copy link
Copy Markdown
Collaborator

@Kitenite Kitenite commented Jan 8, 2026

Summary

  • Parallelize independent git operations (branch comparison, tracking status, numstat) using Promise.all() instead of sequential awaits
  • Optimize untracked file line counting: limit to 50 files max, 100KB size limit, process in parallel batches of 10
  • Add staleTime and disable background refetch on the client to prevent UI flicker and request overlap

Context

The getStatus tRPC procedure runs every 2.5 seconds to poll for git changes. Previously it ran 7-9 git commands sequentially plus read all untracked files one at a time, which could cause UI lag especially with many files.

Test plan

  • Verify Changes panel still shows correct staged/unstaged/untracked files
  • Verify commit counts and branch comparison work correctly
  • Test with a repo that has many untracked files (>50) to confirm limiting works
  • Monitor for UI responsiveness during polling

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Improvements
    • Enhanced performance of status calculations by optimizing Git operations processing.
    • Improved changes view UI stability by reducing unnecessary updates and preventing duplicate requests, resulting in a smoother user experience with less flickering.

✏️ Tip: You can customize this high-level summary in your review settings.

The getStatus procedure was running 7-9 git commands sequentially every 2.5s,
plus reading all untracked files one at a time. This could cause UI lag.

Changes:
- Run branch comparison, tracking status, and numstat operations in parallel
- Limit untracked file line counting to 50 files max (100KB each)
- Process file reads in parallel batches of 10
- Add staleTime and disable background refetch to prevent request overlap

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 8, 2026

Warning

Rate limit exceeded

@Kitenite has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 16 minutes and 32 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 92634e5 and e6cc433.

📒 Files selected for processing (1)
  • apps/desktop/src/lib/trpc/routers/changes/status.ts
📝 Walkthrough

Walkthrough

Refactored the Git status operation to parallelize multiple queries—branch comparison, tracking status, and numstat computations—along with batched untracked line counting. Added query caching options to the Changes view to reduce UI flicker and prevent concurrent refetches.

Changes

Cohort / File(s) Summary
Git Status Parallelization
apps/desktop/src/lib/trpc/routers/changes/status.ts
Introduced Promise.all() to parallelize branch comparison, tracking status, and numstat operations. Refactored untracked line counting with batched concurrency control (10 concurrent reads, 50 file cap, 100 KiB size limit). Added performance-tuned constants MAX_LINE_COUNT_SIZE, MAX_FILES_TO_COUNT, and FILE_READ_CONCURRENCY.
Query Behavior Optimization
apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/ChangesView/ChangesView.tsx
Added staleTime: 2000 to preserve cached data during refetch and refetchIntervalInBackground: false to prevent overlapping in-flight requests.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 Hop, hop, parallel flow—
Git tasks dance together, don't you know?
Batches and cache, with concurrency grace,
The status now runs at a speedy pace!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main changes: parallelization of git status checks and optimization of file scanning, which are the primary focuses of the changeset.
Description check ✅ Passed The description covers all required template sections: summary of changes, context, and test plan. However, it uses a generated with Claude Code footer instead of the standard PR template structure.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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 and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/ChangesView/ChangesView.tsx (1)

56-59: Misleading comment about refetchIntervalInBackground.

The comment on line 58 states this option cancels in-flight requests, but refetchIntervalInBackground: false only pauses interval-based refetching when the window is not focused—it does not cancel existing requests. Consider updating the comment to accurately describe the behavior.

📝 Suggested comment fix
 			// Keep previous data while refetching to prevent UI flicker
 			staleTime: 2000,
-			// Ensure we don't overlap requests - cancel in-flight when new one starts
+			// Pause interval refetching when window is in background
 			refetchIntervalInBackground: false,
apps/desktop/src/lib/trpc/routers/changes/status.ts (1)

176-178: Consider minimal logging for debugging purposes.

Per coding guidelines, errors should not be silently swallowed. While skipping unreadable files is the correct behavior here, adding debug-level logging would help diagnose issues in development without impacting performance.

💡 Optional: Add debug logging
 			} catch {
-				// Skip files that fail validation or reading
+				// Skip files that fail validation or reading (expected for deleted/inaccessible files)
+				console.debug(`[changes/status] Skipped untracked file: ${file.path}`);
 			}
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cec714b and 92634e5.

📒 Files selected for processing (2)
  • apps/desktop/src/lib/trpc/routers/changes/status.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/ChangesView/ChangesView.tsx
🧰 Additional context used
📓 Path-based instructions (6)
apps/desktop/**/*.{ts,tsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

apps/desktop/**/*.{ts,tsx}: For Electron interprocess communication, ALWAYS use tRPC as defined in src/lib/trpc
Use alias as defined in tsconfig.json when possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary.
For tRPC subscriptions with trpc-electron, ALWAYS use the observable pattern from @trpc/server/observable instead of async generators, as the library explicitly checks isObservable(result) and throws an error otherwise

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/ChangesView/ChangesView.tsx
  • apps/desktop/src/lib/trpc/routers/changes/status.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use object parameters for functions with 2+ parameters instead of positional arguments
Functions with 2+ parameters should accept a single params object with named properties for self-documentation and extensibility
Use prefixed console logging with context pattern: [domain/operation] message
Extract magic numbers and hardcoded values to named constants at module top
Use lookup objects/maps instead of repeated if (type === ...) conditionals
Avoid using any type - maintain type safety in TypeScript code
Never swallow errors silently - at minimum log them with context
Import from concrete files directly when possible - avoid barrel file abuse that creates circular dependencies
Avoid deep nesting (4+ levels) - use early returns, extract functions, and invert conditions
Use named properties in options objects instead of boolean parameters to avoid boolean blindness

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/ChangesView/ChangesView.tsx
  • apps/desktop/src/lib/trpc/routers/changes/status.ts
apps/desktop/src/renderer/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Never import Node.js modules (fs, path, os, net) in renderer process or shared code - they are externalized for browser compatibility

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/ChangesView/ChangesView.tsx
**/*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

One component per file - do not create multi-component files

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/ChangesView/ChangesView.tsx
apps/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Drizzle ORM for all database operations - never use raw SQL

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/ChangesView/ChangesView.tsx
  • apps/desktop/src/lib/trpc/routers/changes/status.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Biome for formatting and linting - run at root level with bun run lint:fix or biome check --write

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/ChangesView/ChangesView.tsx
  • apps/desktop/src/lib/trpc/routers/changes/status.ts
🧬 Code graph analysis (1)
apps/desktop/src/lib/trpc/routers/changes/status.ts (3)
apps/desktop/src/lib/trpc/routers/changes/utils/parse-status.ts (1)
  • parseGitStatus (31-74)
apps/desktop/src/lib/trpc/routers/changes/utils/apply-numstat.ts (1)
  • applyNumstatToFiles (5-24)
apps/desktop/src/shared/changes-types.ts (1)
  • ChangedFile (22-28)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build
🔇 Additional comments (3)
apps/desktop/src/lib/trpc/routers/changes/status.ts (3)

32-44: Good parallelization of independent operations.

The Promise.all pattern correctly runs independent operations concurrently. The destructuring intentionally ignores the void results from the mutation functions (applyNumstatToFiles, applyUntrackedLineCount). This is a valid pattern, though a brief inline comment clarifying that the last three operations mutate their inputs in place would improve readability for future maintainers.


149-154: Well-structured performance constants.

Good extraction of magic numbers into named constants with clear documentation. The values are sensible for the use case.


160-181: Solid batched concurrency implementation.

The sequential batch processing with Promise.all effectively limits concurrent file operations to 10 at a time, preventing resource exhaustion. The early slice at line 161 ensures the 50-file cap is applied upfront. Good balance between parallelism and resource management.

Kitenite and others added 2 commits January 8, 2026 14:55
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@Kitenite Kitenite merged commit 366a083 into main Jan 8, 2026
5 checks passed
@Kitenite Kitenite deleted the consider-git-checks branch January 8, 2026 23:00
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jan 8, 2026

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ⚠️ Neon database branch
  • ⚠️ Electric Fly.io app

Thank you for your contribution! 🎉

saddlepaddle pushed a commit that referenced this pull request Jan 10, 2026
…ng (#679)

* perf(desktop): parallelize git status checks and optimize file scanning

The getStatus procedure was running 7-9 git commands sequentially every 2.5s,
plus reading all untracked files one at a time. This could cause UI lag.

Changes:
- Run branch comparison, tracking status, and numstat operations in parallel
- Limit untracked file line counting to 50 files max (100KB each)
- Process file reads in parallel batches of 10
- Add staleTime and disable background refetch to prevent request overlap
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