'use strict' function meshRejoinJitterMs (guildId, salt = '') { const max = Math.max(0, Number(process.env.PEARCORD_MESH_REJOIN_JITTER_MS) || 900) if (!max) return 0 let h = 2166136261 const key = `${guildId || ''}:${salt}` for (let i = 0; i < key.length; i++) { h ^= key.charCodeAt(i) h = Math.imul(h, 16777619) } return h % max } /** * Score 0–100 for selective mesh sync priority (higher is healthier). * @param {object} row peer seen row * @param {object} opts */ function computeMeshPeerQualityScore (row, opts = {}) { const now = Date.now() const rttMs = Math.max(0, Number(row?.rttMs) || Number(opts.fallbackRttMs) || 120) const staleMs = Math.max(0, now - (Number(row?.lastSeenAt) || 0)) const drops = Math.max(0, Number(row?.dropCount) || 0) let score = 100 score -= Math.min(40, Math.round(rttMs / 20)) score -= Math.min(25, drops * 6) score -= Math.min(22, Math.round(staleMs / 12000)) if (row?.sparseCursorStale) score -= 12 return Math.max(0, Math.min(100, score)) } function rankMeshPeersByQuality (peerMap, opts = {}) { const rows = [] for (const [peerId, row] of peerMap.entries()) { const qualityScore = computeMeshPeerQualityScore(row, opts) rows.push({ peerId, qualityScore, rttMs: Number(row.rttMs) || null, dropCount: Number(row.dropCount) || 0, lastSeenAt: Number(row.lastSeenAt) || 0, sparseCursorStale: !!row.sparseCursorStale }) } rows.sort((a, b) => b.qualityScore - a.qualityScore) return rows } module.exports = { meshRejoinJitterMs, computeMeshPeerQualityScore, rankMeshPeersByQuality }