Squashed 'cms/core/' content from commit 59b9e20
git-subtree-dir: cms/core git-subtree-split: 59b9e2075ac48cf017db38009d54dbe56a98fffc
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
// Serialisiert asynchrone Aufgaben je `key` und koalesziert Wartende:
|
||||
// - Es läuft nie mehr als eine Aufgabe pro Key gleichzeitig.
|
||||
// - Kommen während eines Laufs weitere Aufrufe rein, wird GENAU EIN weiterer
|
||||
// Durchlauf nachgelagert (egal wie viele warten) — sie teilen sich dessen
|
||||
// Ergebnis. So sehen alle den jüngsten Stand, ohne einen Lauf-Sturm.
|
||||
//
|
||||
// Einsatz: teure, idempotente Vorgänge wie der Hugo-Build (siehe hugo.js).
|
||||
const state = new Map();
|
||||
|
||||
export function coalesce(key, fn) {
|
||||
let s = state.get(key);
|
||||
if (!s) { s = { running: false, rerun: false, fn, waiters: [] }; state.set(key, s); }
|
||||
s.fn = fn; // jüngste Variante gewinnt für den nächsten Lauf
|
||||
return new Promise((resolve, reject) => {
|
||||
s.waiters.push({ resolve, reject });
|
||||
if (!s.running) drain(key);
|
||||
else s.rerun = true;
|
||||
});
|
||||
}
|
||||
|
||||
async function drain(key) {
|
||||
const s = state.get(key);
|
||||
s.running = true;
|
||||
try {
|
||||
do {
|
||||
s.rerun = false;
|
||||
const waiters = s.waiters;
|
||||
s.waiters = [];
|
||||
try {
|
||||
const r = await s.fn();
|
||||
waiters.forEach((w) => w.resolve(r));
|
||||
} catch (e) {
|
||||
waiters.forEach((w) => w.reject(e));
|
||||
}
|
||||
} while (s.rerun);
|
||||
} finally {
|
||||
s.running = false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user