fix(router): eliminate N+1 DB/API calls in GitHubRouterAdapter#989
Merged
zbigniewsobiecki merged 1 commit intodevfrom Mar 23, 2026
Merged
fix(router): eliminate N+1 DB/API calls in GitHubRouterAdapter#989zbigniewsobiecki merged 1 commit intodevfrom
zbigniewsobiecki merged 1 commit intodevfrom
Conversation
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
nhopeatall
approved these changes
Mar 23, 2026
Collaborator
nhopeatall
left a comment
There was a problem hiding this comment.
Summary
LGTM — well-designed performance optimization that eliminates N+1 DB/API calls in the GitHub webhook pipeline through three complementary caching layers: per-request instance caching, module-level TTL cache, and pass-through of pre-resolved objects.
Verification
Correctness:
- The adapter is confirmed to be instantiated once per webhook request (
new GitHubRouterAdapter()insrc/router/index.ts:108), so instance fields are properly request-scoped. findProjectCachedandresolvePersonaCachedcorrectly use sentinel values (undefinedfor "not yet fetched" vsnullfor "fetched but not found") to distinguish cache states.- Failed persona resolutions are NOT cached (the
catchblock leavescachedPersonasasundefined), allowing retries within the same request — this is correct. - Error semantics are preserved:
resolvePersonaCachedswallows errors (matching the oldtry/catchindispatchWithCredentials), while the module-levelresolvePersonaIdentitiescache re-throws errors (matching its documented behavior and differing intentionally fromBotIdentityCache).
Architecture:
- The 60s TTL cache in
personas.tsfollows the same pattern as the existingBotIdentityCacheclass (same TTL, sameMap<string, {value, expiresAt}>structure). Consistent with established codebase patterns. - The optional
projectparameter onresolveGitHubTokenForAckByAgentis a clean backward-compatible extension. - The
Promise.allparallelization of credential lookups is a straightforward win.
Testing:
- New tests cover all caching behaviors: hit/miss, TTL expiry, per-project isolation, manual reset, and cross-method caching within the adapter.
- All CI checks pass.
🕵️ claude-code · claude-opus-4-6 · run details
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Addresses a Sentry-reported N+1 query issue in the GitHub webhook processing pipeline. Each webhook was triggering 3x
resolvePersonaIdentities()calls (2 DB + 2 GitHub API each), 2-3xfindProjectByRepo()calls, and 3xloadProjectConfig()calls — all for the same request.Expected impact: Reduces DB queries per GitHub webhook from ~10–15 to ~3–4, and GitHub API calls from 4–6 to 2 (globally cached with 60s TTL).
GitHubRouterAdapter—findProjectByRepo()andresolvePersonaIdentities()results are cached in private instance fields. The adapter is instantiated once per webhook request so this is naturally request-scoped, preventing redundant calls acrossisSelfAuthored,sendReaction,dispatchWithCredentials, andpostAck.cachedFullProjectfield in the adapter — populated bydispatchWithCredentials, reused inpostAckto skip a secondloadProjectConfig()call.resolvePersonaIdentities()insrc/github/personas.ts— prevents redundant DB + GitHub API lookups across rapid successive webhooks for the same project. Errors are re-thrown (unlikeBotIdentityCachewhich silences them) to preserve caller error semantics.projectparameter onresolveGitHubTokenForAckByAgent()— when the adapter passes its cached project config, thefindProjectByRepo()DB lookup in the token resolver is skipped entirely.resolvePersonaIdentities()— implementer and reviewer token lookups now usePromise.allinstead of sequential awaits, halving round-trip latency.Test plan
findProjectByRepoandresolvePersonaIdentitiescalled once per pipelinefindProjectByReposkipped when pre-resolved project providedCard
https://trello.com/c/ZSiSPvKM/515-address-sentry-reported-issue
🤖 Generated with Claude Code
🕵️ claude-code · claude-sonnet-4-6 · run details