import http from 'k6/http'; import { check, sleep } from 'k6'; import encoding from 'k6/encoding'; /** * ST-COUNT-01 — Lotes concurrentes hacia count-api vía gateway. * En host compartido 8GiB: usar PROFILE=shared8g y liberar MLflow/Airflow antes. * * k6 run -e PROFILE=shared8g k6_count_batches.js */ const PROFILE = __ENV.PROFILE || 'shared8g'; const BASE_URL = __ENV.BASE_URL || 'http://127.0.0.1:8189'; const profiles = { shared8g: { rate: 1, duration: '1m', preAllocatedVUs: 2, maxVUs: 5, }, lab: { rate: 5, duration: '2m', preAllocatedVUs: 10, maxVUs: 20, }, }; const cfg = profiles[PROFILE] || profiles.shared8g; export const options = { scenarios: { batches: { executor: 'constant-arrival-rate', rate: cfg.rate, timeUnit: '1s', duration: cfg.duration, preAllocatedVUs: cfg.preAllocatedVUs, maxVUs: cfg.maxVUs, }, }, thresholds: { http_req_duration: ['p(95)<60000'], checks: ['rate>0.85'], }, tags: { profile: PROFILE }, }; const tinyPdf = encoding.b64decode( 'JVBERi0xLjAKMSAwIG9iago8PAovVHlwZSAvQ2F0YWxvZwovUGFnZXMgMiAwIFIKPj4KZW5kb2JqCjIgMCBvYmoKPDwKL1R5cGUgL1BhZ2VzCi9LaWRzIFszIDAgUl0KL0NvdW50IDEKPD4KZW5kb2JqCjMgMCBvYmoKPDwKL1R5cGUgL1BhZ2UKL1BhcmVudCAyIDAgUgovTWVkaWFCb3ggWzAgMCAzMDAgMTQ0XQo+PgplbmRvYmoKeHJlZgowIDQKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwMDA5IDAwMDAwIG4gCjAwMDAwMDAwNjMgMDAwMDAgbiAKMDAwMDAwMDEyNCAwMDAwMCBuIAp0cmFpbGVyCjw8Ci9TaXplIDQKL1Jvb3QgMSAwIFIKPj4Kc3RhcnR4cmVmCjIwMQolJUVPRgo=', ); export default function () { const bin = __ENV.PDF_B64 ? encoding.b64decode(__ENV.PDF_B64) : tinyPdf; // count-api espera el campo multipart "files" (puede ser múltiple). const data = { files: http.file(bin, 'sample.pdf', 'application/pdf'), }; const res = http.post(`${BASE_URL}/count/v1/count`, data); check(res, { 'status 2xx': (r) => r.status >= 200 && r.status < 300, 'not 5xx': (r) => r.status < 500, }); sleep(0.1); }