perf(github): stop re-spawning the repo-identity probe every 30 seconds (#16450)

This commit is contained in:
Neil
2026-08-25 18:16:58 -07:00
committed by GitHub
parent cac5388545
commit 67f2fc9e7c
2 changed files with 136 additions and 5 deletions
+22 -5
View File
@@ -61,6 +61,14 @@ export function ghRepoExecOptions(context: GitHubRepoContext): {
const OWNER_REPO_POSITIVE_CACHE_TTL_MS = 30_000
const OWNER_REPO_NEGATIVE_CACHE_TTL_MS = 5 * 60_000
/**
* A signature-backed answer is held as long as a negative one. `git remote
* get-url` reads `.git/config`, and the signature covers that file plus every
* path it includes — so while the signature holds, a re-probe can only return
* what is already cached. The short TTL above is the no-signature fallback
* (remote runtimes, an unreadable gitdir), where nothing invalidates on change.
*/
const OWNER_REPO_SIGNED_CACHE_TTL_MS = 5 * 60_000
const OWNER_REPO_CACHE_MAX_ENTRIES = 512
type OwnerRepoCacheEntry = {
@@ -106,10 +114,10 @@ export async function getRemoteUrlForRepo(
}
function getOwnerRepoCacheTtl(value: OwnerRepo | null, configSignature?: string): number {
if (value) {
return OWNER_REPO_POSITIVE_CACHE_TTL_MS
if (configSignature) {
return value ? OWNER_REPO_SIGNED_CACHE_TTL_MS : OWNER_REPO_NEGATIVE_CACHE_TTL_MS
}
return configSignature ? OWNER_REPO_NEGATIVE_CACHE_TTL_MS : OWNER_REPO_POSITIVE_CACHE_TTL_MS
return OWNER_REPO_POSITIVE_CACHE_TTL_MS
}
export async function getOwnerRepoForRemote(
@@ -135,7 +143,11 @@ export async function getOwnerRepoForRemote(
pruneOwnerRepoCache(now)
const cached = ownerRepoCache.get(cacheKey)
if (cached && cached.expiresAt > now) {
if (cached.value === null && cached.configSignature !== undefined) {
// Why every signed entry, not only the negatives: a positive identity is
// held for the same five minutes now, so the same revalidation is what
// keeps a `git remote set-url` visible within one lookup rather than five
// minutes. The signature read is fs stat/readFile, not a Git subprocess.
if (cached.configSignature !== undefined) {
const currentSignature = await readLocalGitConfigSignature(context)
if (currentSignature !== cached.configSignature) {
ownerRepoCache.delete(cacheKey)
@@ -203,9 +215,14 @@ async function resolveOwnerRepoForRemote(
// Why: PR mutations need the effective host behind an SSH alias.
const classification = await classifyGitHubOwnerRepoFromRemoteUrl(remoteUrl, context)
if (classification.kind === 'github') {
// Why store the signature: without it this entry can only expire on the
// clock, which put a `git remote get-url` (plus its ssh-alias probe) on
// every PR refresh cycle — the second most frequent Git subprocess in a
// Windows field trace, on a host spawning Git at ~250-800ms a call.
ownerRepoCache.set(cacheKey, {
value: classification.ownerRepo,
expiresAt: now + getOwnerRepoCacheTtl(classification.ownerRepo, configSignature)
expiresAt: now + getOwnerRepoCacheTtl(classification.ownerRepo, configSignature),
...(configSignature ? { configSignature } : {})
})
pruneOwnerRepoCache(now)
return classification.ownerRepo