fix(relay): bounded recursion in sendTelegram on 429 rate limit#3338
fix(relay): bounded recursion in sendTelegram on 429 rate limit#3338fuleinist wants to merge 3 commits into
Conversation
Replicate legacy NEG_TTL=30000 behaviour in list-military-flights fetchStaleFallback. After a failed live fetch, do not immediately re-read the stale Redis key — that just wastes an Upstash call if OpenSky/the relay is still down. Suppress stale-read attempts for 30 s after the last failed live fetch attempt. Fixes koala73#3277
Add _retryCount parameter (default 0) to sendTelegram and guard against unbounded recursion when Telegram returns sustained 429 responses. - Bail with warn log if _retryCount >= 1 - Pass _retryCount + 1 on recursive call - Fixes koala73#3060
|
@fuleinist is attempting to deploy a commit to the World Monitor Team on Vercel. A member of the Team first needs to authorize it. |
Greptile SummaryThis PR makes two targeted fixes: (1) bounds the previously unbounded recursion in Confidence Score: 5/5Both fixes are correct and minimal; no P0/P1 issues found — safe to merge. The No files require special attention. Important Files Changed
Sequence DiagramsequenceDiagram
participant Caller
participant sendTelegram
participant TelegramAPI
Caller->>sendTelegram: sendTelegram(userId, chatId, text, _retryCount=0)
sendTelegram->>TelegramAPI: POST /sendMessage
TelegramAPI-->>sendTelegram: 429 Too Many Requests
alt _retryCount >= 1
sendTelegram-->>Caller: false (bail — retry limit reached)
else _retryCount == 0
sendTelegram->>sendTelegram: await retry_after delay
sendTelegram->>sendTelegram: sendTelegram(userId, chatId, text, _retryCount=1)
sendTelegram->>TelegramAPI: POST /sendMessage
alt 429 again
sendTelegram-->>Caller: false (bail — _retryCount >= 1)
else 200 OK
sendTelegram-->>Caller: true
end
end
Reviews (2): Last reviewed commit: "fix(military): move lastStaleAttempt ass..." | Re-trigger Greptile |
| lastStaleAttempt = now; | ||
| const staleFlights = await fetchStaleFallback(); | ||
| if (staleFlights && staleFlights.length > 0) { | ||
| return { flights: filterFlightsToBounds(staleFlights, requestBounds), clusters: [], pagination: undefined }; |
There was a problem hiding this comment.
Negative-cache guard fires even when stale data is available
lastStaleAttempt is set unconditionally before calling fetchStaleFallback(). This means the first failed-live request per 30-second window gets stale data, but every subsequent failed request within that window hits the guard at line 276–279 and returns an empty list — even though the stale Redis key is present and unchanged. The goal of a negative-cache guard is to suppress lookups that returned nothing; it should only be armed when the stale fetch came back empty or null.
To fix, move lastStaleAttempt = now to after the empty-stale check:
const staleFlights = await fetchStaleFallback();
if (staleFlights && staleFlights.length > 0) {
return { flights: filterFlightsToBounds(staleFlights, requestBounds), clusters: [], pagination: undefined };
}
lastStaleAttempt = now; // only negative-cache when stale came back empty
markNoCacheResponse(ctx.request);
return { flights: [], clusters: [], pagination: undefined };
There was a problem hiding this comment.
✅ Fixed in 914e156f.
The negative-cache guard is now armed only after fetchStaleFallback() returns empty — i.e., when we actually confirmed no stale data was available, not just after attempting the read.
lastStaleAttempt = now moved to after the stale-empty check, exactly as suggested. This ensures that if stale data exists and hasn't changed, subsequent requests within the NEG_TTL_MS window will still serve it on the next stale-read cycle, rather than being short-circuited by the guard before even attempting the fallback.
Only arm the negative-cache guard when stale data was actually absent, not when we merely attempted a stale read. Fixes comment: koala73#3338 (review)
PR Feedback Addressed ✅Reviewed all comments from @greptile-apps[bot]. Changes Made
Files Changed
Verification
Fixes the issue where subsequent failed-live requests within the NEG_TTL_MS window were returning empty even though stale data was present and unchanged. Now the guard only short-circuits after an actual confirmed absence of stale data. Ready for re-review. cc @greptile-apps[bot] |
Bug
Fixes #3060
Add
_retryCountparameter (default 0) tosendTelegramand guard against unbounded recursion when Telegram returns sustained 429 responses.Changes
_retryCountparameter (default 0) added tosendTelegramsignature_retryCount >= 1_retryCount + 1on recursive callVerification
sendTelegramsignature — confirm it has a_retryCountparameter defaulting to 0_retryCount + 1_retryCount >= 1