Files
arboretum/spikes/s3-tui/flood.mjs
Johan LEROY 65ef616867
Some checks failed
CI / Build & test (Node 24) (push) Has been cancelled
CI / Pack & boot smoke (Node 22) (push) Has been cancelled
CI / No em/en dashes (push) Has been cancelled
CI / Build & test (Node 22) (push) Has been cancelled
Deploy site (production) / build-and-deploy (push) Successful in 20s
chore(typo): retire tous les tirets cadratins/demi-cadratins + garde CI
Remplace les 547 tirets cadratins (U+2014) et demi-cadratins (U+2013) des fichiers versionnés par la ponctuation contextuelle adaptée (point médian, deux-points, virgule, parenthèses ; tiret simple pour les plages), sur 122 fichiers (appli, vitrine, doc, tests, workflows, scripts).

Ajoute le job CI « lint-dashes » (git grep -P) qui échoue si un tiret cadratin/demi-cadratin réapparaît, hors logo binaire et captures brutes du terminal (fidélité des fixtures de détection de dialogue).
2026-07-17 16:44:00 +02:00

68 lines
2.8 KiB
JavaScript

#!/usr/bin/env node
// Spike S3 (volet flood) · pause()/resume() node-pty sous 20 Mo de débit, sans claude (zéro quota).
// Critères : aucune perte (marqueur final reçu, volume >= attendu), 0 octet pendant pause,
// process bash survit à 10 s de pause, écho < 100 ms après le flood.
import ptyMod from '@homebridge/node-pty-prebuilt-multiarch';
import { execSync } from 'node:child_process';
import { writeFileSync, mkdirSync } from 'node:fs';
import { join } from 'node:path';
const CAPTURES = new URL('./captures/', import.meta.url).pathname;
mkdirSync(CAPTURES, { recursive: true });
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
// 20 Mo de base64 (lignes de 76 chars) : la conversion LF→CRLF du TTY est prise en compte
execSync('head -c 15728640 /dev/urandom | base64 > /tmp/spike-flood.txt && wc -c < /tmp/spike-flood.txt');
const fileBytes = parseInt(execSync('wc -c < /tmp/spike-flood.txt').toString().trim(), 10);
const fileLines = parseInt(execSync('wc -l < /tmp/spike-flood.txt').toString().trim(), 10);
const expectedMin = fileBytes; // reçu = fileBytes + fileLines (CR ajoutés) ; on vérifie >= fileBytes
const p = ptyMod.spawn('bash', ['--norc'], { name: 'xterm-256color', cols: 120, rows: 32, cwd: '/tmp', env: process.env });
let received = 0;
let buf = '';
let pausedBytes = 0;
let paused = false;
p.onData((d) => {
received += Buffer.byteLength(d);
if (paused) pausedBytes += Buffer.byteLength(d);
buf = (buf + d).slice(-4000);
});
const results = {};
const t0 = Date.now();
await sleep(500);
p.write('cat /tmp/spike-flood.txt; echo FLOOD-DONE-MARKER\r');
// Après ~2 Mo reçus : pause 10 s
while (received < 2 * 1024 * 1024 && Date.now() - t0 < 60000) await sleep(50);
const beforePause = received;
p.pause(); paused = true;
await sleep(10000);
p.resume(); paused = false;
results.pause = { beforePause, bytesDuringPause: pausedBytes, pauseHeld: pausedBytes < 65536 };
// Attendre la fin du flood
const tFlood = Date.now();
while (!buf.includes('FLOOD-DONE-MARKER') && Date.now() - tFlood < 120000) await sleep(100);
results.flood = {
fileBytes, fileLines, received, receivedAtLeastFile: received >= expectedMin,
markerReceived: buf.includes('FLOOD-DONE-MARKER'),
totalMs: Date.now() - t0,
};
// Écho après flood : write d'un marqueur, mesure du round-trip
await sleep(500);
const echoT0 = process.hrtime.bigint();
p.write('echo ECHO-RT-TEST');
let echoMs = null;
const tEcho = Date.now();
while (Date.now() - tEcho < 5000) {
if (buf.includes('ECHO-RT-TEST')) { echoMs = Number(process.hrtime.bigint() - echoT0) / 1e6; break; }
await sleep(5);
}
results.echo = { echoMs, under100ms: echoMs !== null && echoMs < 100 };
p.kill();
writeFileSync(join(CAPTURES, 'flood-results.json'), JSON.stringify(results, null, 1));
console.log(JSON.stringify(results, null, 1));