@@ -11,6 +11,7 @@ import (
1111
1212 "github.com/codeGROOVE-dev/slacker/pkg/state"
1313 "github.com/codeGROOVE-dev/sprinkler/pkg/client"
14+ "github.com/codeGROOVE-dev/turnclient/pkg/turn"
1415)
1516
1617// Constants for URL parsing.
@@ -84,13 +85,142 @@ func (c *Coordinator) lookupPRsForCheckEvent(ctx context.Context, event client.E
8485 owner := parts [3 ]
8586 repo := parts [4 ]
8687
87- slog .Info ("sprinkler cache miss - looking up PRs for commit via GitHub API" ,
88+ // First, check our local commit→PR cache (populated from recent PR events)
89+ // This is MUCH faster than GitHub API and usually works since check events
90+ // arrive seconds after PR events
91+ cachedPRs := c .commitPRCache .FindPRsForCommit (owner , repo , commitSHA )
92+ if len (cachedPRs ) > 0 {
93+ slog .Info ("found PRs for commit in cache - avoiding GitHub API call" ,
94+ "organization" , organization ,
95+ "owner" , owner ,
96+ "repo" , repo ,
97+ "commit_sha" , commitSHA ,
98+ "pr_count" , len (cachedPRs ),
99+ "pr_numbers" , cachedPRs ,
100+ "type" , event .Type ,
101+ "delivery_id" , deliveryID ,
102+ "cache_hit" , true )
103+ return cachedPRs
104+ }
105+
106+ // Cache miss - try turnclient lookup on most recent PR before falling back to GitHub API
107+ slog .Info ("commit→PR cache miss - will try turnclient on recent PR before GitHub API" ,
88108 "organization" , organization ,
89109 "owner" , owner ,
90110 "repo" , repo ,
91111 "commit_sha" , commitSHA ,
92112 "type" , event .Type ,
93- "delivery_id" , deliveryID )
113+ "delivery_id" , deliveryID ,
114+ "cache_hit" , false ,
115+ "reason" , "check event arrived before PR event or cache expired" )
116+
117+ // Second attempt: Check if we recently saw a PR for this repo
118+ // If yes, fetch it via turnclient to see if it contains this commit
119+ // This is cheaper than searching all PRs via GitHub API
120+ mostRecentPR := c .commitPRCache .MostRecentPR (owner , repo )
121+ if mostRecentPR > 0 {
122+ slog .Debug ("attempting turnclient lookup on most recent PR for repo" ,
123+ "organization" , organization ,
124+ "owner" , owner ,
125+ "repo" , repo ,
126+ "pr_number" , mostRecentPR ,
127+ "commit_sha" , commitSHA ,
128+ "rationale" , "check events usually arrive for recently updated PRs" )
129+
130+ // Get GitHub token
131+ githubToken := c .github .InstallationToken (ctx )
132+ if githubToken != "" {
133+ // Create turnclient
134+ turnClient , tcErr := turn .NewDefaultClient ()
135+ if tcErr == nil {
136+ turnClient .SetAuthToken (githubToken )
137+
138+ // Check the recent PR with current timestamp
139+ checkCtx , checkCancel := context .WithTimeout (ctx , 30 * time .Second )
140+ prURL := fmt .Sprintf ("https://github.com/%s/%s/pull/%d" , owner , repo , mostRecentPR )
141+ checkResult , checkErr := turnClient .Check (checkCtx , prURL , owner , time .Now ())
142+ checkCancel ()
143+
144+ if checkErr == nil && checkResult != nil {
145+ // Check if any commits match
146+ for _ , prCommit := range checkResult .PullRequest .Commits {
147+ if prCommit == commitSHA {
148+ slog .Info ("found commit in most recent PR via turnclient - avoiding GitHub API search" ,
149+ "organization" , organization ,
150+ "owner" , owner ,
151+ "repo" , repo ,
152+ "pr_number" , mostRecentPR ,
153+ "commit_sha" , commitSHA ,
154+ "turnclient_hit" , true ,
155+ "bonus" , "got free PR status update" )
156+
157+ // Populate cache with all commits from this PR
158+ for _ , commit := range checkResult .PullRequest .Commits {
159+ if commit != "" {
160+ c .commitPRCache .RecordPR (owner , repo , mostRecentPR , commit )
161+ }
162+ }
163+
164+ // Process the PR update since we have fresh data
165+ go c .handlePullRequestEventWithData (context .Background (), owner , repo , struct {
166+ Action string `json:"action"`
167+ PullRequest struct {
168+ HTMLURL string `json:"html_url"`
169+ Title string `json:"title"`
170+ CreatedAt time.Time `json:"created_at"`
171+ User struct {
172+ Login string `json:"login"`
173+ } `json:"user"`
174+ Number int `json:"number"`
175+ } `json:"pull_request"`
176+ Number int `json:"number"`
177+ }{
178+ Action : "synchronize" ,
179+ PullRequest : struct {
180+ HTMLURL string `json:"html_url"`
181+ Title string `json:"title"`
182+ CreatedAt time.Time `json:"created_at"`
183+ User struct {
184+ Login string `json:"login"`
185+ } `json:"user"`
186+ Number int `json:"number"`
187+ }{
188+ HTMLURL : prURL ,
189+ Title : checkResult .PullRequest .Title ,
190+ CreatedAt : checkResult .PullRequest .CreatedAt ,
191+ User : struct {
192+ Login string `json:"login"`
193+ }{
194+ Login : checkResult .PullRequest .Author ,
195+ },
196+ Number : mostRecentPR ,
197+ },
198+ Number : mostRecentPR ,
199+ }, checkResult , nil )
200+
201+ return []int {mostRecentPR }
202+ }
203+ }
204+
205+ slog .Debug ("commit not found in most recent PR - will fall back to GitHub API" ,
206+ "organization" , organization ,
207+ "owner" , owner ,
208+ "repo" , repo ,
209+ "pr_number" , mostRecentPR ,
210+ "commit_sha" , commitSHA ,
211+ "pr_commits_checked" , len (checkResult .PullRequest .Commits ))
212+ }
213+ }
214+ }
215+ }
216+
217+ // Third attempt: Fall back to GitHub API to search all PRs
218+ slog .Info ("falling back to GitHub API to search all PRs for commit" ,
219+ "organization" , organization ,
220+ "owner" , owner ,
221+ "repo" , repo ,
222+ "commit_sha" , commitSHA ,
223+ "tried_turnclient" , mostRecentPR > 0 )
94224
95225 // Look up PRs for this commit using GitHub API
96226 // Allow up to 3 minutes for retries (2 min max delay + buffer)
0 commit comments