Merge pull request #289 from PR0M3TH3AN/optimize-relay-ranking-1239301882622685923

⚡ Optimize relay ranking with caching
This commit is contained in:
thePR0M3TH3AN authored and GitHub committed 2026-02-17 22:45:08 -05:00
commit b6775cda28
3 files changed
+176 -18

No files matched your search

+64 -18
View File
@@ -205,6 +205,8 @@ export class RelayHealthManager {
constructor() {
this.metricsByRelay = new Map();
this.lastSnapshotAt = 0;
this._metricsVersion = 0;
this._sortedCache = null;
}
ensureMetrics(relay, config) {
@@ -220,31 +222,72 @@ export class RelayHealthManager {
lastResultAt: null,
};
this.metricsByRelay.set(relay, metrics);
this._metricsVersion += 1;
}
return metrics;
}
rankRelays(relays, config, nowMs = Date.now()) {
const summaries = relays.map((relay) => {
const metrics = this.ensureMetrics(relay, config);
const summary = summarizeRelayMetrics(metrics, nowMs);
return {
relay,
summary,
score: computeRelayScore(summary),
};
});
for (const relay of relays) {
this.ensureMetrics(relay, config);
}
return summaries.sort((a, b) => {
if (b.score !== a.score) return b.score - a.score;
if (a.summary.quarantined !== b.summary.quarantined) return a.summary.quarantined ? 1 : -1;
if (a.summary.averageLatencyMs !== b.summary.averageLatencyMs) {
if (a.summary.averageLatencyMs === null) return 1;
if (b.summary.averageLatencyMs === null) return -1;
return a.summary.averageLatencyMs - b.summary.averageLatencyMs;
if (
!this._sortedCache
|| this._sortedCache.version !== this._metricsVersion
|| nowMs >= this._sortedCache.validUntil
) {
let minQuarantineUntil = Infinity;
const entries = [];
for (const metrics of this.metricsByRelay.values()) {
const summary = summarizeRelayMetrics(metrics, nowMs);
const score = computeRelayScore(summary);
if (metrics.quarantineUntil > nowMs && metrics.quarantineUntil < minQuarantineUntil) {
minQuarantineUntil = metrics.quarantineUntil;
}
entries.push({
relay: metrics.relay,
summary,
score,
metrics,
});
}
return a.relay.localeCompare(b.relay);
});
entries.sort((a, b) => {
if (b.score !== a.score) return b.score - a.score;
if (a.summary.quarantined !== b.summary.quarantined) return a.summary.quarantined ? 1 : -1;
if (a.summary.averageLatencyMs !== b.summary.averageLatencyMs) {
if (a.summary.averageLatencyMs === null) return 1;
if (b.summary.averageLatencyMs === null) return -1;
return a.summary.averageLatencyMs - b.summary.averageLatencyMs;
}
return a.relay.localeCompare(b.relay);
});
this._sortedCache = {
version: this._metricsVersion,
validUntil: minQuarantineUntil,
entries,
};
}
const requestedSet = new Set(relays);
return this._sortedCache.entries
.filter((entry) => requestedSet.has(entry.relay))
.map((entry) => {
const quarantineRemainingMs = entry.metrics.quarantineUntil > nowMs
? entry.metrics.quarantineUntil - nowMs
: 0;
return {
relay: entry.relay,
score: entry.score,
summary: {
...entry.summary,
quarantineRemainingMs,
},
};
});
}
prioritizeRelays(relays, config, nowMs = Date.now()) {
@@ -292,6 +335,7 @@ export class RelayHealthManager {
metrics.quarantineUntil = nowMs + metrics.cooldownMs;
metrics.cooldownMs = Math.min(config.maxQuarantineCooldownMs, Math.floor(metrics.cooldownMs * 1.5));
}
this._metricsVersion += 1;
}
collectSnapshot(relays, config, nowMs = Date.now()) {
@@ -317,6 +361,8 @@ export class RelayHealthManager {
reset() {
this.metricsByRelay.clear();
this.lastSnapshotAt = 0;
this._metricsVersion = 0;
this._sortedCache = null;
}
}