Blog ·
Twee regels met een dode link ertussen
Een crawl van 1776 pagina's vond precies 18 kapotte URL's. Beide regels die ze maakten waren juist; niemand had getoetst wat er in de naad gebeurt.
Door Provibr
We hebben de productiesite voor het eerst in tijden goed gecrawld: elke interne link gevolgd, elk opgegeven taalalternatief gecontroleerd, elk blok gestructureerde gegevens gevalideerd, elke afbeelding op alternatieve tekst gecontroleerd.
1776 pagina's, 1750 sitemapregels, en precies één defect. Nul wezen, nul redirectketens, nul fouten in taalalternatieven over 17218 declaraties, nul ongeldige blokken gestructureerde gegevens over 1642, nul afbeeldingen zonder alternatieve tekst over 15463, en 920 deelafbeeldingen die allemaal 200 antwoordden.
Het ene defect waren 18 adressen die 404 gaven: de documentatiepagina's van twee billingpanelen, in alle negen talen. Elk van die 18 had precies één interne link die ernaar wees, vanaf de integratiepagina voor hetzelfde product in dezelfde taal.
Beide helften daarvan zijn met opzet. Dat is wat het de moeite van het opschrijven waard maakt.
De twee regels
Sommige van onze integraties zitten achter een rolloutschakelaar. Staat de schakelaar uit, dan verdwijnt de provider uit de catalogus, uit de sitemap, uit de tellers en uit de typekeuze in het paneel, allemaal afgeleid uit één tabel zodat er geen tweede lijst is om te vergeten.
Twee ervan zijn niet helemaal gewoon. Voor FOSSBilling en Paymenter is er een module die je in hún paneel installeert, en de pagina op /integrations/fossbilling beschrijft die module. Het is geen pagina over een koppeling die wij aanbieden; het is een pagina over iets wat je vandaag kunt downloaden. Er is dus een regel die die twee integratiepagina's laat staan als de provider achter de schakelaar verborgen is, en hij draagt zijn reden mee in de bron.
De documentatiepagina is het omgekeerde geval. /docs/fossbilling beschrijft de koppeling, en dat is precies wat de schakelaar uitzet, dus hij verdwijnt met de provider mee.
Allebei die regels kloppen. Eén slug, twee oppervlakken, twee antwoorden, en de code heeft twee functies in plaats van één die de helft van de tijd fout zou zijn.
Wat niemand gecontroleerd had is wat er tussen die twee gebeurt. De overlevende pagina droeg de inhoudelijke link naar de verdwenen pagina.
De regel stond al opgeschreven
De functie die die link maakt zoekt een documentatiepad bij een integratieslug. Haar eigen commentaarblok zei, voordat dit allemaal gebeurde, dat een link naar een handleiding die niet bestaat geen inhoudelijke link is maar een dode.
De regel was er. Hij werd tegen de verkeerde lijst gemeten: de verzameling documentatiepagina's die in de bron bestaan, in plaats van de verzameling die in deze build antwoordt. Die twee zijn bijna altijd dezelfde verzameling, en de dag waarop ze verschillen is de dag waarop er iets verborgen is.
De reparatie is één regel. Dat is niet het interessante deel; het interessante deel is dat een juiste regel, uitgeschreven op de plek waar hij hoort, geen controle is. Proza in een commentaar beschrijft een bedoeling. Alleen iets wat draait kan je eraan houden.
Een derde geval dat geen enkele crawl had kunnen vinden
We schreven een bewaking in plaats van alleen de regel te repareren: voor elke integratieslug moet het gevonden documentatiepad er een zijn dat deze build werkelijk serveert. Hij is eerst rood bewezen, en hij meldde de twee pagina's die de crawl gevonden had.
Hij meldde er ook een derde: onze backupserver-integratie, die achter een andere schakelaar zit. Haar documentatiepagina is verborgen, en de link ernaartoe was op precies dezelfde manier gebouwd.
De reden dat geen enkele crawler die ooit zal vinden, is dat haar integratiepagina óók verborgen is. De dode link woonde op een pagina die zelf 404 geeft, dus is er van buitenaf geen pad naar het ding dat fout is. Hij zou zijn bovengekomen op de dag dat iemand die schakelaar aanzette en een pagina met een kapotte link erop uitleverde, en die twee gebeurtenissen zouden weken uit elkaar liggen.
Een crawler kan alleen defecten vinden op bereikbare pagina's. Dat klinkt vanzelfsprekend zodra het opgeschreven staat en het is makkelijk te vergeten als een crawl schoon terugkomt, want een schone crawl voelt als een uitspraak over de code in plaats van over de pagina's die toevallig zichtbaar waren.
De bewaking heeft nog één test die niets anders doet dan de eerste eerlijk houden: hij eist dat meer dan tien slugs werkelijk naar een documentatiepagina leiden. Zonder die test zou een wijziging die de resolver voor alles niets laat teruggeven geen dode links opleveren en helemaal geen inhoudelijke links, en die twee lezen identiek in een groene testrun.
De andere helft: een zoekmachine vertellen dat er iets veranderd is
Dezelfde ronde voegde een aanmeldkanaal toe, en dat is een klein ding met één verrassing erin.
Het protocol is één POST die een aantal zoekmachines vertelt dat een adres gewijzigd is. Het eigendom van de host bewijs je door een sleutel als tekstbestand in de wortel te serveren. Onze sleutel komt uit de omgeving, en als hij ontbreekt doet het geheel niets en zegt het dat één keer. Dat is de normale toestand in ontwikkeling en in elke test.
Twee details zijn het herhalen waard, want het zijn allebei vallen.
Het sleutelbestand wordt via een rewrite geserveerd, want een dynamische route kan niet in de wortel staan naast het taalsegment. Een rewrite die op alles punt txt in de wortel matcht zou ook het robots-bestand opslokken. Twee dingen houden dat tegen: de rewrite draait in de fase die alleen verzoeken ziet waar geen echt bestand op matchte, en het sleutelpatroon eist minstens acht tekens, terwijl robots er zes heeft en llms vier. Die ondergrens is geen netheid; het is het tweede slot.
En de aanmelding hangt aan de functie die al weet dat publieke inhoud gewijzigd is, en niet aan de deploy. Een release die alleen een paneelscherm raakt zou anders elke keer 1750 adressen als gewijzigd aankondigen, en dat is een goede manier om genegeerd te worden. Verandert de prijstabel, dan worden de twee routes die prijzen renderen in negen talen aangemeld, en dat zijn 18 adressen.
Wat eruitzag als een verkeerde instelling
De eerste echte aanmelding na de deploy, met de productiesleutel op zijn plek, gaf 403.
Het sleutelbestand gaf overal waar we het probeerden 200, ook met een crawler-user-agent. Elk ingrediënt klopte. De natuurlijke volgende stap is naar de edge-configuratie gaan kijken, of naar de rewrite, of naar de fasevolgorde, en daar gaat een uur in zitten.
Wat we in plaats daarvan deden was twee kleinere dingen proberen. Eén adres aanmelden gaf meteen 200. Dezelfde bulkaanmelding gaf een minuut later ook 200, op allebei de endpoints.
De 403 was dus een eerste-contacteffect aan hun kant en geen defect aan de onze. Het sleutelbestand was op het moment dat het eerste bulkverzoek binnenkwam nog niet opgehaald en gecachet door de ontvangende dienst.
We hebben dat opgeschreven waar het runbook woont, want de storing is perfect ontworpen om iemand op jacht te sturen: de statuscode zegt verboden, en dat is een uitspraak over toestemming, terwijl alles rond toestemming klopte. Voordat je een autorisatiefout op een eerste verzoek gaat onderzoeken, doe je hetzelfde verzoek nog een keer. Het kost niets en het is de goedkoopste hypothese in de lijst.
Er hoort een verwante notitie bij voor wie die sleutel ooit roteert: het bestand wordt met een uur cache geserveerd, dus een rotatie vraagt om een purge of om een uur geduld, en in dat venster betekent dezelfde 403 iets compleet anders.
Wat we zouden opschrijven
- Twee juiste regels kunnen een defect opleveren in de naad ertussen. Geen van beide eigenaren zit fout en geen van beiden kijkt.
- Dezelfde identificator kan twee oppervlakken met twee juiste antwoorden hebben. Twee functies, niet één.
- Een regel in een commentaar is geen controle. De onze stond uitgeschreven en werd tegen de verkeerde lijst gemeten.
- Wat bestaat en wat antwoordt zijn verschillende verzamelingen, en ze lopen precies uiteen op het moment dat er iets verborgen is.
- Een crawler vindt alleen defecten op bereikbare pagina's. De onze kon het derde geval helemaal niet zien.
- Een bewaking vindt het geval dat nog niet uitgeleverd is. Dat is de hele reden om er een te schrijven in plaats van de regel te repareren.
- Geef elke bewaking een test die bewijst dat ze kijkt. Geen dode links en helemaal geen links lezen hetzelfde.
- Een ondergrens in een patroon kan een veiligheidsgrens zijn. Acht tekens is wat een rewrite van het robots-bestand af houdt.
- Kondig inhoudswijzigingen aan vanuit het ding dat weet dat de inhoud gewijzigd is, nooit vanuit de deploy.
- Probeer opnieuw voordat je een mislukt eerste verzoek diagnosticeert. Een verboden dat een minuut later een succes is, ging nooit over toestemming.
Voor de duidelijkheid over wat dit is: de crawl besloeg 1776 pagina's tegen productie en 1750 sitemapregels met 913 wijzigingsdatums waarvan er geen enkele in de toekomst lag, de reparatie is één regel bewaakt door drie tests die eerst rood bewezen zijn, het aanmeldpad is van begin tot eind uitgeoefend tegen een nagebootst endpoint inclusief vijf faalpaden, en de veeg over een standalone productiebuild eindigde op 96 groen. Onbewezen: op het moment dat de reparatie geschreven werd was hij groen op een lokale productiebuild en nog niet op productie bevestigd, en twee routefamilies in de crawl leverden helemaal geen pagina's op omdat hun registers leeg zijn.
Uit het platformwerk aan Provibr. Wat een facturatiemigratie wel en niet kan meenemen staat in vijftien dingen die niet meekunnen, een deploy waarvan de schemastap nooit gedraaid heeft staat in de migratie die nooit gedraaid heeft, en nog een controle die groen was omdat hij er nooit aankwam staat in groen omdat hij er niet kon komen.