mirror of
https://github.com/R0m1k3/CollectFlow.git
synced 2026-10-11 17:26:32 +02:00
Merge branch 'claude/exciting-goldberg-wILkj' into main
perf(qlik): chemin rapide select-all pour la sync Qlik derrière le flag QLIK_SELECT_ALL_CODES (repli auto sur le chemin par lots en cas de code 15).
This commit is contained in:
1 file changed
+76
-2
@@ -96,7 +96,11 @@ export async function fetchNetworkMetricsPlaywright(
|
|||||||
const qlikArticleBatchSize = envNumber("QLIK_ARTICLE_BATCH_SIZE", 150, 1, 500);
|
const qlikArticleBatchSize = envNumber("QLIK_ARTICLE_BATCH_SIZE", 150, 1, 500);
|
||||||
const csvFallbacks = envNumberCsv("QLIK_ARTICLE_BATCH_FALLBACKS", 1, 500);
|
const csvFallbacks = envNumberCsv("QLIK_ARTICLE_BATCH_FALLBACKS", 1, 500);
|
||||||
const qlikArticleBatchFallbacks = uniqueOrdered([qlikArticleBatchSize, ...(csvFallbacks.length ? csvFallbacks : [75, 50]), 75, 50]);
|
const qlikArticleBatchFallbacks = uniqueOrdered([qlikArticleBatchSize, ...(csvFallbacks.length ? csvFallbacks : [75, 50]), 75, 50]);
|
||||||
console.log(`[qlik-pw] tuning settle=${qlikSettleMs}ms code15Attempts=${qlikCode15MaxAttempts} batchFallbacks=${qlikArticleBatchFallbacks.join(">")}`);
|
// Chemin rapide : sélectionner TOUS les Article Code une seule fois, puis ne
|
||||||
|
// changer que la Date par mois (au lieu de re-sélectionner par lots de 150 chaque
|
||||||
|
// mois). Repli automatique sur le chemin par lots en cas de code 15.
|
||||||
|
const qlikSelectAllCodes = ["1", "true", "yes", "on"].includes((process.env.QLIK_SELECT_ALL_CODES ?? "").trim().toLowerCase());
|
||||||
|
console.log(`[qlik-pw] tuning settle=${qlikSettleMs}ms code15Attempts=${qlikCode15MaxAttempts} batchFallbacks=${qlikArticleBatchFallbacks.join(">")} selectAllCodes=${qlikSelectAllCodes}`);
|
||||||
|
|
||||||
const browser = await getBrowser();
|
const browser = await getBrowser();
|
||||||
console.log(`[qlik-pw] chromium lancé`);
|
console.log(`[qlik-pw] chromium lancé`);
|
||||||
@@ -137,7 +141,7 @@ export async function fetchNetworkMetricsPlaywright(
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
const result = (await page.evaluate(
|
const result = (await page.evaluate(
|
||||||
({ app, dim, mca, mqte, mnb, mcamag, mmarge, codes, token, monthlyPayload, noDateMode, qlikSettleMs, qlikCode15MaxAttempts, qlikArticleBatchFallbacks }: {
|
({ app, dim, mca, mqte, mnb, mcamag, mmarge, codes, token, monthlyPayload, noDateMode, qlikSettleMs, qlikCode15MaxAttempts, qlikArticleBatchFallbacks, selectAllCodes }: {
|
||||||
app: string; dim: string; mca: string; mqte: string; mnb: string; mcamag: string; mmarge: string;
|
app: string; dim: string; mca: string; mqte: string; mnb: string; mcamag: string; mmarge: string;
|
||||||
codes: string[]; token: string;
|
codes: string[]; token: string;
|
||||||
monthlyPayload: Array<{ label: string; dateDebut: string; dateFin: string; serials: number[] }>;
|
monthlyPayload: Array<{ label: string; dateDebut: string; dateFin: string; serials: number[] }>;
|
||||||
@@ -145,6 +149,7 @@ export async function fetchNetworkMetricsPlaywright(
|
|||||||
qlikSettleMs: number;
|
qlikSettleMs: number;
|
||||||
qlikCode15MaxAttempts: number;
|
qlikCode15MaxAttempts: number;
|
||||||
qlikArticleBatchFallbacks: number[];
|
qlikArticleBatchFallbacks: number[];
|
||||||
|
selectAllCodes: boolean;
|
||||||
}) =>
|
}) =>
|
||||||
new Promise<InPageResult>((resolve) => {
|
new Promise<InPageResult>((resolve) => {
|
||||||
const loc = (window as unknown as { location: Location }).location;
|
const loc = (window as unknown as { location: Location }).location;
|
||||||
@@ -320,6 +325,71 @@ export async function fetchNetworkMetricsPlaywright(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Chemin rapide (flag QLIK_SELECT_ALL_CODES) : sélectionne TOUS les
|
||||||
|
// Article Code une seule fois, puis n'itère que la sélection Date par
|
||||||
|
// mois avec UN cube paginé (au lieu de re-sélectionner les codes par lots
|
||||||
|
// de 150 à chaque mois — la SelectValues répétée coûte ~22 s × 120).
|
||||||
|
// Renvoie true si le mois complet a réussi ; false si repli code 15 (les
|
||||||
|
// résultats partiels et sélections sont réinitialisés avant le chemin par lots).
|
||||||
|
const trySelectAllCodesPath = async (): Promise<boolean> => {
|
||||||
|
const savedLen = out.length;
|
||||||
|
try {
|
||||||
|
if (codes.length && fh !== -1) {
|
||||||
|
await timed("clearCodeAll", "Clear", () => rpc("Clear", {}, fh), {});
|
||||||
|
await sleep(qlikSettleMs);
|
||||||
|
const { value: sel } = await timed("selectCodeAll", "SelectValues", () => rpc("SelectValues", {
|
||||||
|
qFieldValues: codes.map((c) => ({ qText: c })),
|
||||||
|
qToggleMode: false,
|
||||||
|
qSoftLock: true,
|
||||||
|
}, fh), {});
|
||||||
|
console.log("[qlik-pw] select-all — SelectValues Article Code (" + codes.length + " codes) → " + JSON.stringify(sel.qReturn));
|
||||||
|
await sleep(qlikSettleMs);
|
||||||
|
}
|
||||||
|
const total = monthlyPayload.length;
|
||||||
|
console.log("[qlik-pw] chemin rapide select-all — " + total + " mois, 1 sélection Article Code globale");
|
||||||
|
for (let mi = 0; mi < total; mi++) {
|
||||||
|
const m = monthlyPayload[mi];
|
||||||
|
const prefix = "[qlik-pw] (rapide) mois " + (mi + 1) + "/" + total + " " + m.label + " (" + m.dateDebut + "→" + m.dateFin + ", " + m.serials.length + "j)";
|
||||||
|
const monthStart = nowMs();
|
||||||
|
const monthTimings: Record<string, number> = {};
|
||||||
|
aggMonths = mi + 1;
|
||||||
|
let code15Retries = 0;
|
||||||
|
// Sélection Date du mois uniquement (la sélection Article Code reste active).
|
||||||
|
const { value: dsel } = await timed("selectDate", "SelectValues", () => rpc("SelectValues", {
|
||||||
|
qFieldValues: m.serials.map((s) => ({ qNum: s, qText: String(s) })),
|
||||||
|
qToggleMode: false,
|
||||||
|
qSoftLock: true,
|
||||||
|
}, dfh), monthTimings);
|
||||||
|
console.log(prefix + " — SelectValues Date " + m.serials.length + " serials → " + JSON.stringify(dsel.qReturn));
|
||||||
|
await sleep(qlikSettleMs);
|
||||||
|
// Un seul cube paginé pour tous les articles du mois.
|
||||||
|
const batchRows: Array<Array<string | number>> = [];
|
||||||
|
const { value: got, ms } = await timed("cube", "batch", () => fetchCubeForSelection(batchRows, monthTimings, () => { code15Retries++; }), monthTimings);
|
||||||
|
out.push(...batchRows);
|
||||||
|
aggBatches++;
|
||||||
|
aggCode15Retries += code15Retries;
|
||||||
|
console.log("[qlik-pw][timing] " + prefix + " — rows=" + got + " cumul=" + out.length + " ms=" + ms + " retries15=" + code15Retries + " timings=" + timingSummary(monthTimings));
|
||||||
|
// Clear Date uniquement — on garde la sélection Article Code pour le mois suivant.
|
||||||
|
if (mi < total - 1) {
|
||||||
|
try { await timed("clearDate", "Clear", () => rpc("Clear", {}, dfh), monthTimings); }
|
||||||
|
catch (e) { console.log(prefix + " — Clear Date ignoré: " + String((e as Error)?.message || e)); }
|
||||||
|
}
|
||||||
|
console.log("[qlik-pw][timing] " + prefix + " — done ms=" + Math.round(nowMs() - monthStart) + " timings=" + timingSummary(monthTimings));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
if (isEngineCode15(e)) {
|
||||||
|
console.log("[qlik-pw] chemin rapide échoué (code 15) → repli sur le chemin par lots");
|
||||||
|
out.length = savedLen;
|
||||||
|
aggMonths = 0; aggBatches = 0; aggCode15Retries = 0;
|
||||||
|
try { await rpc("Clear", {}, dfh); if (fh !== -1) await rpc("Clear", {}, fh); } catch { /* noop */ }
|
||||||
|
await sleep(qlikSettleMs);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (noDateMode) {
|
if (noDateMode) {
|
||||||
// Aucun filtre Date : extraction en un seul appel (tous les codes d'un coup).
|
// Aucun filtre Date : extraction en un seul appel (tous les codes d'un coup).
|
||||||
// On sélectionne uniquement Article Code ; Date reste libre.
|
// On sélectionne uniquement Article Code ; Date reste libre.
|
||||||
@@ -337,6 +407,9 @@ export async function fetchNetworkMetricsPlaywright(
|
|||||||
aggBatches = 1;
|
aggBatches = 1;
|
||||||
aggCode15Retries = code15Retries;
|
aggCode15Retries = code15Retries;
|
||||||
console.log("[qlik-pw][timing] noDate rows=" + got + " cumul=" + out.length + " ms=" + ms + " retries15=" + code15Retries + " timings=" + timingSummary(timings));
|
console.log("[qlik-pw][timing] noDate rows=" + got + " cumul=" + out.length + " ms=" + ms + " retries15=" + code15Retries + " timings=" + timingSummary(timings));
|
||||||
|
} else if (selectAllCodes && (await trySelectAllCodesPath())) {
|
||||||
|
// Chemin rapide terminé avec succès (voir trySelectAllCodesPath).
|
||||||
|
// Si false (repli code 15), on tombe dans le chemin par lots ci-dessous.
|
||||||
} else {
|
} else {
|
||||||
// Itération par mois × lots de codes : pour chaque mois, SelectValues Date
|
// Itération par mois × lots de codes : pour chaque mois, SelectValues Date
|
||||||
// (~30 serials), puis SelectValues Article Code par petits lots. Le cube
|
// (~30 serials), puis SelectValues Article Code par petits lots. Le cube
|
||||||
@@ -454,6 +527,7 @@ export async function fetchNetworkMetricsPlaywright(
|
|||||||
qlikSettleMs,
|
qlikSettleMs,
|
||||||
qlikCode15MaxAttempts,
|
qlikCode15MaxAttempts,
|
||||||
qlikArticleBatchFallbacks,
|
qlikArticleBatchFallbacks,
|
||||||
|
selectAllCodes: qlikSelectAllCodes,
|
||||||
},
|
},
|
||||||
)) as InPageResult;
|
)) as InPageResult;
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user