[Init] Initial commit - NetMesh terminal manager
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
This commit is contained in:
161
electron/bridges/tcpConnectLatency.cjs
Normal file
161
electron/bridges/tcpConnectLatency.cjs
Normal file
@@ -0,0 +1,161 @@
|
||||
"use strict";
|
||||
|
||||
const dns = require("node:dns");
|
||||
|
||||
const DEFAULT_TIMEOUT_MS = 3000;
|
||||
const DEFAULT_CACHE_TTL_MS = 30000;
|
||||
const DEFAULT_FAILURE_CACHE_TTL_MS = 5000;
|
||||
const MAX_CACHE_ENTRIES = 256;
|
||||
const MAX_CONCURRENT_PROBES = 8;
|
||||
const MAX_QUEUED_PROBES = 64;
|
||||
|
||||
function createTcpConnectLatencyProbe({
|
||||
net,
|
||||
lookup = dns.lookup,
|
||||
now = () => performance.now(),
|
||||
cacheNow = () => Date.now(),
|
||||
cacheTtlMs = DEFAULT_CACHE_TTL_MS,
|
||||
failureCacheTtlMs = DEFAULT_FAILURE_CACHE_TTL_MS,
|
||||
maxCacheEntries = MAX_CACHE_ENTRIES,
|
||||
maxConcurrentProbes = MAX_CONCURRENT_PROBES,
|
||||
maxQueuedProbes = MAX_QUEUED_PROBES,
|
||||
setTimer = setTimeout,
|
||||
clearTimer = clearTimeout,
|
||||
}) {
|
||||
const resultCache = new Map();
|
||||
const inFlight = new Map();
|
||||
const queue = [];
|
||||
let activeProbeCount = 0;
|
||||
const concurrentLimit = Math.max(1, Math.floor(maxConcurrentProbes));
|
||||
const queueLimit = Math.max(0, Math.floor(maxQueuedProbes));
|
||||
|
||||
function runProbe({ hostname, port, timeoutMs }) {
|
||||
return new Promise((resolve) => {
|
||||
let startedAt = net.isIP?.(hostname) ? now() : null;
|
||||
let settled = false;
|
||||
let socket = null;
|
||||
|
||||
const finish = (latencyMs) => {
|
||||
if (settled) return;
|
||||
settled = true;
|
||||
try { socket?.destroy(); } catch { /* best-effort cleanup */ }
|
||||
resolve(latencyMs);
|
||||
};
|
||||
|
||||
try {
|
||||
const connectOptions = { host: hostname, port };
|
||||
if (startedAt === null) {
|
||||
connectOptions.lookup = (host, options, callback) => {
|
||||
lookup(host, options, (err, address, family) => {
|
||||
startedAt = now();
|
||||
callback(err, address, family);
|
||||
});
|
||||
};
|
||||
}
|
||||
socket = net.createConnection(connectOptions, () => {
|
||||
const connectedAt = now();
|
||||
finish(Math.max(0, Math.round(connectedAt - (startedAt ?? connectedAt))));
|
||||
});
|
||||
socket.once("error", () => finish(null));
|
||||
socket.setTimeout(timeoutMs, () => finish(null));
|
||||
} catch {
|
||||
finish(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function startScheduledProbe(task) {
|
||||
activeProbeCount += 1;
|
||||
let result;
|
||||
try {
|
||||
result = Promise.resolve(task());
|
||||
} catch (err) {
|
||||
result = Promise.reject(err);
|
||||
}
|
||||
return result.finally(() => {
|
||||
activeProbeCount -= 1;
|
||||
while (activeProbeCount < concurrentLimit && queue.length > 0) {
|
||||
const next = queue.shift();
|
||||
clearTimer(next.timer);
|
||||
const remainingMs = next.deadline - cacheNow();
|
||||
if (remainingMs <= 0) {
|
||||
next.resolve(null);
|
||||
continue;
|
||||
}
|
||||
startScheduledProbe(() => next.task(remainingMs)).then(next.resolve, next.reject);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function scheduleProbe(task, timeoutMs) {
|
||||
if (activeProbeCount < concurrentLimit) return startScheduledProbe(() => task(timeoutMs));
|
||||
if (queue.length >= queueLimit) return Promise.resolve(null);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const entry = {
|
||||
task,
|
||||
resolve,
|
||||
reject,
|
||||
deadline: cacheNow() + timeoutMs,
|
||||
timer: null,
|
||||
};
|
||||
entry.timer = setTimer(() => {
|
||||
const index = queue.indexOf(entry);
|
||||
if (index >= 0) queue.splice(index, 1);
|
||||
resolve(null);
|
||||
}, timeoutMs);
|
||||
queue.push(entry);
|
||||
});
|
||||
}
|
||||
|
||||
function cacheResult(key, value) {
|
||||
resultCache.delete(key);
|
||||
resultCache.set(key, {
|
||||
value,
|
||||
expiresAt: cacheNow() + (value === null ? failureCacheTtlMs : cacheTtlMs),
|
||||
});
|
||||
while (resultCache.size > maxCacheEntries) {
|
||||
resultCache.delete(resultCache.keys().next().value);
|
||||
}
|
||||
}
|
||||
|
||||
return function measureTcpConnectLatency({ hostname, port, timeoutMs = DEFAULT_TIMEOUT_MS }) {
|
||||
if (!hostname || !Number.isInteger(port) || port < 1 || port > 65535) {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
const key = `${String(hostname).toLowerCase()}\u0000${port}`;
|
||||
const pending = inFlight.get(key);
|
||||
if (pending) return pending;
|
||||
|
||||
const cached = resultCache.get(key);
|
||||
const checkedAt = cacheNow();
|
||||
if (cached && cached.expiresAt > checkedAt) {
|
||||
resultCache.delete(key);
|
||||
resultCache.set(key, cached);
|
||||
return Promise.resolve(cached.value);
|
||||
}
|
||||
resultCache.delete(key);
|
||||
|
||||
const promise = scheduleProbe(
|
||||
(remainingMs) => runProbe({ hostname, port, timeoutMs: remainingMs }),
|
||||
timeoutMs,
|
||||
)
|
||||
.catch(() => null)
|
||||
.then((value) => {
|
||||
inFlight.delete(key);
|
||||
cacheResult(key, value);
|
||||
return value;
|
||||
});
|
||||
inFlight.set(key, promise);
|
||||
return promise;
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createTcpConnectLatencyProbe,
|
||||
DEFAULT_TIMEOUT_MS,
|
||||
DEFAULT_CACHE_TTL_MS,
|
||||
MAX_CONCURRENT_PROBES,
|
||||
MAX_QUEUED_PROBES,
|
||||
};
|
||||
Reference in New Issue
Block a user