Fix boot active-server selection and titlebar peer chip
Release rolling / release (push) Successful in 8m49s
Release rolling / release (push) Successful in 8m49s
Stop overwriting the header on every parallel restore connect; wait for the last-used peer before falling back; avoid persisting temporary active selection so the remembered server stays correct across restarts.
This commit is contained in:
+37
-5
@@ -315,20 +315,52 @@ export class ConnectionManager extends EventEmitter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark a connected peer as the UI/RPC active server.
|
||||
* @param {string} id
|
||||
* @param {{ persist?: boolean }} [opts]
|
||||
* persist (default true): write last-active to peers.json / localStorage.
|
||||
* Use persist:false for temporary boot fallback so a faster sibling peer
|
||||
* does not overwrite the user's real last-used server.
|
||||
*/
|
||||
setActive(id) {
|
||||
setActive(id, opts = {}) {
|
||||
const conn = this.connections.get(id)
|
||||
if (!conn) return
|
||||
this.active = conn
|
||||
try {
|
||||
setLastActivePeerId(id)
|
||||
} catch {
|
||||
// ignore persist failures
|
||||
const persist = opts.persist !== false
|
||||
if (persist) {
|
||||
try {
|
||||
setLastActivePeerId(id)
|
||||
} catch {
|
||||
// ignore persist failures
|
||||
}
|
||||
}
|
||||
this.emit('active', conn)
|
||||
}
|
||||
|
||||
/**
|
||||
* Human label for header / fleet: alias when known, else short peer id.
|
||||
* @param {string|null|undefined|{ id?: string, alias?: string|null }} idOrConn
|
||||
* @returns {string}
|
||||
*/
|
||||
resolvePeerLabel(idOrConn) {
|
||||
if (idOrConn == null) return 'peer'
|
||||
const id =
|
||||
typeof idOrConn === 'string'
|
||||
? idOrConn
|
||||
: String(idOrConn.id || idOrConn.publicKeyHex || '').slice(0, 12)
|
||||
if (!id) return 'peer'
|
||||
const live = this.connections.get(id)
|
||||
const recon = this._reconnect.get(id)
|
||||
const alias = String(
|
||||
(typeof idOrConn === 'object' && idOrConn.alias) ||
|
||||
live?.alias ||
|
||||
recon?.alias ||
|
||||
''
|
||||
).trim()
|
||||
if (alias) return alias
|
||||
return `Peer ${String(id).slice(0, 6)}…`
|
||||
}
|
||||
|
||||
/**
|
||||
* Close a live connection.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Active-server selection helpers (boot restore / peer switch).
|
||||
* Pure functions — safe for unit tests without DOM or DHT.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Loose id match: equal, or either is a prefix of the other (12-char vs longer).
|
||||
* @param {string} a
|
||||
* @param {string} b
|
||||
*/
|
||||
export function topicIdsMatch(a, b) {
|
||||
if (!a || !b) return false
|
||||
const x = String(a)
|
||||
const y = String(b)
|
||||
return x === y || x.startsWith(y) || y.startsWith(x)
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer last-known active peer if connected; otherwise first connected in list order.
|
||||
* @param {string|null|undefined} lastActiveId
|
||||
* @param {string[]} orderedKeys
|
||||
* @param {Record<string, { peer?: { connected?: boolean, id?: string }|null }>} table
|
||||
* @returns {string|null}
|
||||
*/
|
||||
export function pickPreferredActivePeer(lastActiveId, orderedKeys, table = {}) {
|
||||
const keys = Array.isArray(orderedKeys) ? orderedKeys : []
|
||||
if (lastActiveId) {
|
||||
const match = keys.find(
|
||||
(k) => topicIdsMatch(k, lastActiveId) && table[k]?.peer?.connected
|
||||
)
|
||||
if (match) return match
|
||||
for (const k of keys) {
|
||||
const peer = table[k]?.peer
|
||||
if (peer?.connected && topicIdsMatch(peer.id, lastActiveId)) return k
|
||||
}
|
||||
}
|
||||
const firstLive = keys.find((k) => table[k]?.peer?.connected)
|
||||
return firstLive || null
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort peer ids so last-active is first (stable for the rest).
|
||||
* @param {string[]} keys
|
||||
* @param {string|null|undefined} lastActiveId
|
||||
* @returns {string[]}
|
||||
*/
|
||||
export function orderPeersForBoot(keys, lastActiveId) {
|
||||
const list = [...(keys || [])]
|
||||
if (!lastActiveId) return list
|
||||
return list.sort((a, b) => {
|
||||
if (topicIdsMatch(a, lastActiveId)) return -1
|
||||
if (topicIdsMatch(b, lastActiveId)) return 1
|
||||
return 0
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user