Štíteksestavení18

Kam až to může narůst

Je poctivá otázka, než nástroji svěříš dvacet let psaní: v jakém bodě ho přestane být příjemné používat? Měřeno tady v srpnu, na archivu 6 639 příspěvků, byla upřímná odpověď pokrčení rameny: přidání jednoho příspěvku stálo celý archiv – osmačtyřicet sekund od stisknutí klávesy Enter do chvíle, kdy web běžel – protože každá stránka, která se o příspěvku byť jen zmiňovala, se musela vyrobit znovu, ať se změnila, nebo ne.

To už upřímná odpověď není. Od 1.6 si sestavení vede záznam o tom, co do každé stránky vstoupilo, a znovu vyrábí jen ty, jejichž záznam už nesedí. Archiv pod tím je tentýž, na kterém se to v srpnu měřilo, o sedm příspěvků těžší: teď 6 646, a engine o tři vydání dál, na 1.9.

Na co čekáš dnes

Publikace příspěvku s dnešním datem na tomtéž archivu: šestnáct sekund sestavení, dvě nahrávání – kde bylo osmačtyřicet. Sestavení už nesahá na stránky, které to nepotřebovaly, takže velikost archivu přestala být tím, z čeho se čekání skládalo.

Kde se velikost stále ukazuje

Číst dál

Zámek, který nečeká

Dvakrát za hodinu na dost velkém webu sáhnou dvě úlohy cronu do téže složky téměř ve stejnou chvíli: naplánované publikování, které sestaví a nasadí příspěvek, jehož čas právě nastal, a obnova postranního panelu, která přepisuje několik týchž výstupních souborů čerstvými čísly. Většina tiků se mine o minuty. Na archivu tak velkém, že sestavení s úplným nasazením trvá déle než interval mezi nimi, se některé neminou.

Nasazení, které prochází strom, zatímco ho jiný běh ještě přepisuje, může vydat stránku zapsanou napůl. Běh, který maže osiřelé soubory, může jako osiřelou smazat stránku, kterou druhý běh o sekundu dřív publikoval. Ani jedno selhání se neohlásí – web je prostě potichu špatně.

Zámek a co odmítá dělat

Mezi těmi dvěma běhy stojí jediný soubor, .blog-sh.lock v kořeni projektu – a rozhoduje se způsobem, který vypadá špatně, dokud neuvidíš alternativu. Běh, který najde zámek obsazený, na něj nečeká.

Číst dál

Jeden řádek barvy

Čtenář změnil jednu barvu okraje v site.css, spustil nové sestavení a čekal, zatímco sestavení vytvořilo, bajt po bajtu, každou stránku, která už existovala. Zeptal se proč. Odpovědí bylo jedno slovo v jednom seznamu a 1.7 ho odstraňuje.

Co si sestavení zapisuje

Od 1.6 si sestavení vede záznam o tom, co vstoupilo do každé stránky, kterou zapsalo – příspěvek, příspěvky kolem něj, štítky, čísla, která stránka počítá. Při dalším sestavení se stránka, jejíž záznam se nezměnil, vůbec nevykresluje. Ne že by se vykreslila a pak shledala shodnou – nevykreslí se. Souhrn na konci říká, kolik stránek zůstalo netknutých; to je první číslo, na které se podívat, když je sestavení pomalé.

Záznam platí jen po dobu, kdy engine, který ho zapsal, je týž engine, a proto visí na otisku toho, z čeho se engine skládá – souborů v templates/, lib/, build/, locales/ a config/, hašovaných podle obsahu, ne podle času změny. Změň cokoli z toho a záznam se zahodí celý, protože cokoli z toho může změnit každou stránku.

Proč barva stála celý archiv

Číst dál

Všechno ostatní v 1.6

Pět příspěvků pokrylo to, o čem 1.6 je. Tenhle je zbytek, v pořadí, v jakém ho provozovatel potká.

Cesta ven z koše a z verzí

Obě úložiště měla cestu zpět – restore a výběr verze ve vlastnostech příspěvku – a žádnou cestu ven, takže obě léta rostla a nic neříkalo o kolik. empty trash a empty versions vypíšou, co se chystají odstranit, v položkách a v megabajtech, a než cokoli odejde, chtějí ten počet opsat. empty versions nechá každému příspěvku jeho nejnovější verzi, protože verze existují proto, aby odpověděly na „vrať mi, co jsem právě přepsal". doctor teď koš s příspěvky zaznamená, jako poznámku, ne jako závadu: na instalaci, kolem které tento engine vznikl, byl jediný způsob, jak ho vidět, du na serveru.

Fotografie uložená jednou

public.nosync/ dřív držel druhou kopii každého obrázku. Teď drží pevný odkaz, takže obrázky zabírají polovinu toho, co dřív – 1,8 GB na instalaci tohoto projektu. V záloze to neušetří nic, a to bylo změřeno, ne předpokládáno: 200 souborů pod dvěma jmény, 101 MB na disku, 201 MB v záloze. Nic k udělání; první sestavení po aktualizaci odkazy vytvoří.

Číst dál

Příspěvek předaný jako soubor

Až do 1.6 přicházel příspěvek od člověka u terminálu. Průvodce položil své otázky, otevřel editor, na konci se zeptal, co dál. Nic jiného ho napsat neumělo: ani skript, ani cron, ani telefon.

./blog.sh add post.md

dělá tutéž práci s markdownem předaným místo napsaným. Žádný editor, žádné otázky, žádný dialog na konci. Holé jméno souboru se hledá v incoming/, takže soubor může dorazit týmž nahráním jako fotografie, a jakmile je příspěvek zapsán, smaže se.

Kde by se průvodce ptal, tohle odmítá

Člověka se lze zeptat. Skriptu ne, takže z každé otázky je odmítnutí, které nic nezapíše: fotka, která se nedonahrála, prázdné tělo, soubor, který není text, druhé jméno souboru tam, kde se čekalo jedno. Alternativa – hádání – byla změřena na starém kódu, kde se značka pořadí bajtů před hlavičkou brala jako text těla: tři neviditelné bajty z editoru ve Windows a příspěvek dorazil bez titulku a bez štítků, pojmenovaný po slovech „title:" a „tags:", exit 0. 1.6 čte hlavičku skrz ně.

--json: jeden objekt, nic jiného

Číst dál

Čas mezi rozhodnutím a tím, než to web řekne

Publikace příspěvku dřív stála tolik, kolik měří archiv, ne kolik měří změna. Příspěvek datovaný dneškem změní tucet souborů. Sestavení vykreslilo každou stránku v archivu a každou přečetlo zpět z disku, aby to zjistilo.

Na archivu, kolem kterého tento engine vznikl – 6 639 příspěvků, na serveru, kde bydlí – to bylo 47 vteřin za nové sestavení, které nezměnilo nic, a 48 od stisku publikovat do chvíle, kdy byl příspěvek venku. V pořádku pro jeden příspěvek ráno. Méně v pořádku pro opravu překlepu v deseti z nich.

Co si sestavení teď pamatuje

1.6 si vede záznam o tom, co vstoupilo do každé stránky: příspěvek, šablona, lokalizace, konfigurace, engine sám. Při dalším sestavení vykreslí jen stránky, jejichž záznam už nesedí, a zbytek stojí jeden stat každá místo plného vykreslení a čtení zpět.

Týž archiv, měřený stejně: nové sestavení, které nemění nic, trvá sedminu toho, co dřív. Publikace příspěvku datovaného dneškem trvá asi dvě pětiny – 16 vteřin sestavení a 2 nahrání, kde bylo 48 – a sestavení to říká samo: Stránek beze změny, nepřestavěny: 10 160. Poměr je to, co cestuje; vteřiny jsou jednoho stroje.

Číst dál

Všechno ostatní v 1.5

Pět příspěvků pokrylo tvar tohoto vydání. Tady je zbytek, po odstavci na každou věc.

Číst dál

Uříznuto dřív, než se to zapíše

Karta ve výpisu bývala celý příspěvek. Engine do stránky vykreslil každý jeho blok a stylesheet výsledek ořízl na 500 pixelů.

Na skutečné titulní straně to znamenalo čtrnáct karet nesoucích mezi 794 a 2 616 pixely obsahu a ukazujících 500. Z 50 659 znaků stránky jich 49 312 sedělo uvnitř oříznutí. Třiatřicet ze 154 jejích zaostřitelných prvků šlo dosáhnout klávesnicí, zatímco byly na obrazovce neviditelné – odkazy, které vidící uživatel s myší neviděl a uživatel s klávesnicí nemohl přeskočit.

1.5 kartu uřízne dřív, než se zapíše. Stylesheet neskrývá nic.

Ta stránka šla z 89 268 bajtů HTML na 41 155. Její největší karta, 7 463 znaků, má teď 2 566. A „číst dál" se objeví přesně tehdy, když se něco nevešlo, místo aby sedělo pod kartou, která už ukazovala všechno, co měla.

Rozpočet je v pixelech, ne ve znacích

Číst dál

Dvě stránky, které si web sestavil sám ze sebe

Až dosud ti tento engine uměl ukázat deset příspěvků najednou a nic jiného. /page/128/ je na velkém archivu skutečná adresa a neřekne ti nic o tom, jestli jsi přistál v roce 2009 nebo 2014 – stránkování je ukotvené od nejstaršího příspěvku, takže se ti číslo pod nohama pohne pokaždé, když se něco publikuje. Jediný úplný seznam čehokoli žil v terminálu.

1.5 přidává dvě stránky, které archiv čtou, místo aby jím procházely.

/archive/ – tvar celku

Řádek na rok a vedle něj pás dvanácti měsíců. Měsíc je vystínovaný v jednom ze čtyř stupňů, ne jen rozsvícený nebo tmavý, protože „má příspěvky / nemá" není otázka, na kterou stojí za to odpovídat: na referenčním archivu drží měsíc kdekoli mezi jedním příspěvkem a sedmaosmdesáti, a kreslit je stejně by skrylo to jediné, k čemu mapa je. /archive/<rok>/ je jeden řádek na příspěvek, po měsících.

Dvě úrovně a víc ne. Třetí by byla nějakých 280 stránek jednotlivých měsíců – hodně sestavování na otázku, kterou nikdo nepoložil.

Číst dál

Druhá polovina check

./blog.sh check přečte celý archiv a řekne, co je špatně: média, o která si příspěvek říká a nemá je, odkazy na adresy, na kterých nic neodpovídá, dva příspěvky, které by se servírovaly na jedné adrese. Až do 1.3 tam to končilo – seznam nálezů a návratový kód, s opravou ponechanou tobě a textovému editoru.

--repair to projde s tebou

check --repair je druhá polovina kontroly: ke každému nálezu nabídne tu jednu opravu, kterou nález dovoluje – starou adresu zapsanou do redirect_from cílového příspěvku, relativní odkaz přepsaný na adresu, kterou míní, osiřelý soubor přesunutý do koše. Nic se nepoužije bez stisku klávesy, nic se nemaže rovnou a nález bez zjevné odpovědi – dva příspěvky v kolizi, obrázek, který posoudí jen člověk – se ukáže a přeskočí, místo aby se hádal.

Osvědčil se dřív, než vyšel: na skutečném archivu snížil 238 nálezů na 42 a 21 oprav, které navrhl, se jedna k jedné shodovalo s tím, co už člověk rozhodl ručně.

--json říká všechno

Číst dál

Nasazení ve vlastním jazyce

Průvodci byli přeložení od začátku; vyprávění kolem nich ne. Český web sledoval vlastní nasazení v angličtině, o řádek nad českou větou – varování sestavení, selhání oznámení, chyby importu, pokyny fronty k opravě, všechno. Ne přímo rozbité. Jen dům, kde půlka pokojů odpovídá jiným jazykem.

Šedesát vět se přestěhovalo domů

1.4 tu práci dokončuje: celé vyprávění nasazení – hlavička, průběh, závěrečný součet, každé oznámení o omezení – plus všech jedenáct varování sestavení, každé selhání Bluesky a Mastodonu a věty, které import vypíše, když zdroj zemře. Angličtina, čeština a němčina nesou tutéž sadu a sada testů paritu vynucuje, takže klíč nemůže existovat v jednom jazyce a v druhém shodit běh.

Co zůstává, jak přišlo

Diagnostika uvnitř vět se nepřekládá: HTTP kód, syrová odpověď serveru, text výjimky. To jsou důkazy a důkazy se citují, ne parafrázují – věta kolem nich patří webu, to uvnitř patří síti.

Past plurálu

Číst dál

Deset menších věcí

Zbytek tohoto vydání je deset přírůstků, z nichž každý potřebuje odstavec, ne příspěvek.

Stránky

page: true dá příspěvku trvalou adresu v kořeni – /about/ – mimo výpisy a feedy, ale v sitemapě a v indexu hledání. Ghost, WordPress, Squarespace a Substack je teď importují jako stránky, místo aby je přeskočily, a import řekne, kde přistály a že na ně zatím nic neodkazuje. Engine za tebe položku nav: nenapíše; kam stránka patří v tvém menu, je tvoje rozhodnutí.

Série

series: seskupuje příspěvky a series_part: řadí ten, který jsi publikoval mimo pořadí. Každá série dostane výpis a každý příspěvek v ní odkazuje na předchozí a další díl – jen uvnitř série, nikdy se nepřelévá do archivu okolo. Náhled konceptu říká, jestli se jméno jeho série připojuje k něčemu, co existuje, nebo zakládá něco nového, takže překlep se chytí, dokud je ještě zadarmo opravit.

Mimo výpisy

Číst dál

Co potichu hnije

./blog.sh doctor se ptá, jestli je instalace v pořádku, a trvá to vteřinu. Nemá co říci k archivu čtyř tisíc příspěvků, ve kterém se jeden obrázek nikdy nestáhl, tři trvalé odkazy nikam nevedou a dva příspěvky si nárokují tutéž starou adresu.

./blog.sh check to všechno projde a řekne.

Co hledá

Každý nález pojmenuje příspěvek a slug – něco, kam jít a co opravit – a nese řádek, co s tím udělat.

Číst dál

Všechno, co je špatně, najednou

Každé přerušení v tomto enginu je správné tam, kde stojí. Každé také hlásí přesně jeden problém – ten první, odkudkoli v kódu, kde si ho náhodou všimlo. Oprav ho, spusť znovu, potkej další. Opakuj, dokud se to nesestaví.

./blog.sh doctor přečte, co je na disku, a řekne ti všechno v jednom průchodu, celými větami, každou s řádkem opravy napsaným pro někoho, kdo neví, ve kterém souboru to nastavení bydlí.

Jde po tichých selháních

Hlasitá chyba se aspoň ohlásí. Problémy, na které se doctor soustředí, jsou ty, které nikdy nic neřeknou:

Číst dál

Starý odkaz pořád zná cestu

První příspěvek na tomto webu je o fotce, která zmizela z blogového zápisu z roku 2012, zatímco odkaz na ni fungoval dál. Rozpad odkazů je důvod, proč tento engine existuje, takže engine, který by si potichu rozbíjel vlastní adresy, by byl špatný vtip.

Přejmenování příspěvku mění jeho adresu. To je nevyhnutelné – slug je adresa. Co je odvratitelné, je to, aby se ze staré adresy stala 404.

Co přejmenování dělá teď

Přejmenuj příspěvek – r v dialogu vlastností – a příspěvek si svou starou adresu zaznamená do sebe. Sestavení pak na každé adrese, kterou příspěvek kdy měl, drží jednostránkové přesměrování.

Odkaz v dva roky starém tootu se dál překládá. Odkaz, který někdo dal do vlastního blogového příspěvku, se dál překládá. Můžeš opravit slug, kterého lituješ, aniž tě oprava stojí každý odkaz na něj, který už ve světě existuje.

Přesměrování patří příspěvku

Číst dál

Žádné gemy (jedna hvězdička)

./blog.sh nepotřebuje žádné gemy. Tady je ta jedna hvězdička u té věty, protože tvrzení bez své výjimky za moc nestojí.

Napřed tvrzení: nula gemů, nula balíčků z npm, žádný Bundler, žádný lockfile, žádná složka node_modules potichu tloustnoucí ve tmě. Ruby 2.7 nebo novější a bash. Naklonuj a běží.

Hvězdička, hned na začátku

Dva volitelné widgety postranního panelu – Pixelfed a obecné RSS – rozebírají XML pomocí rexml. To je výchozí gem: přichází přibalený s každou normální instalací Ruby, takže pro většinu lidí tvrzení platí, jak je napsáno. Ale některé linuxové distribuce Ruby rozdělují do balíčků a výchozí gemy dávají do samostatného.

Takže: když ty dva widgety zapneš na Ruby z distribučního balíčku a sestavení si stěžuje na rexml, jsi ta hvězdička. Dvě cesty ven – nainstalovat balíček své distribuce, něco jako ruby-rexml, nebo gem install rexml. Tak či tak je to jeden balíček, jednou, a jen když ty widgety vůbec používáš.

Číst dál

Nasazení, které odmítne smazat tvůj web

Petr
Pustil jsem --prune po rozbitém sestavení.
Pavel
Takže máš prázdný web.
Petr
Ne. Nasazení odmítlo.
Pavel
…to chci.

To je celá funkce: nasazení předpokládá, že velká změna je chyba, dokud neřekneš jinak.

Jak to funguje

Každé nasazení si vede manifest – SHA-256, velikost a mtime každého nahraného souboru. Další nasazení se proti němu porovná a sáhne jen na to, co se skutečně změnilo. Rychlé, nudné, správné.

Zajímavá část je to, co se stane, než se cokoli nahraje. Když počet souborů od posledního nasazení klesl o víc než 20 %, celé se to zastaví. Tohle je skutečný výstup z tohoto webu – na minutu jsem odstavil polovinu složek sestavení z dohledu a požádal o nasazení:

Číst dál

Žádná databáze. Jeden soubor JSON na příspěvek.

Tady jsou tři řádky Markdownu a tady je, jak vypadá soubor na disku poté, co je uložíš.

Co napíšeš:

Příspěvky jsou **soubory**. Sestavení je cyklus přes složku.

Žádný třetí krok není.

Co dopadne na disk, jeden soubor JSON na příspěvek:

Číst dál