Repository navigation
fix(ci,#15091): po-2024 runners supervisor — bump ExecStart 8→12 slots (P0 ai-01 famine runners) - #15313
Merged
Conversation
…1 famine runners) Cible : mission P0 ai-01 msg-20260909T011024-jgamgp, deadline 08:30Z EPF. Cause : 682 jobs queued / 10 in_progress, pool linux auto-heberge sature. Mesure firsthand po-2024 : - nproc = 16, loadavg = 0.08 (1/652 process), marge CPU ~15 vCPU - MemTotal = 23.47 GB, MemAvailable = 22.43 GB - Image locale coursia-linux-runner:2.336.0 OK (post-fix entrypoint.sh:58-72) - Service MASKED depuis 2026-09-07, 0 conteneur myia-po-2024-* actif Calcul : 12 slots × 3 vCPU = 36 vCPU sur 16 nproc = overcommit 2.25x, acceptable vu loadavg 0.08. Borne haute alignee sur la regle ai-01 '+4 stables > +12 qui font swap' : on est a +4 (8 → 12), pas +12. L'amend ne touche QUE l'argument ExecStart et le commentaire de section. Le defaut wrapper (N=4 dans coursia-runner-start.sh) reste le filet ; start 12 ici est l'intention explicite pour cette machine, pas une dependance au defaut. L'action d'unmask systemd + systemctl enable --now sur la machine est UAC- gated (sudo password) et reste en attente action user (cf dashboard). Co-Authored-By: Claude-Code <noreply@anthropic.com>
9 tasks done
Contributor
Path-collision (organ #13359/#13615)Cette PR #15313 (
|
9 tasks
jsboige
added a commit
that referenced
this pull request
Sep 9, 2026
…erministe Six points du dispatch msg-20260909T174226-986o1r : - start 12 preserve, UNE seule paire StartLimit 300/5 (jamais le bloc 600), test d'unicite grep -c = 1 (deja en place, verifie) - Test 29 work_cache_health de main (#15105), numerotation unique 1-29 - t0=$SECONDS restaure dans slot_loop/waiter_loop : la fusion l'avait perdu, lifetime=$(( SECONDS - t0 )) sous set -u tuait le superviseur au 1er cycle de toute boucle reelle (line 690: t0: unbound variable) - stubs docker internes 11-28 : desormais 2 probes sha256 (la probe work_cache_health.sh recevait le sha de l'entrypoint => image jugee PERIMEE => tous les tests en boucle reelle echouaient) - determinisme des tests 1-3/7/10/22 : stub sleep global, timeouts 8-20 s, polls boucles ; le test 10 verifie $STATE_DIR/pids (ecrit par redirection directe) au lieu de l'echo stdout bufferise - suite complete fraiche : 61 PASS / 0 FAIL (29 tests) Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
myia-ai-01
pushed a commit
that referenced
this pull request
Sep 10, 2026
…onible (#15166) * fix(ci,#15095): superviseur runners borne -- backoff par duree de vie, garde daemon, unite fail-closed Incident 07/09 (ai-01, 2 gels machine/90 min) : docker.service arret + Restart=always laissaient slot_loop marteler docker run + fetch_token 4-8 fois/min (rc=0, cycles courts), ecriture ext4.vhdx 94-96 Mo/s, load 69. - cycle_backoff : la DUREE DE VIE du conteneur (pas le rc) classe le cycle -- court => backoff exponentiel 15,30,60,...,900 s remis a zero apres un cycle sain (>= 60 s), partag par slot_loop et waiter_loop (remplace [ rc -ne 0 ] && sleep 15 || sleep 2) - assert_docker_daemon : docker info sur le DOCKER_HOST epingle avant tout slot/fetch, dans cmd_start/cmd_waiters/cmd_lean - persist/coursia-runner.service : Requires+BindsTo docker.service (inverse le choix Wants= de #14347) + StartLimitIntervalSec/Burst (fail-closed, retour du daemon = geste operateur) - persist/coursia-runner-start.sh : meme garde au niveau ExecStart - tests 11-15 par stubs PATH (sleep qui logue ses args, docker stub posant STOP_FILE) : 24 assertions PASS, evidence cadence 6 runs/900 s contre 60-120 avant (incident mesure) Deploiement reel hors scope : coursia-runner.service reste DESACTIVE sur ai-01 jusqu'a controle positif sur 1 slot. Co-Authored-By: Claude-Code <noreply@anthropic.com> * fix(ci,#15095): saturer cycle_backoff avant exponentiation + signal de travail reel Review ai-01 (#15166, 3 points) : 1. OVERFLOW (reproduit au SHA, Git Bash 5.2.37, sleep stub) : 15*2^60 deborde l'arithmetique signee 64 bits de bash -- cycle 61 negatif (-1152921504606846976), cycle 65+ nul, et le plafond n'atteint jamais ces valeurs (sleep 0 = retour du martellement 4-8/min de l'incident 07/09). StartLimitBurst ne couvre pas cette boucle interne. Fix : saturation AVANT l'exponentiation -- l'exposant est borne au plus petit cap_exp tel que BASE*2^cap_exp > CAP (probe du p double, BASE*2^k ne pouvant egaliser une puissance de deux exacte, donc pas de debordement du probe lui-meme). Tout exposant >= cap_exp donnait deja le meme delai plafonne : la file observable est identique jusqu'au cap, puis PLATONNE. 2. CYCLE COURT UTILE vs BOUCLE VIDE : la duree seule penalisait tout conteneur < 60 s, meme utile. Ajout d'un signal de travail RECLAME et TERMINE -- le log du cycle est un cumul (rotate_log ne borne que par taille), donc le grep ne lit que la portion ecrite par CE cycle, a partir de l'offset d'octets capture avant le docker run. Un cycle court portant une execution de job ne nourrit pas l'exponentiel (compteur remis a zero, respiration courte) ; la protection contre les boucles sans travail est inchangee. 3. CYCLE LONG rc!=0 : n'est PLUS journalise "sainement" -- compteur de courts conserve, respiration intermediaire (BACKOFF_MIN_SEC), message "non qualifie sain". (Un cycle long rc=0 reste sain.) Tests (test_supervise_guards.sh, +3) : T25 = 70 cycles courts consecutifs => plafond tient jusqu'au bout, aucune valeur negative ni nulle (le test meme du debordement 61+ avec BASE=3 : 3*2^62 deborde au cycle ~63) ; T26 = controle positif -- cycles courts AVEC travail => sleep 2 sans backoff puis repart a 3,6,12 apres la fin du travail (compteur remis a zero) ; T27 = cycle brule mais rc!=0 => non qualifie sain, compteur conserve (3,6,7,12,24,24). Le test 14 preexistant presentait la meme sensibilite au chevauchement de tick (HEALTHY=1, burn 2s) : durci a HEALTHY=2 / burn 3s, sequence attendue INCHANGEE -- signale a po-2023:CoursIA-2 (proprietaire du claim #15095). Validation : suite complete x3 = 58 PASS / 0 FAIL (auparavant 51 tests / 1 fail environne sur test 3 sentinel --force). Co-Authored-By: Claude-Code <noreply@anthropic.com> * fix(ci,#15166): detecter un cycle de travail sans SIGPIPE tail sur gros log de cycle tail | grep -q sort des la premiere ligne et ferme le pipe pendant que tail ecrit encore le corps du log (sous set -uo pipefail) -> SIGPIPE 141 -> pipeline non nulle -> un cycle court AYANT traite un job est classe en boucle vide et part en backoff (sleep 15 au lieu de 2). grep "Running job" >/dev/null lit tout jusqu'a EOF : tail se termine proprement, rc=0 sur match. Test 28 (controle de regression) : cycle court AVEC travail sur un log de cycle >64 Ko (marqueur + 1 Mio de suffixe, >> tampon pipe ~64 Ko) -> sleep 2 sans backoff. Verifie ROUGE (3,6,12) sur l'ancien grep -q, VERT (2,2,2) apres le fix. Suite complete : 60 PASS / 0 FAIL. Co-Authored-By: Claude-Code <noreply@anthropic.com> * reconcile(fix/ci,#15166): reintegration post-merge #15313 + suite deterministe Six points du dispatch msg-20260909T174226-986o1r : - start 12 preserve, UNE seule paire StartLimit 300/5 (jamais le bloc 600), test d'unicite grep -c = 1 (deja en place, verifie) - Test 29 work_cache_health de main (#15105), numerotation unique 1-29 - t0=$SECONDS restaure dans slot_loop/waiter_loop : la fusion l'avait perdu, lifetime=$(( SECONDS - t0 )) sous set -u tuait le superviseur au 1er cycle de toute boucle reelle (line 690: t0: unbound variable) - stubs docker internes 11-28 : desormais 2 probes sha256 (la probe work_cache_health.sh recevait le sha de l'entrypoint => image jugee PERIMEE => tous les tests en boucle reelle echouaient) - determinisme des tests 1-3/7/10/22 : stub sleep global, timeouts 8-20 s, polls boucles ; le test 10 verifie $STATE_DIR/pids (ecrit par redirection directe) au lieu de l'echo stdout bufferise - suite complete fraiche : 61 PASS / 0 FAIL (29 tests) Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(ci,#15166): retirer le stub sleep du test 22 -- borne reelle du rythme waiter Le stub bin17/sleep (ajoute avec le stub sleep global) rendait la boucle waiter instantanee : ARGV_LOG grossissait de milliers de lignes sous le timeout 20 s, et `echo "$argv" | grep -q` prenait un SIGPIPE sous pipefail en CI Linux (mesure : 60 PASS / 1 FAIL sur run 34399944998, argv pourtant conforme). Le design d'origine borne le rythme via le sleep 3 reel du stub docker + le backoff reel : le log reste a 1-2 lignes. Suite locale : 61 PASS / 0 FAIL. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(ci,#15166): validation fail-closed des bornes backoff + doublement garde Review v2 (pullrequestreview-5159868981) : les env overrides n'etaient pas valides et le probe de cap_exp pouvait boucler sans fin -- BASE=2^62 / CAP=2^63-1 doublait p vers 2^63 -> -2^63 -> 0 (boucle infinie), BASE=0 produisait un backoff nul sans fin. - validate_backoff_env (cmd_start/waiters/lean, avant assert_docker_daemon) : decimal strictement positif, 18 chiffres max (< 2^60, marge large sous la borne signee pour tout produit garde), BASE <= CAP -- die nomme la variable fautive, jamais de boucle atteinte. - cycle_backoff : d calcule ITERATIVEMENT, on ne double que si d <= CAP/2 (chaque produit <= 2*floor(CAP/2) <= CAP, dans le domaine) ; doublons incomplets => plafond CAP. L'ancien probe cap_exp et le 2**exp sont retires. - Tests 30 (BASE=0 / non numerique / BASE>CAP / CAP hors domaine : refus rc=1 avant toute boucle) et 31 (BASE=CAP=2^59, frontiere puissance de deux : 3 backoffs egaux a la borne, jamais negatif/nul, boucle TERMINEE). Suite complete : 66 PASS / 0 FAIL (61 + 5 nouvelles assertions). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(runner,#15166): harness polls use REAL_SLEEP, not the stub The global sleep stub at $TEST_DIR/bin/sleep sits first in the PATH of tests 3 and 10, so their poll loops ("sleep 0.5" x24) never actually waited: test 10 raced the pids file on the Linux CI runner (65/1). Capture REAL_SLEEP="$(command -v sleep)" BEFORE the stub is created and use it in the two harness polls; the stub stays untouched for the tested program's backoffs. No timeout or iteration count was lengthened. Local: 3 consecutive full-suite runs -> 66 PASS / 0 FAIL. See #15166 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> --------- Co-authored-by: Claude-Code <noreply@anthropic.com>
5 tasks
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.
Grain: LIGHT/guard — lane myia-po-2024:CoursIA — prev: DEEP/lean #15135
Cible
Mission P0 ai-01 (msg-20260909T011024-jgamgp, HIGH, deadline 08:30Z EPF) : augmenter la capacité des runners Linux auto-hébergés po-2024.
Cause du saturé
682 jobs queued / 10 in_progress. Le pool CoursIA-Linux self-hosted ne tient pas la charge. Côté po-2024, deux défauts cumulés :
coursia-runner.serviceetcoursia-waiters.servicepointent/etc/systemd/system/*.servicesur/dev/null. 0 conteneur actif sur les 3 familles (linux-docker, linux-waiter, lean-docker).Mesures firsthand (WSL
/proc, 2026-09-09T05:07Z)nprocWSL/proc/loadavg/proc/meminfo/proc/meminfo/var/run/docker-ce.sockOK (séparé Docker Desktop, R3 docker-ce-trap respecté)ls -lacoursia-linux-runner:2.336.0(6 days ago, 1.87 GB) — post-fix entrypoint.sh:58-72, testée OKdocker historyactive=inactive enabled=maskedsystemctl statusactive=inactive enabled=maskedsystemctl statusFix appliqué
entrypoint.shretourne verdict attendu sur token absent) ; le rebuild 2.337.0 a stallé 3 min à 0 % CPU (probable pull réseau ubuntu:24.04 — sans blocker)start 8→start 12surscripts/ci/docker/linux-runner/persist/coursia-runner.service6735b36d7csur branchefix/15091-runners-12-slots, push OK/dev/nullsur la machine doit être levé manuellementReste à faire (action user)
sudo systemctl unmask coursia-runner.service coursia-waiters.servicesudo systemctl daemon-reload/etc/systemd/system/coursia-runner.servicedepuispersist/coursia-runner.service(avec amend N=12 déjà dans le commit)sudo systemctl enable --now coursia-runner.service coursia-waiters.servicedocker ps --filter name=myia-po-2024-,gh api repos/jsboige/CoursIA/actions/runs?per_page=1, jobs queued avant/aprèsNote pour ai-01 (réponse au DM)
#print axiomsbrut erc20_lean) attendra la fin de la séquence P0 (cycles 05:37Z ou 06:07Z selon rapidité user).— po-2024
Closes rien : cette PR ne résout pas l'issue #15091 (qui est sur le mécanisme restart-bounds, déjà résolu par #15094) ; elle ajuste la capacité po-2024 dans le cadre de la mission P0 ai-01.