Årsvis Betala årsvis och få 2 månader gratis på alla betalplaner. Se planerna
Logga in Kom igång gratis

Användningssidan visade för mycket, och inga pengar rörde sig

Vi börjar med den del som är lättast att tappa bort medan man läser resten: inga pengar togs. Ingen plånbok debiterades två gånger, inget kort belastades, och ingen prenumerationskvot användes till arbete som aldrig ägde…

Vi börjar med den del som är lättast att tappa bort medan man läser resten: inga pengar togs. Ingen plånbok debiterades två gånger, inget kort belastades, och ingen prenumerationskvot användes till arbete som aldrig ägde rum.

Det som var trasigt var en siffra på en skärm. På vissa konton visade användningsuppdelningen på din egen kontosida för mycket — på det värsta vi mätte 2,4 gånger den huvudbok den ska sammanfatta. Huvudboken var korrekt hela tiden. Detsamma gällde månadstaken, som läses från ett helt annat ställe. Det var ett visningsfel, det är åtgärdat, och här är orsaken.

En nyckel som letade efter något ingen hade skrivit

Arbete som uppstår på grund av något du gjorde — uppdatera en daglig användningssammanställning, kreditera en rekommendation, sprida en avisering — sker inte inuti din begäran. Begäran skriver ett meddelande, och en bakgrundskonsument plockar upp det ett ögonblick senare; det är just detta som hindrar en långsam sidoeffekt från att göra en snabb sida långsam.

Faran med det upplägget är att göra samma arbete två gånger, eftersom en mäklare gladeligen levererar samma meddelande igen efter en hicka. Försvaret är en inkorg: före bearbetning gör en konsument anspråk på meddelandet genom att skriva en rad som bär meddelandets nyckel, och ett unikt index gör ett andra anspråk omöjligt.

Vårt gjorde anspråk på ett par — den hyresgäst meddelandet tillhörde, plus meddelandenyckeln — och slog upp det paret mot det hyresgäst-id som meddelandekuvertet bär, vilket är ifyllt.

Anspråksraderna bar inget hyresgäst-id alls. Varenda en var tom, och hade varit det från början. Entitetens egen dokumentation påstod, med just de orden, att ramverket stämplar det vid insättning. Det gjorde det aldrig. Mätt mot produktion samma dag vi hittade det: alla 3 344 inkorgsrader tomma, medan 1 174 av 1 451 rader på den producerande sidan bar en verklig hyresgäst — vilket är precis därför ingen misstänkte den läsande sidan.

Uppslagningen bad alltså om (hyresgäst, nyckel), den lagrade raden var (ingenting, nyckel), och de kunde aldrig matcha.

Inget gick fel, och det är därför det pågick i veckor

En uppslagning som aldrig kan matcha låter som något som borde kasta ett fel vid första försöket. Den gjorde tvärtom.

Anspråket beslutade att meddelandet var nytt. Insättningen träffade sedan det unika indexet och avvisades som dubblett — helt korrekt, eftersom raden redan fanns där. En reservgren fångade avvisningen och läste den välvilligt: en annan leverans måste ha gjort anspråk på den här, inget att göra här. Kuvertet blev kvar i tillståndet "ännu att bearbeta", och eftersom det ännu var att bearbeta plockade nästa leverans upp det och gjorde arbetet igen.

Varje konsument bearbetade sin egen eftersläpning på nytt ungefär var fyrtiofemte sekund, i all oändlighet. Tjugosex gjorde det. En produktionsrad blev klar 333 timmar efter att den kom in — och hade blivit klar om och om igen under större delen av den tiden.

Vad det faktiskt förstörde

Av de tjugosex konsumenterna ackumulerar fyra i stället för att skriva över. De fyra är de faktureringsprojektioner som användningssidan läser, och det är där saken kom upp till ytan.

De hade ett uttryckligt skydd mot precis detta, skrivet efter en incident i augusti där en enda händelse tillämpades nio gånger på en mätare. Skyddet markerar en rad som lyckad innan den bearbetas, så att en omleverans hittar markeringen och stannar. Markeringen skrevs korrekt varje gång. Nästa anspråk letade sedan efter den med samma trasiga nyckel och hittade den inte. Garantin hade varit tom sedan den dag den levererades.

Vad detta inte rörde är värt att räkna upp exakt, eftersom "faktureringsprojektion" låter alarmerande och fakta inte är det:

  • Huvudboken var korrekt. Varje AI-anrop skriver exakt en faktureringspost med sin egen prisögonblicksbild, och inget på den här vägen skriver dem.
  • Ingen plånbok rörde sig. Saldon kommer från huvudboken, aldrig från en sammanställning.
  • Inget tak rörde sig. Budgetvakten läser en separat räknare, och den är den enda sanningskällan för vad du har spenderat den här månaden. Ingen stängdes av för tidigt på grund av en uppblåst siffra, och ingen släpptes igenom som inte borde ha gjort det.

Det enda som läser den påverkade sammanställningen är användningshistoriken på din egen kontosida — din totalsumma och fördelningen av vad den gick till. Det är hela påverkansradien, och det den gjorde var att visa för mycket.

Halvan ingen tittade på

Samma trasiga uppslagning satt på ett andra ställe: vägen som körs när ett meddelande misslyckas. Där hittade den aldrig raden den skulle uppdatera, och direkt under satt en gren med kommentaren "onåbar i praktiken" — som returnerade "detta fel är slutgiltigt" vid varje misslyckande.

Så omförsöksräknaren gick aldrig framåt och inget förgiftat meddelande nådde någonsin kön för olevererbara meddelanden. Ett helt lager av felhantering var avstängt, bakom en kommentar som talade om för alla som läste den att det inte fanns något att kontrollera här.

Rättningen

Båda uppslagningarna nycklar nu på meddelandenyckeln inom konsumentgruppen, vilket är vad det unika indexet ändå framtvingar. Meddelandenycklar härleds från id:t för det som skapade dem, så de kan per konstruktion inte kollidera mellan hyresgäster.

Dokumentationen som påstod stämplingen rättades i stället för att raderas. Den meningen var själva fällan, och att radera den hade inte lämnat något kvar som säger att någon till slut kontrollerade.

Nio tester låser beteendet. Sex av dem faller mot den gamla koden, vilket vi bekräftade genom att sätta tillbaka den gamla koden.

Städningen efteråt

De uppblåsta raderna reparerar sig själva. En worker bygger om dagssammanställningarna från huvudboken varje timme, över ett tvådagarsfönster. Den hade kört hela tiden och förlorat: en gång i timmen mot en konsument som tillämpar om var fyrtiofemte sekund är ingen rättvis kapplöpning.

Med konsumenten som inte längre kör om vinner den. De två dagar som fortfarande låg inom fönstret byggdes om från huvudboken så snart rättningen var i produktion. Två tidigare dagar hade redan fallit utanför, och det som återstår på dem är ett konto av vårt eget plus en försumbar differens någon annanstans — så vi lät dem vara i stället för att bredda ett fönster i produktion för att jaga det. Det kändes bättre än att antyda att sopningen var fullständig.

Vad vi tog med oss

En dedupliceringsnyckel måste spegla vad indexet faktiskt framtvingar, inte vad koden tror skrevs. De två halvorna av denna matades från olika fält, och ingen av dem hade någonsin mätts mot den andra. Nu är båda det, och testet som bevisar det blir rött mot versionen som var fel.

Dela LinkedIn X E-post
Testa på ditt eget arbeteVarje svar visar vad det kostade. Börja med gratisplanen. Kom igång gratis
Få produktnyheter, inte brus Nya modeller, funktioner och höjdpunkter ur changeloggen – ett kort mejl när något faktiskt lanseras.
Genom att prenumerera godkänner du att få e-post från ToRun om produktuppdateringar. Du kan avsluta prenumerationen när som helst. Integritetspolicy