fix: recover from FR24 live-feed backends that return no flights - #111
Merged
Conversation
JeanExtreme002
force-pushed
the
fix/live-feed-empty-backend
branch
from
July 29, 2026 02:28
18394bf to
b05a5ef
Compare
FR24 balances zones/fcgi/feed.js across several backends and at least one of them answers HTTP 200 with a well-formed envelope -- full_count set, stats.total populated -- but no flight entries and stats.visible zeroed. Roughly half the requests landed on it, and its full_count stayed frozen at the same value for over 20 minutes while a healthy backend kept ticking up. Two things turned that into a deterministic failure. The AWSALB cookie pins the session to whichever backend it first hit, so a client that landed on the degraded one returned an empty flight list for the rest of its lifetime -- which is why every flight test failed together while the airport and airline tests passed. And the degraded payload is structurally identical to a legitimately empty result (a bounds box over open ocean), so no field in the response can tell the two apart. getFlights()/get_flights() now treat zero entries with full_count > 0 as suspect: drop the stickiness cookies so the balancer re-rolls the backend, then re-request, up to four times. A successful response re-pins the session to the healthy backend, so the cost is paid at most once per client. A genuinely empty query still returns an empty list. Shedding stickiness needs a targeted cookie delete: clearCookies() would also drop _frPl, the login cookie, which shares the same jar. Hence the new deleteCookie/delete_cookie on the client. Covered by new offline tests in both SDKs (retry-then-succeed, bounded give-up, no retry on full_count 0, no retry when healthy, filters preserved across retries, login cookie survives), so the PR gate keeps guarding this while FR24 is healthy.
JeanExtreme002
force-pushed
the
fix/live-feed-empty-backend
branch
from
July 29, 2026 13:26
b05a5ef to
4b2c349
Compare
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.
Problem
The scheduled runs are red in both SDKs, always on the same tests: everything that goes through
getFlights()/get_flights()comes back with 0 flights (assert 0 >= 100,IndexError,expected +0 to be above 29), while the airport and airline tests pass.Example: Node run 29882853857, and Python run 29884728134.
Root cause
Not our bug — FR24 is serving a broken backend.
data-cloud.flightradar24.com/zones/fcgi/feed.jssits behind an AWS load balancer with at least two targets, visible in thex-fr24-fcgiresponse header:frontend-feed-002full_countticking up each callfrontend-feed-001full_countfrozen at22684for 20+ minutesThe degraded one answers HTTP 200 with a perfectly well-formed envelope —
full_countset,stats.totalpopulated — but no flight rows andstats.visibleall zeros. Roughly half of all requests landed on it.Two things turned a 50/50 coin flip into a deterministic failure:
AWSALBcookie pins the session to a backend (confirmed 8/8 in both directions). SinceSessionpersists cookies, once a test process landed on the broken target, every later call returned[]— which is exactly why all four flight tests failed together.Fix
getFlights()/get_flights()now treat "zero entries whilefull_count > 0" as suspect: drop theAWSALB/AWSALBCORScookies so the balancer re-rolls the target, then re-request, up to 4 retries. A successful response re-pins the session to the healthy backend, so the gamble is paid at most once per client. A genuinely empty query still returns[], just after spending the retry budget.Shedding stickiness needs a targeted delete —
clearCookies()would also drop_frPl, the login cookie, which shares the same jar. Hence the newdeleteCookie/delete_cookieon the client (typed inindex.d.ts).Tests
New offline suites in both SDKs (
testFeedRetry.js,test_feed_retry.py), 7 cases each, no network, using a client double: retry-then-succeed, bounded give-up, no retry onfull_count: 0, no retry when the first response is healthy, caller filters preserved across retries, and the login cookie surviving a stickiness drop. They run in the PR gate, so they keep guarding this while FR24 is healthy.Verification
tsdclean, 40 offline, integration 46/46 in 6 of 7 runsOut of scope
RetryPolicydoes not treat HTTP 429 as transient, and it defaults to off (maxAttempts=1). A real gap, but not what broke these runs — left for a separate change.429onclickhandler, and the airline-logo test) came from firing hundreds of requests within a few minutes, not from CI conditions.