Přeskočit na obsah

Tato stránka byla automaticky přeložena z angličtiny, jediného jazyka, ve kterém se tento web píše. Číst originál.

Přenesení derive

derive offload: běh derive jedné větve na deklarovaném stroji clusteru ve své řadě - příkazy a exit kódy, deklarace `derive-offload`, výběr hostitele podle volného místa a délky fronty, FIFO fronta s odstraňováním mrtvých čekatelů, obousměrný přenos bundle s jeho odmítnutími a vlastním build adresářem každého derive a etiketa nástěnky a meshe

Vykresleno z docs/OFFLOAD.md — stejný Markdown, který ukazuje GitHub.

Derive přegeneruje každý commitnutý odvozený artefakt a každá relace jej potřebuje, než může commitovat. Na nečinném stroji trvá asi deset minut a na sdíleném MacBooku pod zátěží až hodinu. majordomus offload spustí derive větve na jiném stroji, který repozitář deklaruje, v řadě onoho stroje, a odvozené soubory přinese zpět připravené (staged). Nic se necommituje ani nepushuje. Chování tak, jak je implementováno a testováno. Kde se tato stránka a spustitelný soubor rozcházejí, je chybná stránka a mění se ve stejném commitu.

Modul je apps/majordomus-cli/src/offload/. Pravidlo je project.a-derive-offload-waits-its-turn a úkol, který ho vytvořil, je I2398. Před ním byl offload skriptem v domovském adresáři s napsanými hosty. Jeho zámek byl until mkdir lock; do sleep 15; done. 2026-10-11 v 00:18Z takto čekalo na lundra pět relací, nejstarší 2 h 12 min, zatímco zámek vyhrávali pozdější příchozí.

Příkazy

majordomus offload hosts                  # the declaration, defaults filled in; contacts nobody
majordomus offload probe                  # measure every host, name the one a derive would take
majordomus offload derive .               # derive this worktree on the chosen host, stage the result
majordomus offload derive . --host lundra # on a named host (a declared id or address)
majordomus offload derive . --keep        # keep the host's worktree afterwards

--declaration <file> čte soubor deklarace místo repozitářového a --format json vypíše jeden dokument. Spustitelné příklady jsou v generované referenci (generated/cli.md, pod majordomus offload).

ukončeníoffload derive
0odvozeno; změněné soubory jsou připraveny ke commitu, nebo derive nic nezměnil
2nesledovaný soubor, nevyřešený merge nebo merge s neindexovanými změnami: nic se nepřeneslo
10derive na hostiteli selhal; posledních několik řádků jeho logu se vypíše a jeho worktree tam zůstane
11derive smazal sledovaný soubor; nic nebylo aplikováno a snímek je pojmenován pro ruční aplikaci
12žádný deklarovaný hostitel jej nemůže převzít, hostitele nebylo možné použít, nebo se výsledek neaplikoval
75deklarované čekání fronty vypršelo; lístek je stažen

offload probe skončí s 12, když není způsobilý žádný hostitel. offload hosts skončí s 0, i když není nic deklarováno: prázdná deklarace je odpověď.

Deklarace

Hostitelé a jejich limity jsou zapsáni jednou v .ai/repo/offload/derive.yaml. Druh je derive-offload a schéma derive-offload/v1 (share/schemas/majordomus/derive-offload/). Každé sestavení indexu je validuje a obsluhuje se jako jakýkoli jiný objekt vrstvy, jako majordomus://derive-offload/derive. Žádný skript ani řádek crate nenese adresu hostitele.

poleplatívýchozí
hosts[]id, address (user@host), volitelné identity_file, min_free_gib, description; pořadí rozhoduje o shodě— (jedno je povinné)
min_free_gibGiB, které musí být volné pod domovským adresářem hostitele, aby byl vybrán10
baseref, proti kterému se balík řežeorigin/master
queue.directory, queue.lockadresář ticketů a zámek, absolutní na hostiteli/tmp/offload-queue, /tmp/offload-derive.lock
queue.poll_seconds, queue.wait_max_secondsmezi pohledy a celkem5, 14400
remote.checkout, remote.worktreescheckout hosta a kde se vytváří worktree každého derive, pod jeho homedev/prismatic-majordomus, dev/prismatic-majordomus-wt
remote.targetsdílený adresář sestavení, z něhož si každé derive klonuje vlastní.cache/majordomus-offload-target
remote.spoolkam se zapisují balíčky a log derive/tmp
remote.path, remote.derive, remote.touchpředpona PATH, příkaz derive a soubory dotčené před nímadresáře bin z asdf, cargo a Homebrew; scripts/derive; kořeny crate

Přidání stroje je jedna položka pod hosts:. Stroj potřebuje přístup ssh bez promptu, checkout tohoto repozitáře v remote.checkout, z jehož origin umí fetchovat, a toolchain, s nímž scripts/derive staví. offload probe je kontrola, že odpovídá.

Výběr hostitele

Každý deklarovaný hostitel se jednou přes ssh zeptá na volné místo pod svým domovem a na svou frontu. Hostitel se přeskočí a sonda řekne proč, když:

  • neodpovídá, nebo odpovídá něčím, co fronta nečte, například přihlašovacím bannerem;
  • má méně volného místa, než je jeho minimum;
  • nehlásí žádnou hodnotu volného místa, protože neznámé nikdy nestačí.

Z hostitelů, kteří zbyli, derive vezme toho s nejmenším počtem běžících nebo čekajících derive: každý živý tiket, plus jedna, když je zámek držen. Při shodě vyhrává hostitel deklarovaný první.

Fronta

Každý hostitel provádí najednou jedno offloadnuté odvození a jeho čekatelé se obsluhují v pořadí, v jakém přišli. Rozhodnutí se činí v Rustu nad tím, co hostitel hlásí (offload/queue.rs). Hostitel spouští krátké skripty, které jen pozorují a jednají. Každou hodnotu přebírají jako argument, nikdy jako součást svého textu.

  • Čekající spustí na hostiteli držitele, proces, který žije přesně tak dlouho jako spojení čekajícího. Poté zapíše lístek pojmenovaný <arrival>-<holder pid>-<tag>, kde příchod je devatenáct číslic nanosekund od epochy.
  • Čekatel získá zámek, jen když je jeho lístek nejstarší z těch, jejichž držitel žije. Zámek je adresář vytvořený mkdir a drží jeden prázdný soubor na proces derive, který jej drží, pojmenovaný jeho pid.
  • Lístek, jehož držitel je mrtvý, odstraní ten, kdo ho uvidí. Čekající, který byl zabit nebo ztratil spojení, nikoho neblokuje.
  • Zámek, jehož všichni držitelé jsou mrtví, získá zpět kterýkoli čekající a získání jmenuje mrtvé pidy.
  • Adresář zámku bez souboru pid vzal čekatel starých skriptů a nikdo to nemůže ověřit. Čeká se na něj a nikdy se nepřebírá.

Cesty a názvy ticketů jsou ty, které používalo ~/dev/.derive-offload-v2.sh. Čekatel v2 a čekatel tohoto příkazu proto vidí vzájemně své tickety, zatímco se relace přesouvají. Čekatel v1 o zámek stále soupeří, dokud jeho relace nepřestane zámek používat.

Cesta tam a zpět

  1. Co putuje. Worktree tak, jak stojí: HEAD, když je čisté, jinak snímek git stash create jeho sledovaných a připravených změn. Ten zapíše objekt commitu a nedotkne se indexu, worktree ani hooku. Commit hook odmítne strom, který ještě není odvozen, takže změnu nelze commitnout před jejím derive. Nesledované soubory by nepřenesly a jsou odmítnuty.
  2. Probíhající merge putuje jako skutečný merge commit s oběma rodiči, zapsaný git commit-tree z připraveného stromu, jakmile je každý konflikt vyřešen. Stash by druhého rodiče zahodil a changelog, který se skládá z logu, by se odvodil bez mergnutých commitů (PR #854, 2026-10-10). Odvozené soubory se vracejí připravené do merge a git commit jej dokončí přes hook.
  3. Svazek (bundle) obsahuje jen commity, kterých base nedosáhne, a jde přes standardní vstup ssh. Vstup, kterého base už dosáhne, se do svazku nedává, protože ho hostitel má. Nic se nepushuje na origin, takže nezačne žádný běh CI.
  4. Na hostiteli derive běží v odpojeném worktree offload-<tag>, ve své řadě. Staví v build adresáři vlastním: klonu sdíleného adresáře typu copy-on-write, kde souborový systém klony má (cp -c na APFS, cp --reflink=always na Linuxu), jinak v prázdném. Adresář se po skončení derive odstraní. Build do sdíleného adresáře derivem, který zámek nikdy nevzal, tak nemůže nahradit spustitelný soubor tohoto derive. Na druhém MacBooku 2026-10-11 v 00:25Z to udělal a stage C odmítla s „this executable is not of this tree's generation“.
  5. Zpět zde se soubory, které derive změnil, vyhodí (checkout) z odvozeného snímku a připraví (stage) a worktree se s tímto snímkem porovná. Derive, který maže sledovaný soubor, je odmítnut dříve, než se cokoli aplikuje. Balíky se z hostitele odstraní, stejně jako jeho worktree, pokud není zadáno --keep nebo derive neselhal.

Vlastní zámek derive stroje (project.one-derive-at-a-time) se neberou: hlídá tento stroj, a tento stroj neodvozuje. Na hostiteli scripts/derive bere zámek stroje tohoto hostitele jako obvykle.

Nástěnka a mesh

Offload je sdílený zdroj a nástěnka peerů a mesh jsou způsob, jak ho relace sdílejí:

  • Před dlouhým derive to uveďte ve svém záměru majordomus_announce, s hostitelem, pokud jste nějakého určili. Peer, který čte majordomus_peers, pak ví, proč je fronta na lundra dlouhá.
  • offload probe je měření. Čtěte je místo hádání, který hostitel je volný, a zámek nikdy nebertě ručně: ručně vytvořený prázdný adresář zámku je ten, na který musí fronta čekat navždy.
  • Relace na jiném stroji odesílá práci na stejné hostitele a vstupuje do stejných front, takže fronta je koordinací napříč stroji. Pro běžný derive není třeba žádný nárok v mesh. Když se práce na hostiteli nesmí napříč stroji překrývat, například údržba, která vyprázdní jeho sdílený adresář buildu, nejdřív si ho vyžádejte výhradně pomocí majordomus_mesh_claim.
  • Nikdy nespouštějte scripts/derive na hostiteli ručně, dokud tam běží offloady. Nebere ani frontu, ani zámek offloadu.

Testy

souborproves
apps/majordomus-cli/src/offload/queue.rs (jednotka)rozhodnutí nad pozorováními: pořadí, mrtvé tikety, získaný mrtvý zámek, počkáno na neověřitelný zámek, ztracený tiket, odmítnutá nečitelná odpověď
apps/majordomus-cli/src/offload/host.rs (jednotka)volba hostitele: nejméně vytížený, shody podle pořadí deklarace, nedostupný, pod svým minimem, neznámé místo, vlastní minimum hostitele
apps/majordomus-cli/src/offload/declaration.rs (jednotka)deklarace: výchozí hodnoty, neznámé klíče odmítnuty, adresy a cesty validovány
apps/majordomus-cli/tests/offload.rsfronta proti skutečnému adresáři se skutečnými procesy držitelů a příkaz od začátku do konce proti hostitelům, kterými jsou adresáře na tomto stroji, dosažené přes lokální náhradu za ssh

Testy od začátku do konce nepotřebují síť. MAJORDOMUS_OFFLOAD_SSH pojmenovává náhradu, která spouští vzdálený příkaz pod domovským adresářem falešného hostitele. Volné místo hostitele je to, co hlásí jeho náhrada df, a hostitel, který je nedostupný, odmítne spojení s kódem 255 ssh. Dokládají tato chování:

  • dva čekající jsou obslouženi v pořadí příchodu, ačkoli později příchozí začal čekat dřív;
  • lístek mrtvého čekatele frontu neblokuje;
  • hostitel, který je mimo provoz nebo mu chybí místo, se přeskočí;
  • necommitnutá změna putuje a výsledek se vrací jako staged a necommitnutý, bez čehokoli, co by na hostiteli zůstalo, dokonce ani ve sdíleném adresáři sestavení, který checkout deklaruje: adresář sestavení deriveu je připnut ke svému běhovému adresáři i cíli;
  • probíhající sloučení si ponechává oba rodiče;
  • nesledované soubory, nevyřešený merge, derive, který maže, a selhaný derive se odmítají každý zvlášť;
  • souběžný build do sdíleného adresáře nenahradí spustitelný soubor derive.

Každá z těchto mutací shodí test: zámek vzatý bez ohledu na pozici, ponechané mrtvé tikety, CARGO_TARGET_DIR ukázané na sdílený adresář a CARGO_BUILD_BUILD_DIR ponechané deklaraci checkoutu (2026-10-18 to nechalo 87 GB v build-shared/majordomus na lundře, mimo to, co odstraňují pasti běhu, a svazek na 0 bajtech; I2882).

Prohledává názvy a popisy všech stránek, které tento web publikuje.