Skip to content

Commit 703f965

Browse files
committed
cache key generation via graphql text
1 parent 9b8a3d9 commit 703f965

3 files changed

Lines changed: 173 additions & 162 deletions

File tree

cmd/prcost/repository.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ func analyzeRepository(ctx context.Context, owner, repo string, sampleSize, days
1919
since := time.Now().AddDate(0, 0, -days)
2020

2121
// Fetch all PRs modified since the date using library function
22-
prs, err := github.FetchPRsFromRepo(ctx, owner, repo, since, token, nil)
22+
prs, _, err := github.FetchPRsFromRepo(ctx, owner, repo, since, token, nil)
2323
if err != nil {
2424
return fmt.Errorf("failed to fetch PRs: %w", err)
2525
}
@@ -134,7 +134,7 @@ func analyzeOrganization(ctx context.Context, org string, sampleSize, days int,
134134
since := time.Now().AddDate(0, 0, -days)
135135

136136
// Fetch all PRs across the org modified since the date using library function
137-
prs, err := github.FetchPRsFromOrg(ctx, org, since, token, nil)
137+
prs, _, err := github.FetchPRsFromOrg(ctx, org, since, token, nil)
138138
if err != nil {
139139
return fmt.Errorf("failed to fetch PRs: %w", err)
140140
}

internal/server/server.go

Lines changed: 105 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -1568,26 +1568,22 @@ func (s *Server) processRepoSample(ctx context.Context, req *RepoSampleRequest,
15681568
// Calculate since date
15691569
since := time.Now().AddDate(0, 0, -req.Days)
15701570

1571-
// Try cache first
1572-
cacheKey := fmt.Sprintf("repo:%s/%s:days=%d", req.Owner, req.Repo, req.Days)
1573-
prs, cached := s.cachedPRQuery(ctx, cacheKey)
1574-
if cached {
1575-
s.logger.InfoContext(ctx, "Using cached PR query results",
1576-
"owner", req.Owner, "repo", req.Repo, "total_prs", len(prs))
1577-
} else {
1578-
// Fetch all PRs modified since the date
1579-
var err error
1580-
prs, err = github.FetchPRsFromRepo(ctx, req.Owner, req.Repo, since, token, nil)
1581-
if err != nil {
1582-
return nil, fmt.Errorf("failed to fetch PRs: %w", err)
1583-
}
1571+
// Fetch all PRs modified since the date (cache uses query hash internally)
1572+
var err error
1573+
var queryHash string
1574+
prs, queryHash, err := github.FetchPRsFromRepo(ctx, req.Owner, req.Repo, since, token, nil)
1575+
if err != nil {
1576+
return nil, fmt.Errorf("failed to fetch PRs: %w", err)
1577+
}
15841578

1585-
s.logger.InfoContext(ctx, "Fetched PRs from repository",
1586-
"owner", req.Owner, "repo", req.Repo, "total_prs", len(prs))
1579+
// Cache key includes query hash to invalidate when query structure changes
1580+
cacheKey := fmt.Sprintf("repo:%s/%s:days=%d:qh=%s", req.Owner, req.Repo, req.Days, queryHash)
15871581

1588-
// Cache query results
1589-
s.cachePRQuery(ctx, cacheKey, prs)
1590-
}
1582+
s.logger.InfoContext(ctx, "Fetched PRs from repository",
1583+
"owner", req.Owner, "repo", req.Repo, "total_prs", len(prs), "query_hash", queryHash)
1584+
1585+
// Cache query results
1586+
s.cachePRQuery(ctx, cacheKey, prs)
15911587

15921588
if len(prs) == 0 {
15931589
return nil, fmt.Errorf("no PRs found in the last %d days", req.Days)
@@ -1704,25 +1700,21 @@ func (s *Server) processOrgSample(ctx context.Context, req *OrgSampleRequest, to
17041700
// Calculate since date
17051701
since := time.Now().AddDate(0, 0, -req.Days)
17061702

1707-
// Try cache first
1708-
cacheKey := fmt.Sprintf("org:%s:days=%d", req.Org, req.Days)
1709-
prs, cached := s.cachedPRQuery(ctx, cacheKey)
1710-
if cached {
1711-
s.logger.InfoContext(ctx, "Using cached PR query results",
1712-
"org", req.Org, "total_prs", len(prs))
1713-
} else {
1714-
// Fetch all PRs across the org modified since the date
1715-
var err error
1716-
prs, err = github.FetchPRsFromOrg(ctx, req.Org, since, token, nil)
1717-
if err != nil {
1718-
return nil, fmt.Errorf("failed to fetch PRs: %w", err)
1719-
}
1703+
// Fetch all PRs across the org modified since the date (cache uses query hash internally)
1704+
var err error
1705+
var queryHash string
1706+
prs, queryHash, err := github.FetchPRsFromOrg(ctx, req.Org, since, token, nil)
1707+
if err != nil {
1708+
return nil, fmt.Errorf("failed to fetch PRs: %w", err)
1709+
}
17201710

1721-
s.logger.InfoContext(ctx, "Fetched PRs from organization", "org", req.Org, "total_prs", len(prs))
1711+
// Cache key includes query hash to invalidate when query structure changes
1712+
cacheKey := fmt.Sprintf("org:%s:days=%d:qh=%s", req.Org, req.Days, queryHash)
17221713

1723-
// Cache query results
1724-
s.cachePRQuery(ctx, cacheKey, prs)
1725-
}
1714+
s.logger.InfoContext(ctx, "Fetched PRs from organization", "org", req.Org, "total_prs", len(prs), "query_hash", queryHash)
1715+
1716+
// Cache query results
1717+
s.cachePRQuery(ctx, cacheKey, prs)
17261718

17271719
if len(prs) == 0 {
17281720
return nil, fmt.Errorf("no PRs found in the last %d days", req.Days)
@@ -2131,54 +2123,53 @@ func (s *Server) processRepoSampleWithProgress(ctx context.Context, req *RepoSam
21312123
// Calculate since date
21322124
since := time.Now().AddDate(0, 0, -req.Days)
21332125

2134-
// Try cache first
2135-
cacheKey := fmt.Sprintf("repo:%s/%s:days=%d", req.Owner, req.Repo, req.Days)
2136-
prs, cached := s.cachedPRQuery(ctx, cacheKey)
2137-
if !cached {
2138-
// Send progress update before GraphQL query
2126+
// Send progress update before GraphQL query
2127+
logSSEError(ctx, s.logger, sendSSE(writer, ProgressUpdate{
2128+
Type: "fetching",
2129+
PR: 0,
2130+
Owner: req.Owner,
2131+
Repo: req.Repo,
2132+
Progress: fmt.Sprintf("Querying GitHub GraphQL API for %s/%s PRs (last %d days)...", req.Owner, req.Repo, req.Days),
2133+
}))
2134+
2135+
// Start keep-alive to prevent client timeout during GraphQL query
2136+
stopKeepAlive, connErr := startKeepAlive(writer)
2137+
defer close(stopKeepAlive)
2138+
2139+
// Check for connection errors in background
2140+
go func() {
2141+
if err := <-connErr; err != nil {
2142+
s.logger.WarnContext(ctx, "Client connection lost", errorKey, err)
2143+
}
2144+
}()
2145+
2146+
// Fetch all PRs modified since the date with progress updates
2147+
var err error
2148+
var queryHash string
2149+
progressCallback := func(queryName string, page int, prCount int) {
21392150
logSSEError(ctx, s.logger, sendSSE(writer, ProgressUpdate{
21402151
Type: "fetching",
21412152
PR: 0,
21422153
Owner: req.Owner,
21432154
Repo: req.Repo,
2144-
Progress: fmt.Sprintf("Querying GitHub GraphQL API for %s/%s PRs (last %d days)...", req.Owner, req.Repo, req.Days),
2155+
Progress: fmt.Sprintf("Fetching %s PRs (page %d, %d PRs found)...", queryName, page, prCount),
21452156
}))
2157+
}
2158+
//nolint:contextcheck // Using background context intentionally to prevent client timeout from canceling work
2159+
prs, queryHash, err := github.FetchPRsFromRepo(workCtx, req.Owner, req.Repo, since, token, progressCallback)
2160+
if err != nil {
2161+
logSSEError(ctx, s.logger, sendSSE(writer, ProgressUpdate{
2162+
Type: "error",
2163+
Error: fmt.Sprintf("Failed to fetch PRs: %v", err),
2164+
}))
2165+
return
2166+
}
21462167

2147-
// Start keep-alive to prevent client timeout during GraphQL query
2148-
stopKeepAlive, connErr := startKeepAlive(writer)
2149-
defer close(stopKeepAlive)
2150-
2151-
// Check for connection errors in background
2152-
go func() {
2153-
if err := <-connErr; err != nil {
2154-
s.logger.WarnContext(ctx, "Client connection lost", errorKey, err)
2155-
}
2156-
}()
2157-
2158-
// Fetch all PRs modified since the date with progress updates
2159-
var err error
2160-
progressCallback := func(queryName string, page int, prCount int) {
2161-
logSSEError(ctx, s.logger, sendSSE(writer, ProgressUpdate{
2162-
Type: "fetching",
2163-
PR: 0,
2164-
Owner: req.Owner,
2165-
Repo: req.Repo,
2166-
Progress: fmt.Sprintf("Fetching %s PRs (page %d, %d PRs found)...", queryName, page, prCount),
2167-
}))
2168-
}
2169-
//nolint:contextcheck // Using background context intentionally to prevent client timeout from canceling work
2170-
prs, err = github.FetchPRsFromRepo(workCtx, req.Owner, req.Repo, since, token, progressCallback)
2171-
if err != nil {
2172-
logSSEError(ctx, s.logger, sendSSE(writer, ProgressUpdate{
2173-
Type: "error",
2174-
Error: fmt.Sprintf("Failed to fetch PRs: %v", err),
2175-
}))
2176-
return
2177-
}
2168+
// Cache key includes query hash to invalidate when query structure changes
2169+
cacheKey := fmt.Sprintf("repo:%s/%s:days=%d:qh=%s", req.Owner, req.Repo, req.Days, queryHash)
21782170

2179-
// Cache query results
2180-
s.cachePRQuery(ctx, cacheKey, prs)
2181-
}
2171+
// Cache query results
2172+
s.cachePRQuery(ctx, cacheKey, prs)
21822173

21832174
if len(prs) == 0 {
21842175
logSSEError(ctx, s.logger, sendSSE(writer, ProgressUpdate{
@@ -2290,52 +2281,51 @@ func (s *Server) processOrgSampleWithProgress(ctx context.Context, req *OrgSampl
22902281
// Calculate since date
22912282
since := time.Now().AddDate(0, 0, -req.Days)
22922283

2293-
// Try cache first
2294-
cacheKey := fmt.Sprintf("org:%s:days=%d", req.Org, req.Days)
2295-
prs, cached := s.cachedPRQuery(ctx, cacheKey)
2296-
if !cached {
2297-
// Send progress update before GraphQL query
2284+
// Send progress update before GraphQL query
2285+
logSSEError(ctx, s.logger, sendSSE(writer, ProgressUpdate{
2286+
Type: "fetching",
2287+
PR: 0,
2288+
Progress: fmt.Sprintf("Querying GitHub Search API for %s org PRs (last %d days)...", req.Org, req.Days),
2289+
}))
2290+
2291+
// Start keep-alive to prevent client timeout during GraphQL query
2292+
stopKeepAlive, connErr := startKeepAlive(writer)
2293+
defer close(stopKeepAlive)
2294+
2295+
// Check for connection errors in background
2296+
go func() {
2297+
if err := <-connErr; err != nil {
2298+
s.logger.WarnContext(ctx, "Client connection lost", errorKey, err)
2299+
}
2300+
}()
2301+
2302+
// Fetch all PRs across the org modified since the date with progress updates
2303+
var err error
2304+
var queryHash string
2305+
progressCallback := func(queryName string, page int, prCount int) {
22982306
logSSEError(ctx, s.logger, sendSSE(writer, ProgressUpdate{
22992307
Type: "fetching",
23002308
PR: 0,
2301-
Progress: fmt.Sprintf("Querying GitHub Search API for %s org PRs (last %d days)...", req.Org, req.Days),
2309+
Owner: req.Org,
2310+
Repo: "",
2311+
Progress: fmt.Sprintf("Fetching %s PRs (page %d, %d PRs found)...", queryName, page, prCount),
23022312
}))
2313+
}
2314+
//nolint:contextcheck // Using background context intentionally to prevent client timeout from canceling work
2315+
prs, queryHash, err := github.FetchPRsFromOrg(workCtx, req.Org, since, token, progressCallback)
2316+
if err != nil {
2317+
logSSEError(ctx, s.logger, sendSSE(writer, ProgressUpdate{
2318+
Type: "error",
2319+
Error: fmt.Sprintf("Failed to fetch PRs: %v", err),
2320+
}))
2321+
return
2322+
}
23032323

2304-
// Start keep-alive to prevent client timeout during GraphQL query
2305-
stopKeepAlive, connErr := startKeepAlive(writer)
2306-
defer close(stopKeepAlive)
2307-
2308-
// Check for connection errors in background
2309-
go func() {
2310-
if err := <-connErr; err != nil {
2311-
s.logger.WarnContext(ctx, "Client connection lost", errorKey, err)
2312-
}
2313-
}()
2324+
// Cache key includes query hash to invalidate when query structure changes
2325+
cacheKey := fmt.Sprintf("org:%s:days=%d:qh=%s", req.Org, req.Days, queryHash)
23142326

2315-
// Fetch all PRs across the org modified since the date with progress updates
2316-
var err error
2317-
progressCallback := func(queryName string, page int, prCount int) {
2318-
logSSEError(ctx, s.logger, sendSSE(writer, ProgressUpdate{
2319-
Type: "fetching",
2320-
PR: 0,
2321-
Owner: req.Org,
2322-
Repo: "",
2323-
Progress: fmt.Sprintf("Fetching %s PRs (page %d, %d PRs found)...", queryName, page, prCount),
2324-
}))
2325-
}
2326-
//nolint:contextcheck // Using background context intentionally to prevent client timeout from canceling work
2327-
prs, err = github.FetchPRsFromOrg(workCtx, req.Org, since, token, progressCallback)
2328-
if err != nil {
2329-
logSSEError(ctx, s.logger, sendSSE(writer, ProgressUpdate{
2330-
Type: "error",
2331-
Error: fmt.Sprintf("Failed to fetch PRs: %v", err),
2332-
}))
2333-
return
2334-
}
2335-
2336-
// Cache query results
2337-
s.cachePRQuery(ctx, cacheKey, prs)
2338-
}
2327+
// Cache query results
2328+
s.cachePRQuery(ctx, cacheKey, prs)
23392329

23402330
if len(prs) == 0 {
23412331
logSSEError(ctx, s.logger, sendSSE(writer, ProgressUpdate{

0 commit comments

Comments
 (0)