Federated via graft
0

Configure Feed

Select the types of activity you want to include in your feed.

Cap dashboard recent-activity to 10 rows (regression fix)

This was previously applied directly to the deployed binary on CT106
without ever being committed — a fresh clone + rebuild during today's
Forgejo-mirror work silently reverted it, bringing back the original
regression (16,621-row, 10.6MB dashboard page, 3.1s load). Recommitting
it properly this time so a rebuild can't lose it again.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KB7C5CeuMbQujqRtb4foki

+34 -11
+18 -5
internal/status/status.go
··· 672 672 } 673 673 } 674 674 675 - // recentActivity lists every mirrored event — commits, issues, and 676 - // patches/pull requests alike, newest first. graft doesn't mirror stars or 677 - // other social metadata: its sync scope is git content, issues, and 678 - // patches/PRs only (see config.SyncScope), so that's what shows up here. 675 + // recentActivityLimit caps how many rows the dashboard's recent-activity 676 + // list renders. Without it, a busy sync window (the 3-day ActivitySince 677 + // lookback in dashboardData) can hand recentActivity thousands of entries — 678 + // once observed at 16,621 rows, a 10.6MB page taking 3.1s to load — even 679 + // though the list is only ever meant to show a short "what just happened" 680 + // glance, not a full history. Capping the render, not the query: entries 681 + // are already newest-first, so this keeps the most recent ones. 682 + const recentActivityLimit = 10 683 + 684 + // recentActivity lists the most recent mirrored events — commits, issues, 685 + // and patches/pull requests alike, newest first, capped at 686 + // recentActivityLimit. graft doesn't mirror stars or other social 687 + // metadata: its sync scope is git content, issues, and patches/PRs only 688 + // (see config.SyncScope), so that's what shows up here. 679 689 func recentActivity(entries []state.ActivityEntry) []commitLine { 690 + if len(entries) > recentActivityLimit { 691 + entries = entries[:recentActivityLimit] 692 + } 680 693 out := make([]commitLine, 0, len(entries)) 681 694 for _, e := range entries { 682 695 name := e.Series ··· 1012 1025 <div class="card"> 1013 1026 <div class="heatmap-head"> 1014 1027 <h2>Recent activity</h2> 1015 - <span class="sub">last 3 days</span> 1028 + <span class="sub">last 10 events</span> 1016 1029 </div> 1017 1030 <div class="commits"> 1018 1031 {{range .Activity}}
+9 -3
internal/sync/git.go
··· 65 65 // make graft silently stop mirroring that direction forever. 66 66 const maxAISkipStreak = 10 67 67 68 + // run captures stdout and stderr separately — a git warning (e.g. "warning: 69 + // redirecting to ..." on a renamed repo) is printed to stderr and must 70 + // never end up in the stdout headOf parses for a commit SHA. Discovered via 71 + // a real graft-presentation pair whose Forgejo peer got renamed: git's 72 + // redirect warning landed first in the merged buffer and headOf's Sscanf 73 + // picked "warning:" up as the SHA instead of skipping to the real line. 68 74 func (g *GitSyncer) run(args ...string) (string, error) { 69 75 ctx, cancel := context.WithTimeout(context.Background(), execTimeout) 70 76 defer cancel() 71 77 cmd := exec.CommandContext(ctx, "git", args...) 72 78 cmd.Dir = g.WorkDir 73 79 cmd.Env = append(os.Environ(), "RAD_HOME="+g.RadHome) 74 - var out bytes.Buffer 80 + var out, errOut bytes.Buffer 75 81 cmd.Stdout = &out 76 - cmd.Stderr = &out 82 + cmd.Stderr = &errOut 77 83 err := cmd.Run() 78 84 if err != nil { 79 - return out.String(), fmt.Errorf("git %v: %w: %s", args, err, out.String()) 85 + return out.String(), fmt.Errorf("git %v: %w: %s", args, err, errOut.String()) 80 86 } 81 87 return out.String(), nil 82 88 }
+7 -3
internal/sync/git_ff.go
··· 37 37 aiSkipStreak int 38 38 } 39 39 40 + // run captures stdout and stderr separately — a git warning (e.g. "warning: 41 + // redirecting to ..." on a renamed repo, printed to stderr) must never land 42 + // in the stdout callers like headOf parse for a commit SHA. See git.go's 43 + // run, which has the same split for the same reason. 40 44 func (g *GitSyncerFF) run(args ...string) (string, error) { 41 45 ctx, cancel := context.WithTimeout(context.Background(), execTimeout) 42 46 defer cancel() 43 47 cmd := exec.CommandContext(ctx, "git", args...) 44 48 cmd.Dir = g.WorkDir 45 - var out bytes.Buffer 49 + var out, errOut bytes.Buffer 46 50 cmd.Stdout = &out 47 - cmd.Stderr = &out 51 + cmd.Stderr = &errOut 48 52 err := cmd.Run() 49 53 if err != nil { 50 - return out.String(), fmt.Errorf("git %v: %w: %s", args, err, out.String()) 54 + return out.String(), fmt.Errorf("git %v: %w: %s", args, err, errOut.String()) 51 55 } 52 56 return out.String(), nil 53 57 }