mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-01-31 20:03:37 +00:00
fix: Prevent GitHub API rate limiting from frequent worktree PR fetching
Fixes #685 This commit addresses the GitHub API rate limit issue caused by excessive worktree PR status fetching. ## Changes ### Server-side PR caching (list.ts) - Added `GitHubPRCacheEntry` interface and `githubPRCache` Map - Implemented 2-minute TTL cache for GitHub PR data - Modified `fetchGitHubPRs()` to check cache before making API calls - Added `forceRefresh` parameter to bypass cache when explicitly requested - Cache is properly cleared when force refresh is triggered ### Frontend polling reduction (worktree-panel.tsx) - Increased worktree polling interval from 5 seconds to 30 seconds - Reduces polling frequency by 6x while keeping UI reasonably fresh - Updated comment to reflect new polling strategy ### Type improvements (use-worktrees.ts) - Fixed `fetchWorktrees` callback signature to accept `silent` option - Returns proper type for removed worktrees detection ## Impact - Combined ~12x reduction in GitHub API calls - 2-minute cache prevents repeated API hits during normal operation - 30-second polling balances responsiveness with API conservation - Force refresh option allows users to manually update when needed 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -95,12 +95,20 @@ export function useWorktrees({
|
||||
);
|
||||
|
||||
// fetchWorktrees for backward compatibility - now just triggers a refetch
|
||||
const fetchWorktrees = useCallback(async () => {
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: queryKeys.worktrees.all(projectPath),
|
||||
});
|
||||
return refetch();
|
||||
}, [projectPath, queryClient, refetch]);
|
||||
// The silent option is accepted but not used (React Query handles loading states)
|
||||
// Returns removed worktrees array if any were detected, undefined otherwise
|
||||
const fetchWorktrees = useCallback(
|
||||
async (_options?: {
|
||||
silent?: boolean;
|
||||
}): Promise<Array<{ path: string; branch: string }> | undefined> => {
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: queryKeys.worktrees.all(projectPath),
|
||||
});
|
||||
const result = await refetch();
|
||||
return result.data?.removedWorktrees;
|
||||
},
|
||||
[projectPath, queryClient, refetch]
|
||||
);
|
||||
|
||||
const currentWorktreePath = currentWorktree?.path ?? null;
|
||||
const selectedWorktree = currentWorktreePath
|
||||
|
||||
@@ -383,13 +383,13 @@ export function WorktreePanel({
|
||||
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
// Periodic interval check (5 seconds) to detect branch changes on disk
|
||||
// Reduced from 1s to 5s to minimize GPU/CPU usage from frequent re-renders
|
||||
// Periodic interval check (30 seconds) to detect branch changes on disk
|
||||
// Reduced polling to lessen repeated worktree list calls while keeping UI reasonably fresh
|
||||
const intervalRef = useRef<NodeJS.Timeout | null>(null);
|
||||
useEffect(() => {
|
||||
intervalRef.current = setInterval(() => {
|
||||
fetchWorktrees({ silent: true });
|
||||
}, 5000);
|
||||
}, 30000);
|
||||
|
||||
return () => {
|
||||
if (intervalRef.current) {
|
||||
|
||||
Reference in New Issue
Block a user