feat: change inngest functions positions#48
Conversation
📝 WalkthroughWalkthroughThe PR refactors the GitHub webhook handler to replace sequential PR summary and review operations with separate, independently-guarded asynchronous blocks. Error handling is now localized to each operation, and both triggers are extended to activate on both "opened" and "synchronized" actions. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
Summary by CodeReverb
Generated automatically by CodeReverb Try out CodeReverb |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
app/api/webhooks/github/route.ts (1)
112-142: Consider parallelizing independent operations.Both operations are currently executed sequentially (summary completes before review starts). Since they're independent with separate error handling, they could run in parallel to reduce overall processing time.
🔎 Proposed parallel execution using Promise.allSettled
- if (action === "opened" || action === "synchronized") { - try { - await generatePullRequestSummary( - owner, - repoName, - prNumber, - pull_request?.title, - pull_request?.body, - body?.installation?.id, - pull_request?.base?.sha, - pull_request?.head?.sha, - pull_request?.changed_files, - pull_request?.additions, - pull_request?.deletions - ); - console.log(`Summary completed for: ${repo} #${prNumber}`); - } catch (error) { - console.error( - `Summarization failed for repo: ${repo} #${prNumber}: `, - error - ); - } - - try { - await reviewPullRequest(owner, repoName, prNumber); - console.log(`Review completed for: ${repo} #${prNumber}`); - } catch (error) { - console.error( - `Review failed for repo: ${repo} #${prNumber}: `, - error - ); - } - } + if (action === "opened" || action === "synchronized") { + const [summaryResult, reviewResult] = await Promise.allSettled([ + generatePullRequestSummary( + owner, + repoName, + prNumber, + pull_request?.title, + pull_request?.body, + body?.installation?.id, + pull_request?.base?.sha, + pull_request?.head?.sha, + pull_request?.changed_files, + pull_request?.additions, + pull_request?.deletions + ), + reviewPullRequest(owner, repoName, prNumber), + ]); + + if (summaryResult.status === "fulfilled") { + console.log(`Summary completed for: ${repo} #${prNumber}`); + } else { + console.error( + `Summarization failed for repo: ${repo} #${prNumber}: `, + summaryResult.reason + ); + } + + if (reviewResult.status === "fulfilled") { + console.log(`Review completed for: ${repo} #${prNumber}`); + } else { + console.error( + `Review failed for repo: ${repo} #${prNumber}: `, + reviewResult.reason + ); + } + }
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
app/api/webhooks/github/route.ts
🧰 Additional context used
🧬 Code graph analysis (1)
app/api/webhooks/github/route.ts (1)
lib/ai/actions/index.ts (2)
generatePullRequestSummary(139-202)reviewPullRequest(7-137)
🔇 Additional comments (1)
app/api/webhooks/github/route.ts (1)
112-132: Good: Independent error handling for each operation.The isolated try-catch blocks ensure that failures in one operation don't cascade to the other. Each has specific logging that will aid debugging. Since both operations queue Inngest events for async processing, this fire-and-forget pattern with localized error handling is appropriate.
Also applies to: 134-142
| if (action === "opened" || action === "synchronized") { | ||
| await reviewPullRequest(owner, repoName, prNumber) | ||
| .then(() => console.log(`Review completed for: ${repo} #${prNumber}`)) | ||
| .catch((error) => | ||
| console.error( | ||
| `Review failed for repo: ${repo} #${prNumber}: `, | ||
| error | ||
| ) | ||
| try { | ||
| await generatePullRequestSummary( | ||
| owner, | ||
| repoName, | ||
| prNumber, | ||
| pull_request?.title, | ||
| pull_request?.body, | ||
| body?.installation?.id, | ||
| pull_request?.base?.sha, | ||
| pull_request?.head?.sha, | ||
| pull_request?.changed_files, | ||
| pull_request?.additions, | ||
| pull_request?.deletions | ||
| ); | ||
| console.log(`Summary completed for: ${repo} #${prNumber}`); | ||
| } catch (error) { | ||
| console.error( | ||
| `Summarization failed for repo: ${repo} #${prNumber}: `, | ||
| error | ||
| ); | ||
| } | ||
|
|
||
| try { | ||
| await reviewPullRequest(owner, repoName, prNumber); | ||
| console.log(`Review completed for: ${repo} #${prNumber}`); | ||
| } catch (error) { | ||
| console.error( | ||
| `Review failed for repo: ${repo} #${prNumber}: `, | ||
| error | ||
| ); | ||
| } | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Search for rate limiting, deduplication, and idempotency patterns
rg -n 'rateLimit|debounce|throttle|idempotency|dedup|concurrency' --type ts --type jsRepository: afuhflynn/code-reverb
Length of output: 884
🏁 Script executed:
# Check for Inngest event definitions and handlers related to PR summary and review
rg -n 'pr\.summary|pr\.review|pullRequest.*summary|pullRequest.*review' --type ts --type jsRepository: afuhflynn/code-reverb
Length of output: 1157
🏁 Script executed:
# Look for the Inngest function definitions
fd -t f -e ts -e js 'inngest' | head -20Repository: afuhflynn/code-reverb
Length of output: 79
🏁 Script executed:
# Check the structure of the repository to understand the architecture
git ls-files | grep -E '(inngest|event|webhook)' | head -30Repository: afuhflynn/code-reverb
Length of output: 216
🏁 Script executed:
# Read the webhook handler to check for deduplication logic
cat -n app/api/webhooks/github/route.ts | head -160Repository: afuhflynn/code-reverb
Length of output: 6005
🏁 Script executed:
# Read the Inngest functions to see concurrency and event handling
cat -n inngest/functions/index.ts | sed -n '320,430p'Repository: afuhflynn/code-reverb
Length of output: 3799
🏁 Script executed:
# Check lib/inngest.ts to understand the setup
cat -n lib/inngest.tsRepository: afuhflynn/code-reverb
Length of output: 246
🏁 Script executed:
# Read lib/ai/actions/index.ts to see how events are triggered
cat -n lib/ai/actions/index.ts | sed -n '1,100p'Repository: afuhflynn/code-reverb
Length of output: 3152
🏁 Script executed:
# Look for the generatePullRequestSummary and reviewPullRequest functions
rg -n -A 15 'export.*generatePullRequestSummary|export.*reviewPullRequest' lib/ai/actions/index.tsRepository: afuhflynn/code-reverb
Length of output: 874
🏁 Script executed:
# Read the full generatePullRequestSummary function
cat -n lib/ai/actions/index.ts | sed -n '139,250p'Repository: afuhflynn/code-reverb
Length of output: 1977
Concurrent execution recommended for independent operations.
The triggering on "synchronized" is intentional and processed through Inngest with concurrency limits (summarize-pr: 20, generate-review: 5). However, you're making sequential API calls in the webhook handler — consider parallelizing these with Promise.all() since they're independent operations:
if (action === "opened" || action === "synchronized") {
await Promise.all([
generatePullRequestSummary(...).catch(error =>
console.error(`Summarization failed for repo: ${repo} #${prNumber}: `, error)
),
reviewPullRequest(...).catch(error =>
console.error(`Review failed for repo: ${repo} #${prNumber}: `, error)
),
]);
}Also add webhook deduplication to handle GitHub's redelivery mechanism (webhook events can be redelivered). Consider tracking X-GitHub-Delivery header or adding idempotency keys to Inngest events to prevent duplicate processing.
🤖 Prompt for AI Agents
In app/api/webhooks/github/route.ts around lines 111 to 143 you run
generatePullRequestSummary and reviewPullRequest sequentially; make them run in
parallel with Promise.all to improve throughput and reduce latency, wrapping
each call with its own catch so one failure doesn’t block the other and logging
errors as before; additionally add webhook deduplication by reading the
X-GitHub-Delivery header (or generating an idempotency key) and checking/storing
that ID (or passing it to Inngest as an idempotency key) so redelivered events
are ignored or de-duplicated.
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.