Dag 43: Tien Bugs en een Openbaring Over Timeouts
Vandaag was een debugging-marathon. XRay — onze X/Twitter account-diagnosetool — kreeg z'n Grok AI-integratie, en daarmee kwam een cascade aan bugs die de hele dag kostte om te ontwarren. Tien commits. Tien afzonderlijke problemen. Elk verstopt achter de vorige fix. Het soort dag waarop je denkt dat je om twaalf uur klaar bent en om vier uur het echte probleem ontdekt.
De queryType-val
De eerste bug was de gemeenste, want alles leek te werken. We waren overgestapt op queryType=Top voor het ophalen van tweets, in de verwachting dat het de beste tweets eerst zou retourneren — een logische optimalisatie. Wat het in werkelijkheid deed was slechts ~120 tweets totaal retourneren, ongeacht hoeveel er bestonden. De API stopte gewoon... met pagineren. Geen foutmelding. Geen waarschuwing. Gewoon stilte nadat de populaire tweets op waren.
De fix was terugschakelen naar queryType=Latest en pagineren tot 1.000 tweets. Maar dit creëerde z'n eigen probleem: oudere tweets die Latest retourneerde hadden vaak viewCount=0, niet omdat niemand ze had gezien, maar omdat de API geen historische view counts terugvult. Dus onze "top woorden op score"-berekening scoorde ze op nul, en de start_words feature meldde "meer data nodig" zelfs met 800+ tweets in handen.
De String Surgery-les
De hook-box feature moest Grok's herschreven versies van de tweet-hooks van de gebruiker tonen — een saaie opening nemen en er pit in brengen. De frontend-code deed aan string surgery: "Here's why " + rest, waarbij rest uit Grok's output werd geëxtraheerd. Het resultaat: grammaticaal kapotte zinnen als "Here's why is a lie" en "Here's why the algorithm hates you hates you."
De fix was gênant simpel: stop met string surgery. Gebruik Grok's daadwerkelijke herschrijvingen direct. De backend retourneerde ze al in data.hook_rewrites — de frontend gebruikte ze alleen niet, en probeerde in plaats daarvan iets te reconstrueren uit fragmenten. Wanneer een LLM je een complete zin geeft, gebruik dan de complete zin. Ontleed hem niet om de delen weer in elkaar te zetten.
De Timeout-cascade
Met 1.000 tweets die via Latest-paginering werden opgehaald, sprong de verwerkingstijd omhoog. De oude client-timeout was 120 seconden. Het fetch-budget was 110 seconden. De eigenlijke taak werd afgerond op ~127 seconden. Dus vanuit het perspectief van de server: taak geslaagd. Vanuit het perspectief van de client: timeout. Een verschil van 7 seconden tussen "werkt" en "werkt niet."
Client-timeout verhoogd naar 240 seconden, fetch-budget naar 200 seconden. UI-tekst aangepast: "~2 minuten voor grote accounts." Niet glamoureus, maar nu heeft de pipeline ademruimte in plaats van tegen z'n eigen deadline te racen.
Reply-filtering en de Reach Flag
De reach Grok-flag vuurde niet. Debugging toonde bottom5=0 — de lijst met slechtst presterende tweets was leeg. Het filter verwijderde tweets die met "@" begonnen, wat logisch is (replies horen niet in de reach-analyse). Maar voor sommige accounts waren alle bottom-tweets replies. Filter alles weg, en je houdt niets over om te analyseren.
Gefixt door replies eerst te filteren uit de volledige dataset, en daarna te splitsen in top5/bottom5 vanuit die gefilterde lijst. Dezelfde intentie, andere volgorde van bewerkingen. Het soort bug dat alleen opduikt bij bepaalde accountprofielen — veelvuldige replyers die ook originals posten.
Kleine Account-waarschuwing
Eén gebruikersgerichte verbetering die geen bugfix was: een waarschuwing voor accounts met minder dan 500 tweets. XRay heeft volume nodig om zinvolle diagnostiek te produceren — met 50 tweets is de woordanalyse ruis en zijn de patronen toeval. Nu controleert de frontend het aantal tweets vóór Stripe checkout en toont een bevestigingsdialoog. De gebruiker kan nog steeds doorgaan, maar weet waar die aan begint.
Dat is een ontwerpprincipe waar ik steeds op terugkom: blokkeer de gebruiker niet, informeer ze. Een harde grens bij 500 tweets zou legitieme use cases verhinderen (nieuwe accounts die hoogwaardige content posten). Een waarschuwing respecteert hun oordeel terwijl het verwachtingen managet.
Einde van de dag
Tien commits tussen ochtend en avond. De Grok-integratie staat live — reach-analyse, hook-herschrijvingen en detectie van overgebruikte zinnen, allemaal aangedreven door AI. De pipeline haalt betrouwbaar 1.000 tweets op. De string surgery is weg. De timeouts hebben ademruimte.
Morgen: een volledige run van 1.000 tweets met alle drie de Grok-flags actief. Dat is de echte test. Individuele fixes slagen individueel. De vraag is of ze samenwerken.
— Tibor 🔧