feat(NetworkMapDashboard): implement runWithOnePerKey function to ensure single task execution per node during speed tests
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 2m0s
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 2m0s
This commit is contained in:
@@ -25,6 +25,46 @@ async function runWithLimit(tasks, limit = 4) {
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Выполняет задачи так, что на каждый ключ (ноду) в один момент времени
|
||||||
|
* выполняется не более одной задачи. Разные ноды — параллельно.
|
||||||
|
* getKey(i) возвращает ключ для задачи с индексом i.
|
||||||
|
*/
|
||||||
|
async function runWithOnePerKey(tasks, getKey) {
|
||||||
|
const n = tasks.length;
|
||||||
|
const keyToIndices = new Map();
|
||||||
|
for (let i = 0; i < n; i++) {
|
||||||
|
const k = String(getKey(i));
|
||||||
|
if (!keyToIndices.has(k)) keyToIndices.set(k, []);
|
||||||
|
keyToIndices.get(k).push(i);
|
||||||
|
}
|
||||||
|
const results = [];
|
||||||
|
for (let i = 0; i < n; i++) results[i] = null;
|
||||||
|
|
||||||
|
const keys = Array.from(keyToIndices.keys());
|
||||||
|
let round = 0;
|
||||||
|
while (true) {
|
||||||
|
const batch = [];
|
||||||
|
for (const k of keys) {
|
||||||
|
const indices = keyToIndices.get(k);
|
||||||
|
if (round < indices.length) batch.push(indices[round]);
|
||||||
|
}
|
||||||
|
if (batch.length === 0) break;
|
||||||
|
await Promise.all(
|
||||||
|
batch.map(async (i) => {
|
||||||
|
try {
|
||||||
|
const value = await tasks[i]();
|
||||||
|
results[i] = { value };
|
||||||
|
} catch (err) {
|
||||||
|
results[i] = { error: err };
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
round++;
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
export default function NetworkMapDashboard() {
|
export default function NetworkMapDashboard() {
|
||||||
const [servers, setServers] = useState([]);
|
const [servers, setServers] = useState([]);
|
||||||
const [connections, setConnections] = useState([]);
|
const [connections, setConnections] = useState([]);
|
||||||
@@ -222,7 +262,8 @@ export default function NetworkMapDashboard() {
|
|||||||
setSpeedMap((prev) => ({ ...prev, [key]: null }));
|
setSpeedMap((prev) => ({ ...prev, [key]: null }));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
await runWithLimit(tasks, 2);
|
// На каждой ноде (speedTestServerId) в один момент — только один тест, чтобы не делить канал
|
||||||
|
await runWithOnePerKey(tasks, (i) => withSpeed[i].speedTestServerId);
|
||||||
if (speedAbortRef.current) return;
|
if (speedAbortRef.current) return;
|
||||||
setSpeedLoading(false);
|
setSpeedLoading(false);
|
||||||
}, [connections]);
|
}, [connections]);
|
||||||
|
|||||||
Reference in New Issue
Block a user