@@ -64,6 +64,12 @@ export async function triggerSecurityInsightsCheckForRepos(
6464
6565 async function processRepo ( repo : ( typeof repos ) [ 0 ] ) : Promise < void > {
6666 let attempts = 0
67+ // Distinguishes attempt exhaustion caused by transient rate-limits from exhaustion caused
68+ // by per-repo access failures. With MAX_TOKEN_ATTEMPTS == poolSize, a pool where every
69+ // token 403s in this run exits the loop via `attempts >= MAX_TOKEN_ATTEMPTS` rather than
70+ // via `!tokenInfo`, so requeue decisions have to be made here too — otherwise a rate-limit
71+ // wave would falsely fail the repo for the rest of the continueAsNew chain.
72+ let sawRateLimit = false
6773 while ( attempts < MAX_TOKEN_ATTEMPTS ) {
6874 const tokenInfo = getNextToken ( tokenInfos , currentTimeMs )
6975 if ( ! tokenInfo ) {
@@ -115,6 +121,7 @@ export async function triggerSecurityInsightsCheckForRepos(
115121 // batch startTime when details are missing so we still record something.
116122 tokenInfo . rateLimitedAt =
117123 extractFailureTimestamp ( appFailure ) ?? new Date ( currentTimeMs ) . toISOString ( )
124+ sawRateLimit = true
118125 attempts ++
119126 continue // retry with a different token
120127 } else if ( appFailure ?. type === 'TokenAuthError' ) {
@@ -145,8 +152,19 @@ export async function triggerSecurityInsightsCheckForRepos(
145152 }
146153
147154 if ( attempts >= MAX_TOKEN_ATTEMPTS ) {
148- console . error ( `Exhausted token attempts for repo ${ repo . repoUrl } , skipping` )
149- failedRepoUrls . push ( repo . repoUrl )
155+ // If any attempt hit a rate-limit and not every token is permanently invalid, the
156+ // exhaustion is transient — requeue so the repo can be retried once cooldowns expire
157+ // (via the outer loop's `refreshExpiredRateLimits`) or on a later scheduled run.
158+ const allPermanentlyInvalid = tokenInfos . every ( ( t ) => t . isInvalid )
159+ if ( sawRateLimit && ! allPermanentlyInvalid ) {
160+ console . warn (
161+ `Exhausted token attempts (rate-limit) for repo ${ repo . repoUrl } , requeuing` ,
162+ )
163+ queue . unshift ( repo )
164+ } else {
165+ console . error ( `Exhausted token attempts for repo ${ repo . repoUrl } , skipping` )
166+ failedRepoUrls . push ( repo . repoUrl )
167+ }
150168 }
151169 }
152170
0 commit comments