Improve health probe prioritization

This commit is contained in:
thePR0M3TH3AN committed 2025-09-27 13:49:45 -04:00
1 parent 854216f331
commit 1985b16064
1 file changed
+91 -48
+91 -48
View File
@@ -110,7 +110,7 @@ function normalizeResult(result) {
};
}
function queueProbe(magnet, cacheKey) {
function queueProbe(magnet, cacheKey, priority = 0) {
if (!magnet) {
return Promise.resolve(null);
}
@@ -125,21 +125,23 @@ function queueProbe(magnet, cacheKey) {
}
const job = probeQueue
.run(() =>
torrentClient
.probePeers(magnet, {
timeoutMs: PROBE_TIMEOUT_MS,
maxWebConns: 2,
polls: PROBE_POLL_COUNT,
})
.catch((err) => ({
healthy: false,
peers: 0,
reason: "error",
error: err,
appendedTrackers: false,
hasProbeTrackers: false,
}))
.run(
() =>
torrentClient
.probePeers(magnet, {
timeoutMs: PROBE_TIMEOUT_MS,
maxWebConns: 2,
polls: PROBE_POLL_COUNT,
})
.catch((err) => ({
healthy: false,
peers: 0,
reason: "error",
error: err,
appendedTrackers: false,
hasProbeTrackers: false,
})),
priority
)
.then((result) => {
const normalized = normalizeResult(result);
@@ -173,13 +175,35 @@ class ProbeQueue {
this.queue = [];
}
run(task) {
run(task, priority = 0) {
return new Promise((resolve, reject) => {
this.queue.push({ task, resolve, reject });
const normalizedPriority = Number.isFinite(priority) ? priority : 0;
const job = {
task,
resolve,
reject,
priority: normalizedPriority,
};
this.enqueue(job);
this.drain();
});
}
enqueue(job) {
if (!this.queue.length) {
this.queue.push(job);
return;
}
const index = this.queue.findIndex(
(existing) => existing.priority < job.priority
);
if (index === -1) {
this.queue.push(job);
} else {
this.queue.splice(index, 0, job);
}
}
drain() {
if (this.running >= this.max) {
return;
@@ -233,36 +257,16 @@ function ensureState(container) {
const pendingByCard = new WeakMap();
const observedCards = new WeakSet();
state = { observer: null, pendingByCard, observedCards };
const observer = new IntersectionObserver(
(entries) => {
const viewportCenter = getViewportCenter();
const prioritized = entries
.filter((entry) => entry.isIntersecting && entry.target instanceof HTMLElement)
.map((entry) => ({
entry,
ratio:
typeof entry.intersectionRatio === "number"
? entry.intersectionRatio
: 0,
distance: calculateDistanceSquared(entry, viewportCenter),
}))
.sort((a, b) => {
if (b.ratio !== a.ratio) {
return b.ratio - a.ratio;
}
return a.distance - b.distance;
});
prioritized.forEach(({ entry }) => {
const card = entry.target;
handleCardVisible({ card, pendingByCard });
});
processObserverEntries(entries, state);
},
{ root: null, rootMargin: ROOT_MARGIN, threshold: 0.01 }
);
state = { observer, pendingByCard, observedCards };
state.observer = observer;
containerState.set(container, state);
return state;
}
@@ -297,6 +301,47 @@ function calculateDistanceSquared(entry, viewportCenter) {
return dx * dx + dy * dy;
}
function computeVisibilityPriority({ ratio, distance }) {
const normalizedRatio = Number.isFinite(ratio)
? Math.min(Math.max(ratio, 0), 1)
: 0;
const distanceScore = Number.isFinite(distance) ? 1 / (1 + distance) : 0;
return normalizedRatio * 1000 + distanceScore;
}
function prioritizeEntries(entries, viewportCenter) {
if (!Array.isArray(entries) || entries.length === 0) {
return [];
}
return entries
.filter((entry) => entry.isIntersecting && entry.target instanceof HTMLElement)
.map((entry) => {
const ratio =
typeof entry.intersectionRatio === "number" ? entry.intersectionRatio : 0;
const distance = calculateDistanceSquared(entry, viewportCenter);
const priority = computeVisibilityPriority({ ratio, distance });
return { entry, ratio, distance, priority };
})
.sort((a, b) => {
if (b.priority !== a.priority) {
return b.priority - a.priority;
}
return a.distance - b.distance;
});
}
function processObserverEntries(entries, state) {
if (!state || !entries || entries.length === 0) {
return;
}
const viewportCenter = getViewportCenter();
const prioritized = prioritizeEntries(entries, viewportCenter);
prioritized.forEach(({ entry, priority }) => {
const card = entry.target;
handleCardVisible({ card, pendingByCard: state.pendingByCard, priority });
});
}
function getIntersectionRect(entry) {
if (!entry) {
return null;
@@ -395,7 +440,7 @@ function setBadge(card, state, details) {
}
}
function handleCardVisible({ card, pendingByCard }) {
function handleCardVisible({ card, pendingByCard, priority = 0 }) {
if (!(card instanceof HTMLElement)) {
return;
}
@@ -428,7 +473,7 @@ function handleCardVisible({ card, pendingByCard }) {
setBadge(card, "checking");
const probePromise = queueProbe(magnet, infoHash);
const probePromise = queueProbe(magnet, infoHash, priority);
pendingByCard.set(card, probePromise);
@@ -481,6 +526,7 @@ export function attachHealthBadges(container) {
setBadge(card, "unknown");
}
});
processObserverEntries(state.observer.takeRecords(), state);
}
export function refreshHealthBadges(container) {
@@ -491,9 +537,6 @@ export function refreshHealthBadges(container) {
if (!state) {
return;
}
state.observer.takeRecords().forEach((entry) => {
if (entry.isIntersecting) {
handleCardVisible({ card: entry.target, pendingByCard: state.pendingByCard });
}
});
const records = state.observer.takeRecords();
processObserverEntries(records, state);
}