feat(warmup): drain the tail the cap excluded, a batch at a time - #138
Open
parisek wants to merge 14 commits into
Open
feat(warmup): drain the tail the cap excluded, a batch at a time#138parisek wants to merge 14 commits into
parisek wants to merge 14 commits into
Conversation
…tore's TOCTOU window
Breeze scopes breeze_preload_queue per blog on multisite, so the tail tick's brake would always read idle there and the drain would pile onto the origin unthrottled. register() now detects is_multisite() and leaves the tail hooks unwired instead of running without a working brake. Also documents the cold-start rescue and that the batch size, like the priority weights, is read once at registration.
… alone Four tests relied solely on Functions\expect(...)->never(), a Mockery expectation verified at teardown, not a PHPUnit assertion. That left zero assertions and marked them risky, and made them read as tests that prove absence by proving nothing. Capture the calls with Functions\when(...)->alias(...) and assert the resulting array is empty instead. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D1sCgqDJKj7dGQrg5c25bY
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.
Prioritizace (#134) nahřeje po purgi prvních 200 URL v pořadí podle důležitosti. Všechno za stropem zůstane studené, dokud si o to někdo neřekne. Tenhle PR ten zbytek dohřívá — pomalu, po dávkách, ve stejném pořadí, a jen když má origin volno.
Uzavírá #136.
Co tenhle návrh záměrně NESLIBUJE
Dohřívání nemá stav „hotovo".
Plný purge přichází na těchhle projektech i několikrát denně. Ocas o 2 800 URL by při tempu Breeze (~1 s/URL) trval nejméně 47 minut souvislé zátěže, takže každý další purge ho shodí dřív, než doběhne. Slib „po purgi bude celý web teplý" by byl nesplnitelný — a zapnutý flag, který takový slib budí, je horší než žádná funkce.
Místo toho: ber další v pořadí, dokud tě někdo nezastaví. Ať se stihne dvě stě URL nebo dva tisíce, vždycky to byly ty nejcennější, které se zrovna stihly. Na rušném webu se pokryje třeba 40 % sitemapy — zato pořád těch správných 40 %.
Jak to funguje
Cron obnova nově uloží i ocas — jen URL, seřazené stejným
Scorer::sort()jako zbytek — do vlastního option řádku, který horká cesta nikdy nečte. Purge znuluje kurzor a zařadí první tik. Každý tik odebere dávku od kurzoru, pošle ji doBreeze_Cache_Preloader::preload_url()a zařadí nástupce.Řetěz se sám ukončí. Když ocas dojde, další tik se nezařadí — žádný cron běžící naprázdno.
Brzda: fronta Breeze
Měří přesně tu správnou věc: běží už teď nahřívání? Load average by řekl jen „je rušno" a nerozlišil by, jestli za to můžou návštěvníci, záloha, nebo naše vlastní nahřívání.
Vedlejší efekt, který stojí za pojmenování: vzniká přirozené pořadí. Nejdřív doběhne Breeze svých 200 nejdůležitějších, teprve pak se rozjede ocas — bez jediné synchronizační konstrukce, jen proto, že se dohřívač ptá, jestli má uvolněno.
Přiznané okno: Breeze si dávku z fronty odebere před jejím odesláním, takže u poslední dávky vidí brzda volno, ačkoli tři URL jsou ještě ve vzduchu. Trvá to zhruba sekundu na konci tříapůlminutového běhu; vědomě to přijímáme.
Zapnutí
Vypnuté ve výchozím stavu. Vyžaduje oba předchozí flagy — bez pořadí není co dohřívat.
Interval je pevných 5 minut, dávka je jediný knoflík: „kolik renderů originu za pět minut mi nevadí". Filtry
timberkit_warmup_tail_batchatimberkit_warmup_tail_max_urls(výchozí strop ocasu 5000).Pozor na aritmetiku: 100 na tik nevychází na 1200 za hodinu, protože tik ustupuje frontě Breeze. Skutečná propustnost je nižší.
Souběh
Kurzor má dva zapisovatele — purge ho nuluje, tik posouvá. Tik, který přečetl index 500 a mezitím mu purge znuloval kurzor, nesmí zapsat 600: tím by reset zrušil a nechal URL pod pětistovkou nenahřáté za kurzorem, který tvrdí, že hotové jsou. Řeší to podmíněný zápis, stejný optimistický zámek jako
PriorityStore.Docblock
TailStoreříká i to, co guard nechrání: dva skutečně souběžné tiky můžou oba projít kontrolou. Vzácné (řetěz pohání jediný plánovaný tik) a neškodné — opakovaná dávka je pár requestů navíc, ne poškozený stav.Studený start
Ocas plní odložená obnova, ale tik zařazuje purge. Při prvním purgi na projektu může tik doběhnout dřív než obnova, uvidět prázdný ocas a skončit — a obnova pak zapíše ocas, který nic nespustí. Proto obnova po úspěšném zápisu neprázdného ocasu zařadí tik sama.
Multisite
Nedrátuje se tam. Breeze scopuje
breeze_preload_queueper blog, takže by brzda vždy hlásila volno a dohřívání by sypalo do originu bez omezení na každém webu sítě. Odmítnout se zaregistrovat je bezpečnější než běžet bez brzdy.Prioritizace na multisite funguje dál beze změny — vypíná se jen dohřívání ocasu.
Ověření
composer testcomposer test:propertycomposer phpstancomposer adrDvě nové čisté třídy v
src/Breeze/—TailPlanner(rozdělení, otisk, dávka) aTailStore(dva option řádky, podmíněný zápis). Obě bez jediného volání WordPressu, takže property test splňuje izolační konvenci z AGENTS.md.Žádné ADR — je to důsledek rozhodnutí zapsaného v ADR-0006, ne nové architektonické rozhodnutí.
Známá omezení
preload_url()vracívoida URL může odmítnout. Vyčerpaný kurzor neznamená nahřátý ocas.