Skip to content

Cache _work persistant : ni maintenance des packs, ni precondition d'integrite (264 packs, 1471 refs vides) #15105

Closed

Description

@myia-ai-01

Grain: MED/tooling — lane myia-ai-01:CoursIA — prev: MED/tooling #15103

Le cache _work persistant n'a aucune maintenance ni aucune précondition d'intégrité

Deux défauts d'une même cause : actions/checkout est écrit pour un workspace jetable, et #14285 a rendu ce workspace persistant sans rien ajouter en compensation.

Mesuré firsthand sur ai-01 le 2026-09-07, au cours du diagnostic du PR gate rouge de #15094/#15103 (récit complet : #15103 (comment)).

Défaut 1 — croissance des packs sans borne

actions/checkout pose gc.auto = 0 dans le dépôt du slot (contrôle : 0 occurrence de gc.auto dans tout notre dépôt, quand le même grep rend 59 blob:none — ce n'est pas nous). C'est correct pour un workspace jetable : la maintenance git y serait du temps perdu. Sur un volume qui survit aux jobs, ça veut dire que rien ne consolide jamais rien.

Chaque job dépose un pack promisor de plus (récupération paresseuse des blobs sous partialclonefilter = blob:none) :

Slot packs dont promisor .git
1 264 263 849M
2 8 8 761M
3 138 137 2.3G
4 0 0 762M
5 35 35 766M
6 154 154 813M
7 14 12 2.5G
8 116 115 800M

Slot 1 : 264 packs, 821,7 Mio au total — un pack de clone de 713,9 Mio, et 263 packs de 3,11 Mio de moyenne empilés derrière. Toute opération git y ouvre et parcourt 264 index de pack, et le compte croît à chaque job sans plafond.

Défaut 2 — aucune précondition d'intégrité au démarrage d'un slot

Le 2026-09-07, le slot 7 portait 1471 fichiers de réf de zéro octet (séquelle des arrêts brutaux : dirent validée, contenu jamais écrit). git fetch énumère les réfs locales pour bâtir sa liste de have, bute sur la première cassée, et abandonne — fatal: bad object … / did not send all necessary objects.

Conséquence : le gate de toute la flotte est devenu une loterie 1-sur-8. Preuve dans un seul commit de #15094 — au même instant, sur la même tête, Always-on metadata guards réussit pendant que Always-on guards -- 12 organes et le PR gate échouent. Trois jobs, trois tirages de slot.

Le point qui compte : aucun organe ne l'a nommé. Le symptôme visible était « le gate est rouge », et la cause a demandé une investigation manuelle. supervise.sh ne fait aucune vérification du dépôt en cache — grep -n 'fsck\|for-each-ref\|broken' y rend zéro. Un slot au cache corrompu se présente comme un slot sain et empoisonne silencieusement tout job qui l'attrape.

Ce qui est demandé

  1. Précondition d'intégrité avant qu'un slot n'accepte un job : détecter les réfs cassées (git for-each-ref rend ignoring broken ref sur stderr — le canal, pas le code de retour) et, le cas échéant, réparer (retirer les réfs vides) ou marquer le slot défaillant. Le geste de réparation est prouvé : suppression des réfs/logs vides, objects/ hors périmètre, 0 octet de clone — 1472 réfs cassées → 0, les 2,5 Gio d'objets intacts.
  2. Maintenance périodique du cache : git repack -ad (ou git maintenance) entre deux jobs, hors du chemin critique d'un job, sous la borne d'I/O agrégée déployée par fix(ci,#15091): bornes I/O ai-01 -- unite corrigee, daemon.json, garde sur l'arret #15103.

Deux pièges à ne pas répéter

  • .promisor vide est LÉGITIME — c'est un marqueur de pack à récupération paresseuse. Un find .git -type f -empty -delete naïf les emporte et fait croire à git que les objets manquent au lieu d'être fetchables : une seconde corruption déguisée en réparation. Le dry-run l'a rattrapé avant l'exécution ; tout organe écrit ici doit porter ce contrôle.
  • git refuse ces dépôts pour dubious ownership (uid 1001 sous root). Sans -c safe.directory='*', for-each-ref rend zéro réf sans erreur visible si stderr est supprimé — indiscernable d'un cache sain. Ma première sonde a rendu « refs saines (0 refs) » sur les huit slots pour cette raison exacte. Tout détecteur doit lire stderr et porter un contrôle positif.

Ce qui est déjà en service et n'est PAS à refaire

--filter=blob:none (posé explicitement dans nos workflows, sur les huit slots) et le cache de clone persistant par slot (#14285). Je les avais nommés comme leviers de réduction d'empreinte dans #15103 : les deux étaient déjà livrés au moment où je les nommais, et le chiffre de « ~4,8 Gio par clone frais » que j'en tirais décrivait un clone complet, régime que la flotte n'a pas.

Acceptance

  • Un slot au cache corrompu est nommé par un organe, pas découvert à la main après un gate rouge.
  • Le compte de packs d'un slot actif est borné, avec la mesure avant/après citée.
  • Le détecteur porte son contrôle positif (safe.directory, stderr lu, .promisor préservé) — validé par ses faux négatifs, pas par ses hits.

Voir #15091, #15103, #14285.

Activity

  1. jsboige commented on Sep 8, 2026

    @jsboige
    Owner

    [CLAIMED] lane myia-po-2026:CoursIA — précondition d'intégrité du cache slot (réfs cassées, contrôle positif safe.directory/stderr/.promisor) + maintenance repack bornée entre jobs, dans le harnais scripts/ci/docker/linux-runner/

  2. added a commit that references this issue on Sep 9, 2026
  3. added a commit that references this issue on Sep 9, 2026
  4. added a commit that references this issue on Sep 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions